VB.NET (Два столбца Excel ›Условные поля со списком)

Я ищу почти два часа, чтобы найти решение по следующему вопросу. В Excel у меня есть два столбца (один столбец для основных записей и один столбец для подчиненных записей). По сути, в Combobox1 я хочу заполнить все основные записи. Если выбран MasterRecord A, я хочу, чтобы Combobox2 показывал мне только SlaveRecords, принадлежащие A, а не другие записи, принадлежащие другим Master Records.

введите описание изображения здесь

Я добавил Interop Assembly и открыл Excel (соединение уже есть). Ваша помощь очень ценится!

Private Sub Combobox2_Populate()
    'Start Excel Script to populate ComboBox2
    Dim excel As Application = New Application
    Dim w As Workbook = excel.Workbooks.Open(Filename:=databasestatus, [ReadOnly]:=True)
    Dim sheet As Worksheet = w.Sheets("AIR_NL_1")
    Dim StartRow As Integer
    Dim TotalRows As Integer
    ComboBox2.Items.Clear()
    sheet.UsedRange.AutoFilter(Field:=9, Criteria1:=ComboBox1.SelectedItem, Operator:=XlAutoFilterOperator.xlFilterValues)
    TotalRows = sheet.Range("A1").CurrentRegion.Rows.Count
    For StartRow = 3 To TotalRows
        If XlCellType.xlCellTypeVisible = True Then
            ComboBox2.Items.Add(sheet.Range("H:H").Cells(StartRow, 1).Text)
        End If
    Next
    w.Close(SaveChanges:=False)
End Sub    

person Yassin Kulk    schedule 17.09.2018    source источник
comment
Можете ли вы предоставить нам полный и проверяемый пример того, что вы пробовали до сих пор? Заранее спасибо!   -  person Simo    schedule 17.09.2018
comment
Привет, Симо. Пожалуйста, найдите выше. Итак, у меня уже есть Combobox1, заполненный записями из столбца A (или столбца I) (основные записи). Я пытаюсь зафиксировать выделение основной записи с помощью Combobox1.SelectedItem. Что я пробовал сейчас, так это отфильтровать лист, а затем попытаться заполнить столбец B (или столбец H) всеми подчиненными записями.   -  person Yassin Kulk    schedule 17.09.2018
comment
Я предлагаю вам использовать следующую логику: заполните DataTable запросом, который возвращает все основные записи. Заполните второй DataTable запросом, который возвращает SlaveRecords, принадлежащий MasterRecords. Заполните ComboBox1 первыми таблицами данных и ComboBox2 второй таблицей данных. @YassinKulk ты понял?   -  person Simo    schedule 17.09.2018
comment
Сейчас у меня будет запуск, вернусь примерно через полторы часа. Если вы все еще будете с этим бороться, я дам соответствующий ответ.   -  person Simo    schedule 17.09.2018
comment
Привет, Симо. Наслаждайтесь обедом! Я понимаю предложенную вами логику. Как новичок в vb.net, я постараюсь найти примеры создания этой таблицы данных. Спасибо!   -  person Yassin Kulk    schedule 17.09.2018
comment
Я могу направить вас на правильный путь: ищите OleDb и как использовать его для заполнения таблиц данных! Затем вы можете посмотреть как привязать таблица данных в поле со списком   -  person Simo    schedule 17.09.2018
comment
Симо, благослови тебя. Большое спасибо за помощь, очень признателен!   -  person Yassin Kulk    schedule 17.09.2018
comment
Я вернулся, вы все еще боретесь с приведенным выше кодом?   -  person Simo    schedule 17.09.2018


Ответы (1)


Это может помочь вам или, по крайней мере, дать вам общее представление:

Private Function ExcelToDataTable(ByVal fileExcel As String, _ 
                                  Optional ByVal columnToExtract As String = "*", _
                                  ) As System.Data.DataTable
    Dim dt As New System.Data.DataTable
    Try
        Dim MyConnection As System.Data.OleDb.OleDbConnection
        Dim MyCommand As OleDbDataAdapter
        Dim fileExcelType As String

        'Chose the right provider
        If IO.Path.GetExtension(fileExcel.ToUpper) = ".XLS" Then
            fileExcelType = "Excel 8.0"
            MyConnection = _
            New System.Data.OleDb.OleDbConnection _
            ("provider=Microsoft.Jet.OLEDB.4.0;Data Source='" & fileExcel & "';Extended Properties=" & fileExcelType & ";")
        Else
            fileExcelType = "Excel 12.0"
            MyConnection = _ 
            New System.Data.OleDb.OleDbConnection _
            ("provider=Microsoft.ACE.OLEDB.12.0;Data Source='" & fileExcel & "';Extended Properties=" & fileExcelType & ";")
        End If

        'Open excel connection
        MyConnection.Open()

        'Populate DataTable
        Dim myTableName = MyConnection.GetSchema("Tables").Rows(0)("TABLE_NAME")
        MyCommand = New OleDbDataAdapter(String.Format("SELECT " & columnToExtract & " FROM [{0}] ", myTableName), MyConnection)
        MyCommand.TableMappings.Add("Table", columnToExtract)
        MyCommand.Fill(dt)
        MyConnection.Close()
    Catch ex As Exception
        Err.Clear()
    End Try
    Return dt
