Allow Typing-in names much faster

south0085

Board Regular
Joined
Aug 15, 2011
Messages
141
Thank you for your time. I'm using Excel 2010.

In a particular cell, the operator types the supplier name. In an adjacent cell, the supplier number populates (vlookup).

In the supplier name cell, I would like for the operater to type the first letter(s) of the supplier name, and the drop down list (or another feature??) to automatically scroll to that letter in the drop down list. Currently, the operator has to scroll very carefully through the drop down until they find the supplier name that they are looking for. This wastes a lot of time.

Or it would be great if: as you typed the letters of the supplier name, it eventually just popped up with that supplier name.

Is something like this possible in Excel?

Thank you.
 

Excel Facts

Round to nearest half hour?
Use =MROUND(A2,"0:30") to round to nearest half hour. Use =CEILING(A2,"0:30") to round to next half hour.
AFAIK, there is no easy way to do this as worksheet cells do not have a keyPress event .. I have worked out a workaround before but the code I came up with used heavily the windows api which had a hit on performance
Are you using Data Validation at the moment ? You could use a combobox created at runtime and take advantage of its KeyPress/KeyDown events to filter the supplier names as you type .. This will also require some not-straight forward coding for this but it can be done and it is a more stable approach than using the api.. If I have time, I'll write the code and post it here
 
Last edited:
Upvote 0
No worries Jaafar. I appreciate your help and explaining that to me. Don't worry about the code. I don't think we would use something that extensive. I'm sure it would work great though. Thanks for the info.
 
Upvote 0
Workbook example

Hi,

I've just finished writing the code for this using a ListBox and a TextBox both created @ runtime

The code requires a reference to the MSFORMS library via tools>References .. or easier, just add a dummy temporary userform to the project and remove it

Steps to bring up the validation list
:
=========================
'- Select the input cell (in this example Cell (E6))
'- Press the (F1) key to display the list
'- Press the (ESC) key or deselect the input cell to dismiss the list

Ok - After you have set a reference to the MSFORMS library, place the following code in the ThisWorkbook module :
(Note: The Workbook_Open event must be ran first in order to hook the (F1) key)
Code:
'Steps to bring up the validation list :
'=========================
    '- Select the input cell (in this example Cell (E6))
    '- Press the (F1) key to display the list
    '- Press the (ESC) key or deselect the input cell to dismiss the list

'This code requires a reference to the MSFORMS library

Option Explicit

Private WithEvents txtbx As MSForms.TextBox
Private WithEvents LB As MSForms.ListBox

'change these Constantes to meet your data layout
Private Const SheetName As String = "Sheet1"
Private Const ListRangeAddr As String = "A7:A287"
Private Const InputCellAddr As String = "E6"


Private Sub Workbook_Open()
    Application.OnKey "{F1}", Me.CodeName & ".BringupList"
End Sub

Private Sub Workbook_BeforeClose(Cancel As Boolean)
    Application.OnKey "{F1}", ""
    On Error Resume Next
    Sheets(SheetName).OLEObjects("MyListBox").Delete
    Sheets(SheetName).OLEObjects("MyTextBox").Delete
End Sub

Private Sub BringupList()
    Dim oTxtBx As OLEObject
    Dim oLbx As OLEObject
    If ActiveCell.Address = Range(InputCellAddr).Address Then
        With Range(InputCellAddr)
            Set oTxtBx = Sheets(SheetName).OLEObjects.Add(ClassType:="Forms.TextBox.1", Link:=False, _
            DisplayAsIcon:=False, Left:=.Left, Top:=.Top, Width:=.Width, Height _
            :=.Height)
        End With
        oTxtBx.Name = "MyTextBox"
        Set oLbx = Sheets(SheetName).OLEObjects.Add(ClassType:="Forms.ListBox.1")
        oLbx.Name = "MyListBox"
        Application.OnTime Now, Me.CodeName & ".HookAndBuildControls"
    End If
End Sub

