Option Explicit
Private WithEvents txtbx As MSForms.TextBox
Private WithEvents LB As MSForms.ListBox
[B][COLOR=#008000]
'change these Constantes to meet your data layout[/COLOR][/B]
[COLOR=#ff0000][B]Private Const SheetName As String = "Sheet1"
Private Const ListRangeAddr As String = "A7:A15000"
Private Const InputCells As String = "E6,E14,G6,G14"[/B][/COLOR]
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
Names("CurInputCell").Delete
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([CurInputCell]).Address Then
With Range([CurInputCell])
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([CurInputCell]) = 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([CurInputCell]) = 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([CurInputCell]) = .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([CurInputCell])
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)
Dim lIndex As Long
On Error Resume Next
If Sh.Name = SheetName Then
lIndex = WorksheetFunction.Match(Target.Address(False, False), Split(InputCells, ","), 0)
If lIndex Then
Names.Add "CurInputCell", Target.Address(False, False)
Application.OnKey "{F1}", Me.CodeName & ".BringupList"
Else
Application.OnKey "{F1}", ""
Sh.OLEObjects("MyTextBox").Delete
Sh.OLEObjects("MyListBox").Delete
End If
End If
End Sub