End Function

Как видите, у нас есть необязательный параметр myWhereStatement.

Что это означает?. Вы можете указать его значение при вызове функции, иначе его значение будет empty string

После этого мы можем вызвать ExcelToDataTable внутри нашего Sub, чтобы заполнить ComboBox, как показано ниже:

Private Sub Combobox_Populate()
    Dim filePath As String = "your_file_path"
    ComboBox1.DataSource = ExcelToDataTable(filePath, "MasterRecord") 
End Sub

Теперь ваш ComboBox1 заполнен данными, но ComboBox2 все еще пуст.

Мы собираемся обработать событие ComboBox1_SelectedValueChanged, что означает, что каждый раз, когда вы выбираете элемент из ComboBox1, он будет программно заполнять ComboBox2 соответствующими элементами, как показано ниже.

Private Sub ComboBox1_SelectedValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles ComboBox1.SelectedValueChanged
    Dim slaveRecords As System.Data.DataTable = ExcelToDataTable(filePath)
    Dim dt As New DataTable
    dt.Columns.Add("SlaveRecords")
    For i As Integer = 0 To slaveRecords.Rows.Count
        If ComboBox1.SelectedItem Is slaveRecords.Rows(i).Item(0) Then
            dt.Rows.Add(slaveRecords.Rows(i).Item(1))
        End If
    Next
    ComboBox2.DataSource = dt
End Sub

Примечания

Как видите, первый вызов ExcelToDataTable имеет только 2 параметра, а второй - 3 параметра. Это необязательный параметр особенность!

Примечание

Как видите, я использую много _ из-за лучшего форматирования кода. Это означает, что будет продолжаться один оператор в нескольких строках

Если что-то не на 100% ясно, не стесняйтесь спрашивать в комментариях ниже.

person Simo    schedule 17.09.2018
comment
Привет, Симо. Абсолютно блестящий. Спасибо, нет. Я добавлю это в свой сценарий и продолжу, но основной принцип мне ясен. Все лучшее для вас! - person Yassin Kulk; 17.09.2018
comment
Привет, Симо. Просто чтобы подтвердить, когда я прохожу через это. myWhereStatement, относится ли это к рабочему листу, в котором нужно углубиться? Что касается MasterRecord и SlaveRecord, это диапазоны столбцов? Я пытаюсь понять часть your_where_clauses_to_match_records. Ваше здоровье! - person Yassin Kulk; 17.09.2018
comment
Да, подумайте, как ваш excel - это таблица sql, и действуйте в соответствии с этим. Есть ли какие-то элементы, которые вы можете использовать в предложениях where для сопоставления подчиненных записей с основными записями? если нет, скажите, что я найду решение. - person Simo; 17.09.2018
comment
По сути, все SlaveRecords являются частью MasterRecord. Итак, в столбце H (ведомые записи) у меня есть такие коды, как 4333A, 4444A, 4555A. В столбце I (MasterRecords) у меня есть тот же номер MasterRecord, повторенный для этих ведомых записей, то есть 631755. Итак, если я сортирую в Excel по столбцу I с критериями 631755, я нахожу 4333A, 4444A и 4555A. Мне нужно добиться того же, где Combobox1 - это список всех MasterRecords (столбец I), а затем Combobox2 должен предоставить мне ведомые записи для всех тех, которые находятся под основной записью, выбранной в Combobox1. Позже мне также нужно знать сумму всех ведомых записей. - person Yassin Kulk; 17.09.2018
comment
Я не понял, можете ли вы обновить свой ответ скриншотом вашего файла Excel? - person Simo; 17.09.2018
comment
Привет, Симо, я добавил картинку выше. Большое спасибо за вашу самоотверженность в поддержке меня здесь, искренне признателен. - person Yassin Kulk; 17.09.2018
comment
@YassinKulk не уверен, что это работает, попробуйте набрать group by MasterRecords вместо your_where_clauses... - person Simo; 17.09.2018
comment
к сожалению, не работает (группа не распознается по умолчанию в моем vb.net. Не уверен, что мне не хватает библиотеки, кроме System RegularExpressions). Кроме того, мои поля со списком, кстати, не заполняются, поэтому я догадываюсь, что он также не подключается должным образом к требуемому листу. в myWhereStatement следует ли добавлять к имени листа суффикс $? - person Yassin Kulk; 17.09.2018
comment
@YassinKulk По крайней мере, вы пробовали, я был уверен, что это не работает, поэтому я не терял время и работал над другим решением. Редактирую ответ прямо сейчас - person Simo; 17.09.2018
comment
Ответ Отредактирован, скажите, есть ли у вас другие проблемы. теперь должно работать - person Simo; 17.09.2018
comment
Большое спасибо за старания. Сценарий должен иметь полный смысл, но я не могу заполнить поля со списком, потому что догадываюсь, что это не относится к нужному листу в исходном файле Excel. Я буду возиться с этим, но основы есть. Еще раз спасибо. - person Yassin Kulk; 17.09.2018
comment
@YassinKulk для работы убедитесь, что в вашем файле excel есть только 2 столбца с именами MasterRecord и SlaveRecord - person Simo; 17.09.2018