openstar
Technical User
- May 11, 2013
- 9
hi,
I had to use this FAQ for one of my software, so i made major improvement in the code
No need for developper to adapt code for each new function as before.
Now this fonction work with :
ALL SQL STATEMENT (without changing the code)
ALL WINDOWS LOCAL SETTINGS
ALL NUMBER OF HIDDEN COLUMNS
ALL NUMBER OF BOUND COLUMNS
ALL NUMBER OF COMBOBOX
Need to Add at Top of a Module
Declare Function GetLocaleInfo Lib "kernel32" Alias "GetLocaleInfoA" (ByVal Locale As Long, ByVal LCType As Long, ByVal lpLCData As String, ByVal cchData As Long) As Long
Need to Add at top of FORM VBA CODE
Dim tempSQLquery As New Collection
PS: i changed the like statement to '*TEXT*' instead of '*T*E*X*T*'
you can change back that in code if necessary.
Here is ComboBox_onchange() code :
Private Sub Combo0_Change() ' Only have to adapt this to your own function
' Function Description:
' Filter a combo box list as the user types,
' I delibarately change code to fit Like "*TEXT*"
' This is accomplished by grabbing the text typed by the user in the
' combo box's edit field, creating an SQL SELECT statement from it,
' and finally applying that SQL statement to the combo box's
' .RowSource property.
' Form design settings:
' Set AutoExpand to No
' Column Count unlimited
' Keyed on column : up to you (record primary key)
' Showing column : up to you (user-readable data)
' Work for as many combobox as possible
' Work independament of local list separator
' No need to know the SQL rowsource
' Need to Add following line at top of Form VBA Code
' Dim tempSQLquery As New Collection
' Need to Add Following line at top of VBA Module Code
' Declare Function GetLocaleInfo Lib "kernel32" Alias "GetLocaleInfoA" (ByVal Locale As Long, ByVal LCType As Long, ByVal lpLCData As String, ByVal cchData As Long) As Long
' Written by Sebastien LAUNAY
' Mail launayseb@gmail.com
' Thanks to tek-tips.com for original code
Dim strText As String
Dim strFind As String
Dim rs As DAO.Recordset
Dim FirstField As String
Dim Widths As String
Dim Separator As String
Dim sBuffer As String
Dim rv As Long
Dim separatorCount As Integer
Dim i As Integer
Dim strSQL As String
Dim MyComboBox As ComboBox
Dim myRowSource As String
Dim ErrNumber As Long
Dim SavedRowSource As String
'Get local list separator from system
sBuffer = String$(256, 0)
rv = GetLocaleInfo(&H400, &HC, sBuffer, Len(sBuffer))
If rv > 0 Then
Separator = Left$(sBuffer, rv - 1)
Else
Separator = ""
End If
'Get the active combobox
Set MyComboBox = Screen.ActiveControl
'Get Rowsource
myRowSource = MyComboBox.RowSource
'replace \r\n and Detele space
myRowSource = Replace(myRowSource, Chr(10), " ")
myRowSource = Replace(myRowSource, Chr(13), " ")
myRowSource = Trim(myRowSource)
'take off last listSeparator of Rowsource if exist (for ex : take off ";" in 'SELECT * FROM MyTable;')
If Right(myRowSource, 1) = Separator Then myRowSource = Left(myRowSource, Len(myRowSource) - 1)
'testing if rowsource allready saved
Err.Clear
On Error Resume Next
SavedRowSource = tempSQLquery.Item(MyComboBox.Name)
ErrNumber = CLng(Err.Number)
On Error GoTo 0
'if rowsource never saved -first time- we save it
If ErrNumber > 0 Then tempSQLquery.Add myRowSource, MyComboBox.Name
Err.Clear
' Get the text that the user has typed into the combo box editable field.
strText = MyComboBox.Text
'Get number of first Visible Field
Widths = MyComboBox.ColumnWidths
i = 1
separatorCount = 0
Do While (Mid(Widths, i, 1) <> "1") And (Mid(Widths, i, 1) <> "2") And (Mid(Widths, i, 1) <> "3") And (Mid(Widths, i, 1) <> "4") And (Mid(Widths, i, 1) <> "5") And (Mid(Widths, i, 1) <> "6") And (Mid(Widths, i, 1) <> "7") And (Mid(Widths, i, 1) <> "8") And (Mid(Widths, i, 1) <> "9")
If Mid(Widths, i, 1) = Separator Then separatorCount = separatorCount + 1
i = i + 1
If i > Len(Widths) Then Exit Do
Loop
'Get Name of first Visible Field
Set rs = CurrentDb.OpenRecordset(tempSQLquery.Item(MyComboBox.Name))
FirstField = rs.Fields(separatorCount).Name
rs.Close
' If the user has typed something in, then filter the combobox
' list to limit the visible records to those that contain the
' typed letters.
' Otherwise (if the field is blank), the user has deleted whatever
' text they typed, so show the entire (unfiltered) list
If Len(Trim(strText)) > 0 Then
' Show the list with only those items containing the typed
' letters.
' Create an SQL query string for the WHERE clause of the SQL
' SELECT statement.
strFind = " Like '*" & strText & "*'"
' changing rowsource
MyComboBox.RowSource = "SELECT * FROM (" & tempSQLquery.Item(MyComboBox.Name) & ") WHERE " & FirstField & strFind
Else
MyComboBox.RowSource = tempSQLquery.Item(MyComboBox.Name)
End If
' Make sure the combobox is open so the user
' can see the items available on list.
MyComboBox.Dropdown
End Sub
I had to use this FAQ for one of my software, so i made major improvement in the code
No need for developper to adapt code for each new function as before.
Now this fonction work with :
ALL SQL STATEMENT (without changing the code)
ALL WINDOWS LOCAL SETTINGS
ALL NUMBER OF HIDDEN COLUMNS
ALL NUMBER OF BOUND COLUMNS
ALL NUMBER OF COMBOBOX
Need to Add at Top of a Module
Declare Function GetLocaleInfo Lib "kernel32" Alias "GetLocaleInfoA" (ByVal Locale As Long, ByVal LCType As Long, ByVal lpLCData As String, ByVal cchData As Long) As Long
Need to Add at top of FORM VBA CODE
Dim tempSQLquery As New Collection
PS: i changed the like statement to '*TEXT*' instead of '*T*E*X*T*'
you can change back that in code if necessary.
Here is ComboBox_onchange() code :
Private Sub Combo0_Change() ' Only have to adapt this to your own function
' Function Description:
' Filter a combo box list as the user types,
' I delibarately change code to fit Like "*TEXT*"
' This is accomplished by grabbing the text typed by the user in the
' combo box's edit field, creating an SQL SELECT statement from it,
' and finally applying that SQL statement to the combo box's
' .RowSource property.
' Form design settings:
' Set AutoExpand to No
' Column Count unlimited
' Keyed on column : up to you (record primary key)
' Showing column : up to you (user-readable data)
' Work for as many combobox as possible
' Work independament of local list separator
' No need to know the SQL rowsource
' Need to Add following line at top of Form VBA Code
' Dim tempSQLquery As New Collection
' Need to Add Following line at top of VBA Module Code
' Declare Function GetLocaleInfo Lib "kernel32" Alias "GetLocaleInfoA" (ByVal Locale As Long, ByVal LCType As Long, ByVal lpLCData As String, ByVal cchData As Long) As Long
' Written by Sebastien LAUNAY
' Mail launayseb@gmail.com
' Thanks to tek-tips.com for original code
Dim strText As String
Dim strFind As String
Dim rs As DAO.Recordset
Dim FirstField As String
Dim Widths As String
Dim Separator As String
Dim sBuffer As String
Dim rv As Long
Dim separatorCount As Integer
Dim i As Integer
Dim strSQL As String
Dim MyComboBox As ComboBox
Dim myRowSource As String
Dim ErrNumber As Long
Dim SavedRowSource As String
'Get local list separator from system
sBuffer = String$(256, 0)
rv = GetLocaleInfo(&H400, &HC, sBuffer, Len(sBuffer))
If rv > 0 Then
Separator = Left$(sBuffer, rv - 1)
Else
Separator = ""
End If
'Get the active combobox
Set MyComboBox = Screen.ActiveControl
'Get Rowsource
myRowSource = MyComboBox.RowSource
'replace \r\n and Detele space
myRowSource = Replace(myRowSource, Chr(10), " ")
myRowSource = Replace(myRowSource, Chr(13), " ")
myRowSource = Trim(myRowSource)
'take off last listSeparator of Rowsource if exist (for ex : take off ";" in 'SELECT * FROM MyTable;')
If Right(myRowSource, 1) = Separator Then myRowSource = Left(myRowSource, Len(myRowSource) - 1)
'testing if rowsource allready saved
Err.Clear
On Error Resume Next
SavedRowSource = tempSQLquery.Item(MyComboBox.Name)
ErrNumber = CLng(Err.Number)
On Error GoTo 0
'if rowsource never saved -first time- we save it
If ErrNumber > 0 Then tempSQLquery.Add myRowSource, MyComboBox.Name
Err.Clear
' Get the text that the user has typed into the combo box editable field.
strText = MyComboBox.Text
'Get number of first Visible Field
Widths = MyComboBox.ColumnWidths
i = 1
separatorCount = 0
Do While (Mid(Widths, i, 1) <> "1") And (Mid(Widths, i, 1) <> "2") And (Mid(Widths, i, 1) <> "3") And (Mid(Widths, i, 1) <> "4") And (Mid(Widths, i, 1) <> "5") And (Mid(Widths, i, 1) <> "6") And (Mid(Widths, i, 1) <> "7") And (Mid(Widths, i, 1) <> "8") And (Mid(Widths, i, 1) <> "9")
If Mid(Widths, i, 1) = Separator Then separatorCount = separatorCount + 1
i = i + 1
If i > Len(Widths) Then Exit Do
Loop
'Get Name of first Visible Field
Set rs = CurrentDb.OpenRecordset(tempSQLquery.Item(MyComboBox.Name))
FirstField = rs.Fields(separatorCount).Name
rs.Close
' If the user has typed something in, then filter the combobox
' list to limit the visible records to those that contain the
' typed letters.
' Otherwise (if the field is blank), the user has deleted whatever
' text they typed, so show the entire (unfiltered) list
If Len(Trim(strText)) > 0 Then
' Show the list with only those items containing the typed
' letters.
' Create an SQL query string for the WHERE clause of the SQL
' SELECT statement.
strFind = " Like '*" & strText & "*'"
' changing rowsource
MyComboBox.RowSource = "SELECT * FROM (" & tempSQLquery.Item(MyComboBox.Name) & ") WHERE " & FirstField & strFind
Else
MyComboBox.RowSource = tempSQLquery.Item(MyComboBox.Name)
End If
' Make sure the combobox is open so the user
' can see the items available on list.
MyComboBox.Dropdown
End Sub