如何确定在 Access VBA 中键入组合框和从下拉列表中选择之间的区别?

Posted

技术标签:

【中文标题】如何确定在 Access VBA 中键入组合框和从下拉列表中选择之间的区别?【英文标题】:How can I determine the difference between typing into a combo box and selecting from a drop down in Access VBA? 【发布时间】:2016-01-14 05:19:33 【问题描述】:

早先在topic with a similar name 中提出了这个问题,但提供的答案并未真正表明这些事件将如何帮助确定有人在组合框中键入内容还是选择列表中的项目。我认为它确实回答了另一个关于如何确定某人何时完成输入的问题,但没有看到事件处理程序,我无法确定。

不幸的是,我是新来的,没有足够的声誉发表评论要求澄清,所以我必须提出一个新问题。这是我正在尝试做的事情:

我有一个在标题中带有组合框的表单,当我在组合框中键入时,我希望将我键入的字符用作表单详细信息部分的过滤器。组合框控件源和表单的记录源都使用相同的查询字符串。

我已经尝试了下面代码的多次迭代,但我无法让它正常工作。

Private Sub cmbAppName_Change()
    Dim strApp As String
    Dim nSelStart As Integer
    Dim nSelLen As Integer
    Dim nSelected As Integer
    Dim strMsg As String

    On Error GoTo ERR_SUB

    strMsg = ""

    Me.cmbAppName.SetFocus

    ' Get current selection details
    nSelStart = Me.cmbAppName.SelStart
    nSelLen = Me.cmbAppName.SelLength
    nSelected = Me.cmbAppName.ListIndex

    Me.cmbAppName.SetFocus
    strApp = Nz(Me.cmbAppName.Text, "")

    Debug.Print "Index = " & nSelected & "; SelStart = " & nSelStart & "; SelLen = " & nSelLen
    If nSelected = -1 Then
        Debug.Print "Change by typing:  " & strApp
    Else
        Debug.Print "Change by list selection:  " & strApp
    End If

    ' Get the part of the text that the user has typed
    If nSelStart > 0 Then
        strApp = Left(strApp, nSelStart)
        Debug.Print "App piece = '" & strApp & "'"
    End If

    ' If there is text, set a filter (MatchAppName = InStr(strApp, datbase_column_value)
    If strApp <> "" Then
        Me.Filter = "MatchAppName('" & strApp & "', " & DCApplications_Application_Col & ") > 0"
        Me.FilterOn = True
'        Me.txtApplication.SetFocus
'        Call DoCmd.FindRecord(strApp, acStart, False, acSearchAll, False, acCurrent, True)
'        Me.cmbAppName.SetFocus
    Else
        Me.Filter = ""
        Me.FilterOn = False
    End If

EXIT_SUB:
    ' Restore the selection in the combo box's text box
    Me.cmbAppName.SetFocus
    Me.cmbAppName.SelStart = nSelStart
    Me.cmbAppName.SelLength = nSelLen
    Exit Sub

ERR_SUB:
    If ERR.Number = 2185 Then
        strApp = Nz(Me.cmbAppName.Value, "")
        Me.cmbAppName.SetFocus
        Debug.Print "Using " & strApp
        Resume Next
    End If

    Me.Filter = ""
    Me.FilterOn = False
    Debug.Print ErrorMessage(ERR.Description, "cmbAppName_Change", ERR.Number, "Value = '" & Me.cmbAppName.Value & "'", False)
    Resume EXIT_SUB
End Sub ' cmbAppName_Change

正如您从错误处理代码中看到的那样,我经常收到错误 2185,告诉我在使用 Text 属性时我的控件没有焦点,尽管它之前有一个 SetFocus 调用。

如果有人从列表中选择(通过单击或移动选择),我想转到该记录,但我至少需要先完成上述工作。

【问题讨论】:

【参考方案1】:

在网上搜索后,我发现有零记录的详细信息部分会导致 2185 错误。显然,当过滤掉所有记录时,这样的过滤会导致问题。

Web 上的解决方案说您可以将表单的 Allow Additions 属性设置为 True,但始终在 Details 部分显示一行。如果详细信息部分中的行包含将显示在“添加”行中的控件,这可能会特别令人困惑。此外,在导致“详细信息”部分的记录为零的字符之后,我仍然会输入其他字符时出错。

最后,我用一个简单的文本控件替换了组合框来过滤“详细信息”部分。当 Details 部分有行时,我关闭 Allow Additions 并使控件可见;当它没有行时,我打开允许添加并隐藏控件。

