使用MS Access Combobox键入时搜索

时间:2015-11-24 11:29:41

标签: vba ms-access combobox access-vba ms-access-2010

我想在 Microsoft Access 中创建一个简单的搜索类型组合框,如下图所示。

enter image description here

注意:上面的图片来自我想要实现的here

的复杂实现

我的组合框命名为ctlSearch。使用Visual Basic,我想挂钩onChange事件,检测用户输入,从而完善可能的结果列表。是否有可能采用这种方法来实现类似搜索的组合框?

6 个答案:

答案 0 :(得分:8)

这是我用来过滤键入的组合框的函数:

Public Sub FilterComboAsYouType(combo As ComboBox, defaultSQL As String, lookupField As String)
Dim strSQL As String
    If Len(combo.Text) > 0 Then
        strSQL = defaultSQL & " WHERE " & lookupField & " LIKE '*" & combo.Text & "*'"
    Else
        strSQL = defaultSQL    'This is the default row source of combo box
    End If
    combo.RowSource = strSQL
    combo.Dropdown
End Sub

将组合框的“自动展开”属性设置为False并调用Sub 像这样的Change事件中的FilterComboAsYouType:

Private Sub cmbProductName_Change()
    FilterComboAsYouType Me.cmbProductName, "SELECT * FROM Product", "ProductName"
End Sub

Products

答案 1 :(得分:4)

您可以设置如下所示的组合或列表框:

SELECT ID,Hotel,Location FROM Sometable t 
WHERE t.Hotel 
LIKE "*" & Forms!YourForm!txtSearch.Text & "*"
ORDER BY t.Hotel

然后在Change事件中重新查询组合或列表框。

答案 2 :(得分:0)

尝试使用此功能比您提到的源码简单得多。

Option Compare Database
Option Explicit
'************* Code Start **************
' This code was originally written by OpenGate Software
' It is not to be altered or distributed,
' except as part of an application.
' You are free to use it in any application,
' provided the copyright notice is left unchanged.
' OpenGate Software    http://www.opengatesw.net

Function fLiveSearch(ctlSearchBox As TextBox, ctlFilter As Control, _
                      strFullSQL As String, strFilteredSQL As String, Optional ctlCountLabel As Control)
