简体   繁体   中英

Excel VBA populate list box with searched dynamic range

My difficulty is this: I have a Excel spreadsheet where I need a UserForm ListBox to populate itself with some rows of data depending on previous user input.

So the UserForm should pick up the user's input in Sheet1 (say it's 123abc ) and then search for similar results in Sheet2 . The nearest results (probably a range of about five similar results) should then fill the listbox.

So it could return something like 123a , 123ab , 1235c , and 1355abc from the list

Hope this makes sense - thanks for your help in advance.

The code I've tried (and doesn't work, turns a 1004) with notes for clarification:

Private Sub UserForm_Initialize()
  Dim cs As Worksheet
  Dim c As Range
  Dim i As Integer
  Dim code As Variant
  Dim co As String

Set code = Sheets("Sheet1").Range("B4") 'picks up user input
co = Left(code, 2) 'just takes first two letters of input to find similar

Set cs = Sheets("Sheet2")
Set c = cs.Range("A2:A20000").Find(co) 'find code (obviously :))

For i = 1 To cs.Cells(c.Offset(5, 0), 1).End(xlUp).Row Step 1
   If cs.Cells(i, 1).Value <> vbNullString Then Me.ListBox1.AddItem cs.Cells(i, 1).Value
Next i 'populate listbox

End Sub

Many thanks!


EDIT

I have marked the below as the accepted answer, but for others browsing this, the problem still exists as to integrating this with the template Excel files, as it returns the error 'External table is not in the expected format'. I had to change ThisWorkbook.FullName to the full template path to remove another error too.

Below is the aforementioned example. The code is mostly commented with what is needed. Please feel free to ask any questions.

I did a quick performance test searching for a text string in a data set of about 65,000 records. It look less than a second.

Here's the code:

'Making these variable public so they don't need to be recreated each time
'Make sure you add a reference to ADO through the tool-->references menu
Public MyConnection As New ADODB.Connection
Public MyRecordset  As New ADODB.Recordset
Private Sub UserForm_Initialize()
    Dim ColumnName As String: ColumnName = "[Number]" ' The name of the Column in Sheet2 you are searching for, it should have a header in row 1
    Dim SearchStr  As String: SearchStr = Left(Sheets("Sheet1").Range("B4").Value2, 2) ' This is what will be searched

    If MyConnection.State <> adStateOpen Then
        With MyConnection
            'Connection string below is assuming you are using an XLSX file 2007 or higher
            'It also assumes Sheet2 has column headers, e.g. HDR=Yes in the connection string
            .ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.FullName & _
                                ";Extended Properties='Excel 12.0 Xml;HDR=YES;IMEX=1';"
            .Open
        End With
    End If

    If MyRecordset.State = adStateOpen Then MyRecordset.Close ' Make sure recordset is closed when open
    MyRecordset.Open "Select top 5 " & ColumnName & " from [Sheet2$] where " & ColumnName & _
                     " like '%" & SearchStr & "%'", MyConnection, adOpenForwardOnly, adLockReadOnly

    Me.ListBox1.Clear ' Clear all entries from the listbox
    If Not MyRecordset.EOF Then MyRecordset.MoveFirst 'Move to start of recordset

    Do Until MyRecordset.EOF 'Loop recordset and add all the items
        Me.ListBox1.AddItem MyRecordset.Fields(0).Value
        MyRecordset.MoveNext
    Loop

End Sub

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM