Suppose I have a ComboBox in Excel VBA with the following sorts of info:
1234 apples
2345 pears
2367 oranges
I want the user to be able to
So first to give some context to this answer. SectorDropDown1_1 (which is part of a form) is a drop down list that is populated with the concatenated strings of a number value and a string value coming from a column J. In this context the _change() method responds to the user typing in values. I have 2 columns "R", and "S", in a spreadsheet "SectorSearch" that have separated the number and the text. So now if the user enters either the number or the text, then the appropriate value in the Drop Down list is selected. But here is the problem, my code sort of awkwardly jumps to the exact value and so I want to "smooth things out" so to speak so that after the user types more than 2 characters that match the appropriate value that this value is now selected and the drop down list shows the nearby values.
Option Explicit
Private Sub SectorDropDown1_1_Change()
Dim i As Long
Dim StringRange1 As String
Dim StringRange2 As String
Dim Stringrange3 As String
Dim LengthOfValue As Integer
Dim TotalSectorCodes As Integer
If SectorDropDown1_1.Value <> "" And Len(SectorDropDown1_1.Value) > 2 Then
TotalSectorCodes = Worksheets("SectorSearch").Range("J:J").Cells.SpecialCells(xlCellTypeFormulas).Count
LengthOfValue = Len(SectorDropDown1_1.Value)
For i = 2 To TotalSectorCodes
StringRange1 = "R" & CStr(i)
StringRange2 = "S" & CStr(i)
Stringrange3 = "J" & CStr(i)
Select Case SectorDropDown1_1.Value
Case Left(Worksheets("SectorSearch").Range(StringRange1).Value, LengthOfValue)
SectorDropDown1_1.Value = Worksheets("SectorSearch").Range(Stringrange3).Value
Exit For
Case Left(Worksheets("SectorSearch").Range(StringRange2).Value, LengthOfValue)
SectorDropDown1_1.Value = Worksheets("SectorSearch").Range(Stringrange3).Value
Exit For
Case Else
'...
End Select
Next i
End If
End Sub
Since you are using a form and form controls I'd like to throw in another solution (which I'd personally prefer). In this case I am not using a ComboBox but rather a ListBox:
This is the code to populate the ListBox on the form and to show the form:
Sub Button3_Click()
Dim i As Long
Dim lngLastRow As Long
Load frmSearchForChoices
With ThisWorkbook.Worksheets(1)
lngLastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
For i = 2 To lngLastRow
frmSearchForChoices.lstAvailableOptions.AddItem
frmSearchForChoices.lstAvailableOptions.List(frmSearchForChoices.lstAvailableOptions.ListCount - 1, 0) = .Cells(i, 1).Value2
frmSearchForChoices.lstAvailableOptions.List(frmSearchForChoices.lstAvailableOptions.ListCount - 1, 1) = .Cells(i, 2).Value2
frmSearchForChoices.lstAvailableOptions.List(frmSearchForChoices.lstAvailableOptions.ListCount - 1, 2) = .Cells(i, 3).Value2
Next i
frmSearchForChoices.Show
End With
End Sub
The following code resides on the form itself:
Option Explicit
Option Compare Text
Private Sub btnCancel_Click()
frmSearchForChoices.Hide
Unload frmSearchForChoices
End Sub
Private Sub btnOK_Click()
Dim lngMatch As Long
If frmSearchForChoices.lstAvailableOptions.ListCount > 0 Then
If frmSearchForChoices.lstAvailableOptions.ListIndex >= 0 Then
For lngMatch = 0 To frmSearchForChoices.lstAvailableOptions.ListCount - 1
If frmSearchForChoices.lstAvailableOptions.Selected(lngMatch) = True Then
MsgBox "You selected" & Chr(10) & _
frmSearchForChoices.lstAvailableOptions.List(lngMatch, 1) & " (" & _
frmSearchForChoices.lstAvailableOptions.List(lngMatch, 0) & ")" & _
IIf(Len(frmSearchForChoices.lstAvailableOptions.List(lngMatch, 2)) > 0, _
" from " & frmSearchForChoices.lstAvailableOptions.List(lngMatch, 2), "")
frmSearchForChoices.Hide
Unload frmSearchForChoices
End If
Next lngMatch
End If
End If
End Sub
Private Sub txtSearchTerm_Change()
Dim i As Long
Dim lngMatch As Long
Dim varArray As Variant
If Len(Trim(frmSearchForChoices.txtSearchTerm.Value)) = 0 Then Exit Sub
For lngMatch = 0 To frmSearchForChoices.lstAvailableOptions.ListCount - 1
frmSearchForChoices.lstAvailableOptions.Selected(lngMatch) = False
frmSearchForChoices.lstAvailableOptions.List(lngMatch, 3) = 0
Next lngMatch
varArray = Split(Trim(frmSearchForChoices.txtSearchTerm.Value), " ")
For i = LBound(varArray) To UBound(varArray)
For lngMatch = 0 To frmSearchForChoices.lstAvailableOptions.ListCount - 1
If InStr(1, frmSearchForChoices.lstAvailableOptions.List(lngMatch, 1), varArray(i)) Or _
InStr(1, frmSearchForChoices.lstAvailableOptions.List(lngMatch, 2), varArray(i)) Then
frmSearchForChoices.lstAvailableOptions.List(lngMatch, 3) = Val(frmSearchForChoices.lstAvailableOptions.List(lngMatch, 3)) + 1
End If
Next lngMatch
Next i
For lngMatch = 0 To frmSearchForChoices.lstAvailableOptions.ListCount - 1
If frmSearchForChoices.chkMatchBoth.Value Then
If Val(frmSearchForChoices.lstAvailableOptions.List(lngMatch, 3)) >= UBound(varArray) - LBound(varArray) + 1 Then
frmSearchForChoices.lstAvailableOptions.Selected(lngMatch) = True
End If
Else
If Val(frmSearchForChoices.lstAvailableOptions.List(lngMatch, 3)) >= 1 Then
frmSearchForChoices.lstAvailableOptions.Selected(lngMatch) = True
End If
End If
Next lngMatch
End Sub
I sure hope that most variables and controls can be identified within the code due to the followed naming convention (starting with frm
for forms, lbl
for labels on forms, ´lst` for ListBox on form, etc). Yet, do not hesitate to let me know if you have any questions regarding this solution.