'==================================================================================
'  THIS FUNCTION ALLOWS YOU TO FILTER A COMBO BOX OR LIST BOX AS THE USER TYPES
'  ALL YOU NEED TO DO IS PASS IN THE CONTROL REFERENCE TO THE SEARCH BOX ON YOUR
'  FORM, THE LISTBOX/COMBO BOX YOU WANT TO FILTER, AND WHAT THE FULL AND FILTERED
'  SQL (ROWSOURCE) SHOULD BE.
'
'  ctlSearchBox       THE TEXTBOX THE USER TYPES IN TO SEARCH
'
'  ctlFilter          THE LISTBOX OR COMBOBOX ON THE FORM YOU WANT TO FILTER
'
'  strFullSQL         THE FULL ROWSOURCE YOU WANT TO DISPLAY AS A DEFAULT IF NO
'                     RESULTS ARE RETURNED
'
'  strFilteredSQL     THE FILTERED ROWSOURCE FOR THE LISTBOX/COMBOBOX; FOR EXAMPLE
'                     YOU WOULD WANT TO USE '...like ""*" & me.txtsearch.value & "*"""
'                     TO FILTER THE RESULTS BASED ON THE USER'S SEARCH INPUT
'
' ctlCountLabel       (OPTIONAL) THE LABEL ON YOUR FORM WHERE YOU WANT TO DISPLAY THE
'                     COUNT OF ROWS DISPLAYED IN THE LISTBOX/COMBOBOX AS THEY SEARCH
'=====================================================================================

'ADVANCED PARAMETERS - Change these constants to change the behaviour of the search
  Const iSensitivity = 1 'Set to the number of characters the user must enter before the search starts
  Const blnEmptyOnNoMatch = True 'Set to true if you want nothing to appear if nothing matches their search


10    On Error GoTo err_handle

          'restore the cursor to where they left off
20        ctlSearchBox.SetFocus
30        ctlSearchBox.SelStart = Len(ctlSearchBox.Value) + 1

40        If ctlSearchBox.Value <> "" Then
                 'Only fire if they've input more than two characters (otherwise it's wasteful)
50               If Len(ctlSearchBox.Value) > iSensitivity Then
60                   ctlFilter.RowSource = strFilteredSQL
70                   If ctlFilter.ListCount > 0 Then
80                       ctlSearchBox.SetFocus
90                       ctlSearchBox.SelStart = Len(ctlSearchBox.Value) + 1
100                   Else
110                     If blnEmptyOnNoMatch = True Then
120                      ctlFilter.RowSource = ""
130                     Else
140                      ctlFilter.RowSource = strFullSQL
150                     End If
160                   End If
170             Else
180               ctlFilter.RowSource = strFullSQL
190             End If

200        Else
210           ctlFilter.RowSource = strFullSQL
220        End If

            'if there is a count label, then update it
230         If IsMissing(ctlCountLabel) = False Then
240           ctlCountLabel.Caption = "Displaying " & Format(ctlFilter.ListCount - 1, "#,##0") & " records"
250         End If

260   Exit Function
err_handle:
270   Select Case Err.Number
    Case 91 'no ctlCountLabel
       'exit
280       Case 94 'null string
       'exit
290       Case Else
300         MsgBox "An unexpected error has occurred: " & vbCrLf & Err.Description & _
            vbCrLf & "Error " & Err.Number & vbCrLf & "Line: " & Erl
310   End Select


End Function
'   ***** Code End ******

答案 3 :(得分:0)

感谢弗拉多(Vlado),您的回答令人鼓舞,简洁且带有gif解释。几天前,我从一个苛刻的客户那里要求使用相同的功能。

但是,请求是使用类似Google的搜索。换句话说,允许在目标组合中随机(随您键入)搜索(部分)包含多个短语(当然是AND)。文字(这是几个字段“标签”的串联,包括鸡尾酒名称,酒类(是/否),成分,玻璃器皿,品牌,类别等。

现在我又被要求输入相同的内容。我想将其附加在这里,以供将来搜索以帮助其他人(陷入困境的程序员)。再次感谢弗拉多。

您要去的地方

Public Sub GoogleSearch(combo As ComboBox, OriginalSQL As String, LookupField As String)
' - OriginalSQL is not the recursive one  
' - Use queries to build up your sql statement, then copy/paste thier sql text in the combo row source  
'   do not just point the row source to the query name (keep the query for reference if you like.
'   to avoid the quotation agony of VBA built-in editor to create your OriginalSQL
' - Always store your OriginalSQL in global module variable,
' - Initiate it on (form) load, restore it on cancel AND after_update
' Created by Walid Zohair, not to be used without the exact comments

If Trim(combo.Text) = "" Or IsNull(combo.Text) Then
    combo.RowSource = OriginalSQL
    combo.Requery
    combo.Dropdown
    combo.SetFocus
    Exit Sub
End If

Dim SQLStr As String
SQLStr = Replace(OriginalSQL, ";", "") ' make sure a bar end sql is used

' make sure order_by, group_by, Having will not be after where clause (gives error)
' This also can be used to give clearer names in outer SQL to be used in Where clause later
SQLStr = "SELECT * FROM ( " & SQLStr & " ) WHERE "

Dim StrArray() As String
StrArray = Split(Trim(combo.Text)) ' for saftey could be limited to up to 100 records only = Split(combo.text, " ", 100)
For i = 0 To UBound(StrArray)
    SQLStr = SQLStr & LookupField & " LIKE '*" & StrArray(i) & "*'"

    If UBound(StrArray) - i > 0 Then
        SQLStr = SQLStr & " AND " ' Add AND to the search string
    End If
Next i
combo.RowSource = SQLStr
combo.Dropdown
End Sub

此外,根据SO社区指南,我认为这可以更多地考虑问题(更好的答案),而不是对其他答案的反应。

答案 4 :(得分:0)

我进行了广泛的搜索,这是最接近我所做的,所以我将我的脚本留在这里。它是关于将多个短语放在一个文本框中并让它搜索一个字段并在列表框中生成结果(如谷歌)。我在医学领域工作,因此术语和短语可能非常复杂。

Smart Man 上面的帖子和我做过的类似,我尝试了他的方法但没有成功。具有挑战性的是他所做的 For 循环的制定,但我的版本将 WHERE 子句更改为 SQL 语句,它最多搜索四个短语,如 google。我对预期短语的数量进行了硬编码,如果有人提出更正的 For 循环,请随时分享。我只有一个 For 循环可以一次处理两个短语而不是多个短语。

在我见过的其他搜索方法中,您必须按照它们在表格中的顺序输入短语,这限制了用户,尤其是在医学领域。 所以这里是.....

 Private Sub txtbox_Change()

    Dim text As String
    Dim output As String
    Dim ArrayNo As Integer
    
    text = Me.txtbox.text
    
    Dim whereclause() As String
    
        whereclause = Split(text, " ")
        
        'output = Join(whereclause, "*")  'This will cause the search to be in order of the entry/array. We really want it in any order
    
        'Using a method for 4 string phrases
        ArrayNo = UBound(whereclause)
       
       If ArrayNo < 1 Then
                output = Join(whereclause(), " Table.FieldName LIKE '*") 'String that works for first array
            ElseIf ArrayNo = 1 Then
              output = whereclause(0) & "*' And Table.FieldName Like '*" & whereclause(1) & ""
            ElseIf ArrayNo = 2 Then
               output = whereclause(0) & "*' And Table.FieldName Like '*" & whereclause(1) & "*' And Table.FieldName Like '*" & whereclause(2) & ""
            ElseIf ArrayNo = 3 Then
                output = whereclause(0) & "*' And Table.FieldName Like '*" & whereclause(1) & "*' And Table.FieldName Like '*" & whereclause(2) & "*' And Table.FieldName Like '*" & whereclause(3) & ""
        End If
            
    Dim SQL As String
    
     SQL = "SELECT Table.FieldName FROM icd10_codes_combined " & _
                " WHERE Table.FieldName LIKE '*" & output & "*' "
    
        List.Visible = True
        List.RowSource = SQL
    
    End Sub

答案 5 :(得分:0)

试试这个 VBA 代码:

Public Function ComboBoxSearch(P_ComboBox As Control, P_DefaultSql As String, P_FieldSeachName As String)
    Dim V_SearchStr As String
    If Me.ActiveControl.Name = P_ComboBox.Name Then
        V_SearchStr = P_ComboBox.Text
    Else
        V_SearchStr = P_ComboBox
    End If
    If Len(V_SearchStr) Then
        Dim P_DefaultSql2 As String
        If P_DefaultSql Like "*ORDER*" Then
            P_DefaultSql2 = Mid(P_DefaultSql, InStr(1, P_DefaultSql, "ORDER"))
            P_DefaultSql = Left(P_DefaultSql, InStr(1, P_DefaultSql, "ORDER") - 1)
        End If
        P_ComboBox.RowSource = P_DefaultSql & " WHERE " & _
        P_FieldSeachName & " LIKE '*" & V_SearchStr & "*'" & P_DefaultSql2
    Else
        P_ComboBox.RowSource = P_DefaultSql
    End If
    P_ComboBox.Dropdown
    P_ComboBox.SelLength = Len(V_SearchStr)
End Function