Private Sub LB_KeyUp(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
    Static lastIndex As Long
    With Sheets(SheetName)
        If KeyCode = vbKeyEscape Then
            .OLEObjects("MyTextBox").Delete
            .OLEObjects("MyListBox").Delete
            Exit Sub
        End If
        If KeyCode = vbKeyUp And LB.ListIndex = 0 And lastIndex <> 1 Then
            LB.ListIndex = -1
            .OLEObjects("MyTextBox").Activate
            txtbx.Text = "": Exit Sub
        End If
    End With
    txtbx.Text = LB.Text
    lastIndex = LB.ListIndex
End Sub

Private Sub LB_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As Single, ByVal Y As Single)
    On Error Resume Next
    Range(InputCellAddr) = LB.Value
    Sheets(SheetName).OLEObjects("MyTextBox").Delete
    Sheets(SheetName).OLEObjects("MyListBox").Delete
End Sub

Private Sub LB_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
    With Sheets(SheetName)
        If KeyCode = VBA.vbKeyEscape Then
            .OLEObjects("MyTextBox").Delete
            .OLEObjects("MyListBox").Delete
            Exit Sub
        End If
        If KeyCode = vbKeyReturn Then
            Range(InputCellAddr) = LB.Value
            .OLEObjects("MyTextBox").Delete
            .OLEObjects("MyListBox").Delete
            Exit Sub
        End If
    End With
End Sub

Private Sub txtbx_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
    Dim indx As Long
    On Error Resume Next
    Select Case KeyCode
        Case vbKeyDown
            LB.Selected(0) = True
            Sheets(SheetName).OLEObjects("MyListBox").Activate
            Exit Sub
        Case vbKeyUp
            Exit Sub
        Case vbKeyEscape
            Sheets(SheetName).OLEObjects("MyTextBox").Delete
            Sheets(SheetName).OLEObjects("MyListBox").Delete
            Exit Sub
        Case vbKeyReturn
            With txtbx
            indx = WorksheetFunction.Match(.Text, Application.Transpose(Range(ListRangeAddr)), 0)
            If indx = 0 Then
                MsgBox "invalid input" & vbCrLf & "Try Again", vbCritical
                .SelStart = 0
                .SelLength = Len(.Text)
            Else
                Range(InputCellAddr) = .Text
                Sheets(SheetName).OLEObjects("MyTextBox").Delete
                Sheets(SheetName).OLEObjects("MyListBox").Delete
                Exit Sub
            End If
            End With
    End Select
    Application.OnTime Now, Me.CodeName & ".FilterList"
End Sub

Private Sub FilterList()
    Dim oCell As Range
    On Error Resume Next
    With LB
        .Clear
        For Each oCell In Range(ListRangeAddr).Cells
            If UCase(oCell.Text) Like UCase(txtbx.Text) & "*" Then
                .AddItem oCell
            End If
        Next
        .IntegralHeight = False
        .Height = .Height
        .IntegralHeight = True
        Sheets(SheetName).OLEObjects("MyListBox").Visible = False
        If .ListCount > 0 Then
            Sheets(SheetName).OLEObjects("MyListBox").Visible = True
        End If
    End With
End Sub

Private Sub HookAndBuildControls()
    Dim oCell As Range
    Set txtbx = Sheets(SheetName).OLEObjects("MyTextBox").Object
    With txtbx
        .SpecialEffect = fmSpecialEffectFlat
        .BackColor = &H80FFFF
        .BorderStyle = fmBorderStyleSingle
        .ForeColor = vbRed
        .Font.Bold = True
    End With
    Set LB = Sheets(SheetName).OLEObjects("MyListBox").Object
    With Range(InputCellAddr)
        LB.Left = .Left
        LB.Top = .Offset(1).Top + 1
        LB.Height = 200
        LB.Width = .Width + 12
    End With
    With LB
        .SpecialEffect = fmSpecialEffectFlat
        .BackColor = &H80FFFF
        .BorderStyle = fmBorderStyleSingle
        .IntegralHeight = False
        .Height = .Height
        .IntegralHeight = True
    End With
    For Each oCell In Range(ListRangeAddr).Cells
        LB.AddItem oCell
    Next
    Sheets(SheetName).OLEObjects("MyListBox").Visible = False
    Sheets(SheetName).OLEObjects("MyListBox").Visible = True
    txtbx.Activate
