MS Access:延迟后是否执行“ onchange”事件操作?

时间:2018-07-30 17:03:08

标签: vba ms-access

早上好!

我在Microsoft Access中具有“精美”搜索功能,在您在搜索字段中键入时,可能的选项列表会缩小。不幸的是,计算机和服务器无法跟上这些快速的数据查询。

当前,该命令用于使用搜索框的“ onchange”功能中的字段重新查询。我想添加一个延迟,以便仅在搜索框未更改一秒钟时才运行重新查询。因此,如果有人输入8个字母的单词,则不会执行8个查询。

我目前的想法是,我知道必须有更好的东西。

“在更改时,将搜索框值设置为X并等待1秒钟。1秒钟后,如果X =搜索框值,请运行重新查询。问题是它将迅速重写X值并产生'wait '为每个字母浮动的命令。

希望有一种方法可以编写一个事件触发器“字段X已更改,但在过去一秒内未更改。”

谢谢!

根据要求,这是我当前的代码

'Create a string (text) variable
    Dim vSearchString As String
'Populate the string variable with the text entered in the Text Box SearchFor
    vSearchString = SearchFor.Text
'Pass the value contained in the string variable to the hidden text box SrchText,
'that is used as the sear4ch criteria for the Query QRY_SearchAll
    SrchText = vSearchString
'Requery the List Box to show the latest results for the text entered in Text Box SearchFor
    Me.SearchResults.Requery
    Me.SearchResults2.Requery
'Tests for a trailing space and exits the sub routine at this point
'so as to preserve the trailing space, which would be lost if focus was shifted from Text Box SearchFor
    If Len(Me.SrchText) <> 0 And InStr(Len(SrchText), SrchText, " ", vbTextCompare) Then
        'Set the focus on the first item in the list box
            Me.SearchResults = Me.SearchResults.ItemData(1)
            Me.SearchResults.SetFocus
        'Requery the form to refresh the content of any unbound text box that might be feeding off the record source of  the List Box
            DoCmd.Requery
        'Returns the cursor to the the end of the text in Text Box SearchFor,
        'and restores trailing space lost when focus is shifted to the list box
            Me.SearchFor = vSearchString
            Me.SearchFor.SetFocus
            Me.SearchFor.SelStart = Me.SearchFor.SelLength
            Exit Sub
    End If
'Set the focus on the first item in the list box
'    Me.SearchResults = Me.SearchResults.ItemData(1)
    Me.SearchResults.SetFocus    
'Requery the form to refresh the content of any unbound text box that might be feeding off the record source of  the List Box
    DoCmd.Requery
'Returns the cursor to the the end of the text in Text Box SearchFor
    Me.SearchFor.SetFocus
    If Not IsNull(Len(Me.SearchFor)) Then
        Me.SearchFor.SelStart = Len(Me.SearchFor)
    End If

很明显,这不是我的代码,它来自互联网上的某个地方。对于本地存储的数据库,它的工作效果非常好,但是一切都转移到了我们的Sharepoint服务器上,该服务器运行在由麻醉性沙鼠支撑的发霉地下室中的386上。

4 个答案:

答案 0 :(得分:2)

您可以简单地使用当前表单的计时器。无需单独的表格或其他任何内容。

Private Sub DoSearch()

    ' Your current code
    ' but you should look into removing as many "Requery" from there as possible!

End Sub

Private Sub SearchFor_Change()

    ' Wait for x Milliseconds until the search is started.
    ' Each new change restarts the timer interval.
    ' Use 1000 (1 s) for slow typists or a really slow server
    ' 200 ms feels right for a normal typist
    Me.TimerInterval = 200

End Sub

Private Sub Form_Timer()

    ' Disable timer (will be enabled by the next SearchFor_Change)
    Me.TimerInterval = 0
    ' Now run the search
    DoSearch

End Sub

注意:您可能需要将某些光标处理代码从DoSearch()移到SearchFor_Change(),具体是:

Me.SearchFor.SelStart = Len(Me.SearchFor)

答案 1 :(得分:1)

为更改事件中的逻辑分配一个快捷键,例如(Ctrl + J),并在键入搜索关键字完成后按需调用。

  1. 删除更改事件。
  2. 创建具有on change事件逻辑的其他过程并分配快捷键
  3. 按快捷键即可获取搜索建议

其他方法

将以下验证添加到Change事件中,该事件将检查字符串的长度,并且仅在字符串的长度为> = 8时才会触发

Private Sub txtSearch_Change()

    If Len(Nz(txtSearch.Text, 0)) >= 8 Then


    End If

End Sub

答案 2 :(得分:1)

由于我几乎不使用MS Access表单,因此我要走出我的舒适区,但是为什么您要对服务器/数据库这么麻烦呢?以我的经验,每个查询花费相同的时间,无论它返回1条记录还是100,000条记录。

因此,即使在用户键入任何内容之前,为什么不只执行一个查询就返回排序列表。之后,几乎不需要花时间就可以使用VBA处理结果并在列表中找到所有以用户键入的内容开头的内容(毕竟是按顺序排序的)。

除了初始负载外,数据库本地用户或世界另一端的用户都将从您的界面中获得相同的快速响应。

----------

就像我说的那样,我并没有太多地使用Access Forms,所以这更像是一个严格的VBA解决方案。也许有一种更好的方法可以做到,而不必超出别人可能会启发我们的“访问表单”框。

基本上,您应该在加载表单时或需要时调用LoadItemList

Public dbConn As ADODB.Connection
Private ItemList As Variant
Private RecordCount As Long

Sub LoadItemList()
Dim SQL As String
Dim RS As New ADODB.Recordset

    SQL = "SELECT T.Name FROM Table T"
    Set RS = dbConn.Execute(SQL)
    If Not RS.EOF Then
        ItemList = RS.GetRows
        RecordCount = UBound(ItemList, 2) - LBound(ItemList, 2) + 1
    End If
End Sub

然后将DoCmd.Requery替换为AddItemtoCombobox SearchResults, SearchFor.Text

Sub AddItemtoCombobox(Control As ComboBox, Filter As String)
Dim Index As Long
    Control.Clear
    If Not IsEmpty(ItemList) Then
        For Index = 0 To RecordCount - 1
            If ItemList(Index) Like Filter Then Control.AddItem ItemList(Index)
        Next
    End If
End Sub

再次,也许Access中内置了一种更好的方法...

答案 3 :(得分:0)

您要寻找的技术术语是去抖动。

您可以在更改事件中进行操作,跟踪当前的搜索字符串

关于伪代码。

sub onChange()
   Form.timerinterval = 0
   setSearchString
   form.timerinterval = delay

因此,根据解释,如果调用了您的on change,请禁用计时器。更新搜索字符串,然后将计时器重置为在一定时间后触发。表单应该是包含您要执行的代码的隐藏表单