1

I'm searching for nearly two hours to find a solution on the following. In Excel I have two columns (One Column for Master Records and one Column for Slave Records). Basically, in Combobox1 I want to populate all the Master Records. If a selection is made for MasterRecord A, I want Combobox2 to only show me the SlaveRecords belonging to A and not the other records belonging to other Master Records.

enter image description here

I have the Interop Assembly added and Excel opened (there is a connection already). Your help is much appreciated!

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    
  • Can you provide us with a [complete and verifiable](https://www.stackoverflow.com/help/mcve) example of what you tried so far? Thanks in advance! – Simo Sep 17 '18 at 11:32
  • Hello Simo. Please find above. So I already have Combobox1 populated with the records from Column A (or Column I) (Master Records). I try to capture the Master Record selection using Combobox1.SelectedItem. What I tried now is filter the sheet and then try to populate Column B (or Column H) with all the Slave Records. – Yassin Kulk Sep 17 '18 at 11:42
  • 1
    I suggest you to use the following logic: Populate a `DataTable` with a query that returns all Master Records. Populate a second `DataTable` with a query that returns the `SlaveRecords` belonging to the MasterRecords. Fill the `ComboBox1` with the first data tables and the `ComboBox2` with the second data table. @YassinKulk did you understand? – Simo Sep 17 '18 at 11:47
  • Now I'm going to have launch, I will be back in about one and half our. If you will still struggling with this, I will make and appropriate answer. – Simo Sep 17 '18 at 11:48
  • Hi Simo. Enjoy the lunch! I get the logic you proposed. As a newbie to vb.net, I'll try to find examples on creating this data-table. Thanks! – Yassin Kulk Sep 17 '18 at 11:51
  • I can put you on the right way: Look for OleDb and how to use it to fill data tables! Than you can look at [how to bind](https://stackoverflow.com/questions/13300194/assigning-a-datatable-to-a-combobox-and-then-making-changes) data table to a combo box – Simo Sep 17 '18 at 11:52
  • Simo, bless you. Thanks a lot for the help, much appreciated! – Yassin Kulk Sep 17 '18 at 11:55
  • I'm back, are you still struggling with the above code? – Simo Sep 17 '18 at 13:20

1 Answers1

0

This might help you, or at least give you a basic idea:

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

As you can see, we have an optional parameter called myWhereStatement.

What does it mean? You can specify its value when you call the function, otherwise its value will be an empty string

After that we can call ExcelToDataTable inside our Sub in order to populate the ComboBox as shown below:

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

Now you have your ComboBox1 filled with data, but the ComboBox2 is still empty.

We are going to handle the event of ComboBox1_SelectedValueChanged that means that every time you select an Item from the ComboBox1 it will programmatically fill the ComboBox2 with the propper items as shown below.

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

Remarks

As you can see the first call of ExcelToDataTable has only 2 parameters while the second one has 3 parameters. That's the optional parameter feature!

N.B.

As you can see I'm using alot of _ because of better code formatting. It means that a single statement will continue across multiple lines

If something isn't 100% clear ot you have any dubt feel free to ask in the comments below.

Simo
  • 955
  • 8
  • 18
  • 1
    Hello Simo. Absolutely brilliant. Thanks a not. I will inject this into my script and go from there, but the basic principle is all clear to me. All the best to you! – Yassin Kulk Sep 17 '18 at 15:29
  • Hi Simo. Just to confirm as I step through it. myWhereStatement, does that refer to the worksheet where it needs to deep-dive into? As far as MasterRecord and SlaveRecord, are these the Column Ranges? I'm trying to understand the "your_where_clauses_to_match_records" part. Cheers! – Yassin Kulk Sep 17 '18 at 15:37
  • 1
    Yes, think as your excel is an sql table and act accorting to this. Is there some kind of elements that you can use in the where clauses to match the slave records with the master records? if not tell me that I will find a solution. – Simo Sep 17 '18 at 15:39
  • Basically, the SlaveRecords are all part of the MasterRecord. So in Column H (Slave Records) I have codes like 4333A, 4444A, 4555A. In Column I (MasterRecords) I have the same MasterRecord number repeated for those slave records, i.e. 631755. So If I sort in Excel on column I with Criteria 631755, I find 4333A, 4444A and 4555A. I need to achieve the same where Combobox1 is a list of all the MasterRecords (column I), and then Combobox2 should provide me the slave records for all those under the Master Record selected in Combobox1. Later, I need to know the sum of all Slave Records as well. – Yassin Kulk Sep 17 '18 at 15:46
  • I didn't understand, can you update your answer with a screenshot of you excel file? – Simo Sep 17 '18 at 15:58
  • 1
    Hi Simo, I've added a picture above. Thanks a lot for your dedication in supporting me here, truly appreciated. – Yassin Kulk Sep 17 '18 at 16:07
  • 1
    @YassinKulk not sure if it works, try typing `group by MasterRecords` instead of `your_where_clauses...` – Simo Sep 17 '18 at 16:13
  • sadly not working (group is not recognized by default by the way in my vb.net. Not sure if I'm missing a library apart from System RegularExpressions). Other than that my comboboxes do not fill by the way, so I'm hunching it's also not connecting properly to the required sheet. in the myWhereStatement, should the sheet name be suffixed with a $? – Yassin Kulk Sep 17 '18 at 16:23
  • 1
    @YassinKulk At least you tried, i was pretty sure that wasn't working so I didnt' waste time and I worked on another solution. I'm editing the answer right now – Simo Sep 17 '18 at 16:38
  • 1
    Answer Edited, tell me if you have other problems. now should work – Simo Sep 17 '18 at 16:46
  • 1
    Thanks a lot for the efforts. Script should make total sense, but I can't get to populate the Comboboxes, hunching it's not referring to the right sheet within the source Excel file. I will fiddle with that, but the basics are there. Thanks again. – Yassin Kulk Sep 17 '18 at 16:58
  • @YassinKulk in order to work, make sure that in your excel file there are only 2 columns called "MasterRecord" and "SlaveRecord" – Simo Sep 17 '18 at 16:59