这是我使用的代码:

Private Sub txtApplicationFilter_Change()
    Dim strApp As String
    Dim nSelStart As Integer
    Dim nSelLen As Integer
    Dim strFilter As String
    Dim strQuery As String
    Dim strWhere As String
    Dim nRecs As Integer
    
    On Error GoTo ERR_SUB
    
    ' Save text selection
    nSelStart = Me.txtApplicationFilter.SelStart
    nSelLen = Me.txtApplicationFilter.SelLength
   
    ' Get application name typed and selection information
    strApp = Nz(Me.txtApplicationFilter.Text, "")
    strFilter = "[" & DCApplications_Application_Col & "] LIKE '*" & EscapeQuotes(strApp) & "*'"
    nRecs = DCount("[" & DCApplications_Application_Col & "]", LocalTableName(DCApplications_Tab), strFilter)

    ' Kludge code to prevent various errors (like 2185) when no records are returned in the form
    Call UpdateList(nRecs)
    
    ' Update the record source to reflect the filtered list of apps
    strWhere = " WHERE APPS." & strFilter
    strQuery = strSelect & strFrom & strWhere & strOrderBy
    Me.RecordSource = strQuery

    ' 20200423 SHM: Restore or update filter to avoid  issues with Delete and Backspace and applications with spaces in their names
    Me.txtApplicationFilter.SetFocus
    Me.txtApplicationFilter = strApp
    Me.txtApplicationFilter.SelStart = nSelStart
    Me.txtApplicationFilter.SelLength = nSelLen

EXIT_SUB:
    Me.btnAddNew.enabled = (Nz(Me.txtApplicationFilter, "") <> "")
    Exit Sub
    
ERR_SUB:
    ' NOTE:  ErrorMessage is a helper function that basically displays a form displaying the error
    Call ErrorMessage(ERR.Description, "txtApplicationFilter_Change", ERR.Number, "Filter = " & strApp & " Records = " & nRecs)
    
    Resume EXIT_SUB
    Resume Next
End Sub ' txtApplicationFilter_Change

Private Sub UpdateList(nRecs As Integer)
    Dim bShowControls As Boolean
    
    On Error GoTo ERR_SUB
    
    bShowControls = (nRecs > 0)
    
    ' Kludge code to turn off checkbox control source
    If bShowControls Then
        strSelect = strSelectStart & ", (" & strAppUser & ") AS " & strCtrlSource
        Me.chkTestedByMe.ControlSource = strCtrlSource
    Else
        strSelect = strSelectStart
        Me.chkTestedByMe.ControlSource = ""
    End If
    
    ' Kludge code to prevent various errors (like 2185) when no records are returned in the form
    ' Turning on AllowAdditions prevents errors when no records are returned.
    ' However, that puts an empty row in the form, but the controls are showing, so we have to hide them to prevent confusing the user.
    Me.AllowAdditions = Not bShowControls
    Me.btnAddExisting.visible = bShowControls
    Me.chkTestedByMe.visible = bShowControls
EXIT_SUB:
    Exit Sub
    
ERR_SUB:
    Call ErrorMessage(ERR.Description, "UpdateList", ERR.Number, " Records = " & nRecs)
    
    Resume EXIT_SUB
    Resume Next
End Sub ' UpdateList

【讨论】:

【参考方案2】:

我会使用变通方法来解决这个问题

下面的一个简单代码演示了使用组合框的 Tag 属性和 keypress 事件 以及 change 事件 的工作,我希望它可以应用到您的代码中

Private Sub Combo2_Change()
    If Combo2.Tag = 1 Then
        Text4 = "change - from key"
    Else
        Text4 = "change - from select"
    End If
    Combo2.Tag = 0
End Sub

Private Sub Combo2_KeyPress(KeyAscii As Integer)
    Combo2.Tag = 1
End Sub

不要忘记在设计视图中将组合框的标签属性设置为 0,以避免在比较空标签与数字时出错

【讨论】:

以上是关于如何确定在 Access VBA 中键入组合框和从下拉列表中选择之间的区别?的主要内容,如果未能解决你的问题,请参考以下文章

Microsoft Access 组合框和 vba 代码 2007

如何在 MS Access 2010 中使用 VBA 选择多值组合框的值?

如何在VBA中的用户窗体上使用组合框和文本框来搜索和查找活动Excel电子表格中的数据?

准时下班系列!Access合集之第7集—自定义多选组合框和VBA处理多值字段实例

为什么Access VBA下拉方法不起作用?

为啥 Access VBA 下拉方法不起作用?