End Sub

Private Sub Workbook_SheetActivate(ByVal Sh As Object)
    If Sh.Name = SheetName Then
        Application.OnKey "{F1}", Me.CodeName & ".BringupList"
    End If
End Sub

Private Sub Workbook_SheetDeactivate(ByVal Sh As Object)
    If Sh.Name = SheetName Then
        Application.OnKey "{F1}", ""
    End If
End Sub

Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
    On Error Resume Next
    If Sh.Name = SheetName Then
        If Target.Address = Range(InputCellAddr).Address Then
            Application.OnKey "{F1}", Me.CodeName & ".BringupList"
        Else
            Application.OnKey "{F1}", ""
            Sh.OLEObjects("MyTextBox").Delete
            Sh.OLEObjects("MyListBox").Delete
        End If
    End If
End Sub

Tested on excel 2007 .. Hope this works for you in Excel 2010
 
Upvote 0
I tested the above code with a list containing a greater number of entries ( around 1000 entries ) and I noticed a bad lagging in performance when the list is being updated .. The following version of the code addresses this issue ( Testd on a list with around 5000 entries and no noticeable lagging )

New Workbook Example

So please, ignore the previous code and use this one :

Code in the Thisworkbook module :
Code:
[COLOR=#008000]'Code written by jaafar tribak on 01/05/2015[/COLOR] [COLOR=#008000]@ MrExcel.com[/COLOR]

[COLOR=#008000]'This code adds a custom validation list to a worksheet cell
'The list is dynamically filtered down to the entries that begin with the first typed letters
'This speeds up data entry enormously ! Ideal for data entry from long lists
'The code uses a textbox and a listbox both added @ runtime[/COLOR]

[COLOR=#008000]'Steps to bring up the validation list :
'=========================
    '- Select the input cell (in this example Cell (E6))
    '- Press the (F1) key to display the list
    '- Press the (ESC) key or deselect the input cell to dismiss the list

'This code requires a reference to the MSFORMS library
'You can just add a temporary dummy userform to the vb project and then delete it

'Code written and tested on Win XP - Excel 2007[/COLOR]

Option Explicit

Private WithEvents txtbx As MSForms.TextBox
Private WithEvents LB As MSForms.ListBox

[COLOR=#008000]'change these Constantes to meet your data layout[/COLOR]
Private Const SheetName As String = "Sheet1"
Private Const ListRangeAddr As String = "A7:A5000"
Private Const InputCellAddr As String = "E6"

Private Sub Workbook_Open()
    Application.OnKey "{F1}", Me.CodeName & ".BringupList"
End Sub

Private Sub Workbook_BeforeClose(Cancel As Boolean)
    Application.OnKey "{F1}", ""
    On Error Resume Next
    Sheets(SheetName).OLEObjects("MyListBox").Delete
    Sheets(SheetName).OLEObjects("MyTextBox").Delete
End Sub

Private Sub BringupList()
    Dim oTxtBx As OLEObject
    Dim oLbx As OLEObject
    If ActiveCell.Address = Range(InputCellAddr).Address Then
        With Range(InputCellAddr)
            Set oTxtBx = Sheets(SheetName).OLEObjects.Add(ClassType:="Forms.TextBox.1", Link:=False, _
            DisplayAsIcon:=False, Left:=.Left, Top:=.Top, Width:=.Width, Height _
            :=.Height)
        End With
        oTxtBx.Name = "MyTextBox"
        Set oLbx = Sheets(SheetName).OLEObjects.Add(ClassType:="Forms.ListBox.1")
        oLbx.Name = "MyListBox"
        Application.OnTime Now, Me.CodeName & ".HookAndBuildControls"
    End If
End Sub

Private Sub LB_KeyUp(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
    Static lastIndex As Long
    With Sheets(SheetName)
        If KeyCode = vbKeyEscape Then
            .OLEObjects("MyTextBox").Delete
            .OLEObjects("MyListBox").Delete
            Exit Sub
        End If
        If KeyCode = vbKeyUp And LB.ListIndex = 0 And lastIndex <> 1 Or LB.ListCount = 0 Then
            LB.ListIndex = -1
            .OLEObjects("MyTextBox").Activate
            txtbx.Text = "": Exit Sub
        End If
    End With
    txtbx.Text = LB.Text
    lastIndex = LB.ListIndex
End Sub

Private Sub LB_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As Single, ByVal Y As Single)
    On Error Resume Next
    Range(InputCellAddr) = LB.Value
    Sheets(SheetName).OLEObjects("MyTextBox").Delete
    Sheets(SheetName).OLEObjects("MyListBox").Delete
End Sub

Private Sub LB_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
    With Sheets(SheetName)
        If KeyCode = VBA.vbKeyEscape Then
            .OLEObjects("MyTextBox").Delete
            .OLEObjects("MyListBox").Delete
            Exit Sub
        End If
        If KeyCode = vbKeyReturn Then
            Range(InputCellAddr) = LB.Value
            .OLEObjects("MyTextBox").Delete
            .OLEObjects("MyListBox").Delete
            Exit Sub
        End If
    End With
End Sub

Private Sub txtbx_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
    Dim indx As Long
    Dim ar() As Variant
    On Error Resume Next
    Select Case KeyCode
        Case vbKeyDown
            LB.Selected(0) = True
            Sheets(SheetName).OLEObjects("MyListBox").Activate
            Exit Sub
        Case vbKeyUp
            Exit Sub
        Case vbKeyEscape
            Sheets(SheetName).OLEObjects("MyTextBox").Delete
            Sheets(SheetName).OLEObjects("MyListBox").Delete
            Exit Sub
        Case vbKeyReturn
            With txtbx
            indx = WorksheetFunction.Match(.Text, Application.Transpose(Range(ListRangeAddr)), 0)
            If indx = 0 Then
                MsgBox "Invalid input" & vbCrLf & "Try Again ", vbCritical
                .SelStart = 0
                .SelLength = Len(.Text)
            Else
                Range(InputCellAddr) = .Text
                Sheets(SheetName).OLEObjects("MyTextBox").Delete
                Sheets(SheetName).OLEObjects("MyListBox").Delete
                Exit Sub
            End If
            End With
        Case VBA.vbKeyBack
            If Len(txtbx.Text) = 1 Or Len(txtbx.Text) = 0 Then
                LB.Clear
                ar = Application.Transpose(Range(ListRangeAddr))
                LB.List = ar
                Exit Sub
            End If
    End Select
    Application.OnTime Now, Me.CodeName & ".FilterList"
End Sub

Private Sub FilterList()
    On Error Resume Next
    Dim i As Long
    Dim ar() As Variant
    ar = Application.Transpose(Range(ListRangeAddr))
    With LB
        .Clear
        For i = 0 To UBound(ar())
            If UCase(ar(i)) Like UCase(txtbx.Text) & "*" Then
                .AddItem ar(i)
            End If
        Next
        .IntegralHeight = False
        .Height = .Height
        .IntegralHeight = True
    End With
End Sub

Private Sub HookAndBuildControls()
    Dim oCell As Range
    Dim ar() As Variant
    Set txtbx = Sheets(SheetName).OLEObjects("MyTextBox").Object
    With txtbx
        .SpecialEffect = fmSpecialEffectFlat
        .BackColor = &H80FFFF
        .BorderStyle = fmBorderStyleSingle
        .ForeColor = vbRed
        .Font.Bold = True
    End With
    Set LB = Sheets(SheetName).OLEObjects("MyListBox").Object
    With Range(InputCellAddr)
        LB.Left = .Left
        LB.Top = .Offset(1).Top + 1
        LB.Height = 200
        LB.Width = .Width + 12
    End With
    With LB
        .SpecialEffect = fmSpecialEffectFlat
        .BackColor = &H80FFFF
        .BorderStyle = fmBorderStyleSingle
        .IntegralHeight = False
        .Height = .Height
        .IntegralHeight = True
    End With
    ar = Application.Transpose(Range(ListRangeAddr))
    LB.List = ar
    Sheets(SheetName).OLEObjects("MyListBox").Visible = False
    Sheets(SheetName).OLEObjects("MyListBox").Visible = True
    txtbx.Activate
End Sub

Private Sub Workbook_SheetActivate(ByVal Sh As Object)
    If Sh.Name = SheetName Then
        Application.OnKey "{F1}", Me.CodeName & ".BringupList"
    End If
End Sub

Private Sub Workbook_SheetDeactivate(ByVal Sh As Object)
    If Sh.Name = SheetName Then
        Application.OnKey "{F1}", ""
    End If
End Sub

Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
    On Error Resume Next
    If Sh.Name = SheetName Then
        If Target.Address = Range(InputCellAddr).Address Then
            Application.OnKey "{F1}", Me.CodeName & ".BringupList"
        Else
            Application.OnKey "{F1}", ""
            Sh.OLEObjects("MyTextBox").Delete
            Sh.OLEObjects("MyListBox").Delete
        End If
    End If
End Sub
 
Upvote 0
I reckon swapping out:
Rich (BB code):
    With LB
        .Clear
        For i = 0 To UBound(ar())
            If UCase(ar(i)) Like UCase(txtbx.Text) & "*" Then
                .AddItem ar(i)
            End If
        Next
        .IntegralHeight = False
        .Height = .Height
        .IntegralHeight = True
    End With

For:
Rich (BB code):
    With LB
        .List = Filter(ar, txtbx.Text, compare:=vbTextCompare)
        .IntegralHeight = False
        .Height = .Height
        .IntegralHeight = True
    End With

Would be faster still :)
 
Upvote 0
Or for exactly the same results, somewhat more cryptically:
Rich (BB code):
    Dim resultString As String
    Dim delim As String: delim = Chr(1)
    Dim ar() As Variant
    ar = Application.Transpose(Range(ListRangeAddr))
    With LB
        resultString = Join(Filter(Split("|" & Join(ar, Chr(2) & delim), Chr(2)), delim & txtbx.Text, compare:=vbTextCompare), "")
        If Len(resultString) <> 0 Then
            .List = Split(Right(resultString, Len(resultString) - 1), delim)
        Else
            .Clear
        End If
        .IntegralHeight = False
        .Height = .Height
        .IntegralHeight = True
    End With
 
Upvote 0
Thanks for the feedback Kyle123

Code:
With LB
        .List = Filter(ar, txtbx.Text, compare:=vbTextCompare)
        .IntegralHeight = False
        .Height = .Height
        .IntegralHeight = True
End With

I tested the vba Filter function and ,indeed, it proved faster than looping through the array ..The problem is that it doesn't filter the list to show the items beginning with the typed letters .. It returns all the list items containing the typed letters regardless of the location of the letters within the item string ie : anywhere within the item string .. This is however still extremely useful because from experience, a lot of people don't necessarely remember the exact first couple of letters in a long ( and/or complicated) name instead they remember a couple of letters somewhere within it .. Definitely a nice and useful addition .. Thank you

Your second code which uses Join/Split is not really much different than mine in terms of speed . In fact, I would be wary about using lots of vb string functions/operations because they are known to be rather slow

Regards
 
Last edited:
Upvote 0
But nowhere near as slow as .AddItem, its performance is astoundingly bad; with a substantial number of matches, I'd take string functions any day. In this case though, I'd loop through an untransposed array (transposing is slow) and add to a dictionary and set the List property to the items. Both this and the string functions would be much faster than yours for a large number of matches.

For a discussion on the performance of .Additem vs .List see: http://www.excelforum.com/excel-programming-vba-macros/789489-should-additem-be-used-or-not.html
 
Last edited:
Upvote 0
But nowhere near as slow as .AddItem, its performance is astoundingly bad; with a substantial number of matches, I'd take string functions any day. In this case though, I'd loop through an untransposed array (transposing is slow) and add to a dictionary and set the List property to the items. Both this and the string functions would be much faster than yours for a large number of matches.

For a discussion on the performance of .Additem vs .List see: Should .AddItem be Used or Not?

Yep. you are right Kyle .. Just tested it with a larger number of entries and like you said, the .AddItem Property is much slower than using the String VB functions

BTW, the idea of left-padding the entry items with non printable characters before using the Split function is very neat ! I just added the ar(1) = Chr(2) & delim & ar(1) line in order to include the list top entry

Code:
ar(1) = Chr(2) & delim & ar(1)
  resultString = Join(Filter(Split("|" & Join(ar, Chr(2) & delim), Chr(2)), delim & txtbx.Text, compare:=vbTextCompare), "")

So I have finally settled for the following code :
Code:
'Code written by jaafar tribak on 29/04/2015

'This code adds a custom validation list to a worksheet cell
'The list is dynamically filtered down to the entries that begin with the first typed letters
'This speeds up data entry enormously ! Ideal for data entry from long lists
'The code uses a textbox and a listbox both added @ runtime

'Steps to bring up the validation list :
'=========================
    '- Select the input cell (in this example Cell (E6))
    '- Press the (F1) key to display the list
    '- Press the (ESC) key or deselect the input cell to dismiss the list

'This code requires a reference to the MSFORMS library
'You can just add a temporary dummy userform to the vb project and then delete it

'Code written and tested on Win XP - Excel 2007
'Thanks to Kyle123 @ MrExcel.com for assissiting with the Filter function 

Option Explicit
Private WithEvents txtbx As MSForms.TextBox
Private WithEvents LB As MSForms.ListBox

'change these Constantes to meet your data layout
Private Const SheetName As String = "Sheet1"
Private Const ListRangeAddr As String = "A7:A15000"
Private Const InputCellAddr As String = "E6"

Private Sub Workbook_Open()
    Application.OnKey "{F1}", Me.CodeName & ".BringupList"
End Sub

Private Sub Workbook_BeforeClose(Cancel As Boolean)
    Application.OnKey "{F1}", ""
    On Error Resume Next
    Sheets(SheetName).OLEObjects("MyListBox").Delete
    Sheets(SheetName).OLEObjects("MyTextBox").Delete
End Sub

Private Sub BringupList()
    Dim oTxtBx As OLEObject
    Dim oLbx As OLEObject
    If ActiveCell.Address = Range(InputCellAddr).Address Then
        With Range(InputCellAddr)
            Set oTxtBx = Sheets(SheetName).OLEObjects.Add(ClassType:="Forms.TextBox.1", Link:=False, _
            DisplayAsIcon:=False, Left:=.Left, Top:=.Top, Width:=.Width, Height _
            :=.Height)
        End With
        oTxtBx.Name = "MyTextBox"
        Set oLbx = Sheets(SheetName).OLEObjects.Add(ClassType:="Forms.ListBox.1")
        oLbx.Name = "MyListBox"
        Application.OnTime Now, Me.CodeName & ".HookAndBuildControls"
    End If
End Sub

Private Sub LB_KeyUp(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
    Static lastIndex As Long
    With Sheets(SheetName)
        If KeyCode = vbKeyEscape Then
            .OLEObjects("MyTextBox").Delete
            .OLEObjects("MyListBox").Delete
            Exit Sub
        End If
        If KeyCode = vbKeyUp And LB.ListIndex = 0 And lastIndex <> 1 Or LB.ListCount = 0 Then
            LB.ListIndex = -1
            .OLEObjects("MyTextBox").Activate
            txtbx.Text = "": Exit Sub
        End If
    End With
    txtbx.Text = LB.Text
    lastIndex = LB.ListIndex
End Sub

Private Sub LB_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As Single, ByVal Y As Single)
    On Error Resume Next
    Range(InputCellAddr) = LB.Value
    Sheets(SheetName).OLEObjects("MyTextBox").Delete
    Sheets(SheetName).OLEObjects("MyListBox").Delete
End Sub

Private Sub LB_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
    With Sheets(SheetName)
        If KeyCode = VBA.vbKeyEscape Then
            .OLEObjects("MyTextBox").Delete
            .OLEObjects("MyListBox").Delete
            Exit Sub
        End If
        If KeyCode = vbKeyReturn Then
            Range(InputCellAddr) = LB.Value
            .OLEObjects("MyTextBox").Delete
            .OLEObjects("MyListBox").Delete
            Exit Sub
        End If
    End With
End Sub

Private Sub txtbx_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
    Dim indx As Long
    Dim ar() As Variant
    On Error Resume Next
    Select Case KeyCode
        Case vbKeyDown
            LB.Selected(0) = True
            Sheets(SheetName).OLEObjects("MyListBox").Activate
            Exit Sub
        Case vbKeyUp
            Exit Sub
        Case vbKeyEscape
            Sheets(SheetName).OLEObjects("MyTextBox").Delete
            Sheets(SheetName).OLEObjects("MyListBox").Delete
            Exit Sub
        Case vbKeyReturn
            With txtbx
            indx = WorksheetFunction.Match(.Text, Application.Transpose(Range(ListRangeAddr)), 0)
            If indx = 0 Then
                MsgBox "Invalid input" & vbCrLf & "Try Again ", vbCritical
                .SelStart = 0
                .SelLength = Len(.Text)
            Else
                Range(InputCellAddr) = .Text
                Sheets(SheetName).OLEObjects("MyTextBox").Delete
                Sheets(SheetName).OLEObjects("MyListBox").Delete
                Exit Sub
            End If
            End With
        Case VBA.vbKeyBack
    End Select
    Application.OnTime Now, Me.CodeName & ".FilterList"
End Sub
Private Sub FilterList()
    On Error Resume Next
    Dim i As Long
    Dim ar() As Variant
    Dim resultString As String
    Dim delim As String: delim = Chr(1)
    ar = Application.Transpose(Range(ListRangeAddr))
    With LB
        ar(1) = Chr(2) & delim & ar(1)
        resultString = Join(Filter(Split("|" & Join(ar, Chr(2) & delim), Chr(2)), delim & txtbx.Text, compare:=vbTextCompare), "")
        If Len(resultString) <> 0 Then
            .List = Split(Right(resultString, Len(resultString) - 1), delim)
        Else
            .Clear
        End If
            .IntegralHeight = False
            .Height = .Height
            .IntegralHeight = True
    End With
End Sub

Private Sub HookAndBuildControls()
    Dim oCell As Range
    Dim ar() As Variant
    Set txtbx = Sheets(SheetName).OLEObjects("MyTextBox").Object
    With txtbx
        .SpecialEffect = fmSpecialEffectFlat
        .BackColor = &H80FFFF
        .BorderStyle = fmBorderStyleSingle
        .ForeColor = vbRed
        .Font.Bold = True
    End With
    Set LB = Sheets(SheetName).OLEObjects("MyListBox").Object
    With Range(InputCellAddr)
        LB.Left = .Left
        LB.Top = .Offset(1).Top + 1
        LB.Height = 200
        LB.Width = .Width + 12
    End With
    With LB
        .SpecialEffect = fmSpecialEffectFlat
        .BackColor = &H80FFFF
        .BorderStyle = fmBorderStyleSingle
        .IntegralHeight = False
        .Height = .Height
        .IntegralHeight = True
    End With
    ar = Application.Transpose(Range(ListRangeAddr))
    LB.List = ar
    Sheets(SheetName).OLEObjects("MyListBox").Visible = False
    Sheets(SheetName).OLEObjects("MyListBox").Visible = True
    txtbx.Activate
End Sub

Private Sub Workbook_SheetActivate(ByVal Sh As Object)
    If Sh.Name = SheetName Then
        Application.OnKey "{F1}", Me.CodeName & ".BringupList"
    End If
End Sub

Private Sub Workbook_SheetDeactivate(ByVal Sh As Object)
    If Sh.Name = SheetName Then
        Application.OnKey "{F1}", ""
    End If
End Sub

Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
    On Error Resume Next
    If Sh.Name = SheetName Then
        If Target.Address = Range(InputCellAddr).Address Then
            Application.OnKey "{F1}", Me.CodeName & ".BringupList"
        Else
            Application.OnKey "{F1}", ""
            Sh.OLEObjects("MyTextBox").Delete
            Sh.OLEObjects("MyListBox").Delete
        End If
    End If
End Sub

Regards
 
Upvote 0

Forum statistics

Threads
1,223,903
Messages
6,175,287
Members
452,631
Latest member
a_potato

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top