Reputation: 27239
I have a bound form in Single Form view.
I want to mimic the behavior of the Search box in the Record Navigation Buttons, but also have more control. The problem I am facing is that when my users search for a record, sometimes they accidentally start typing over a record when it's found (say after 3 or 4 letters are entered and they are still typing the search term) and the original data gets lost. Since these fields require data entry at times, locking them isn't really an option at this point.
My thought was to turn the Navigation Buttons off and mimic this feature through VBA or through a macro, and set the focus on another locked field when the value searched for is found (also with options to find the next one or to alert that something was, or was not found).
I have tried working with macros and VBA already, but cannot get it work.
I have this code (and have played with the arguments a bit), but it will only search the current record (and not all records) and either moves to the next record, or no record at all if I comment out the FindNext
line.
Private Sub cmdFind_Click()
Dim sText As String
sText = Me.txtSearch 'a text box where user enters search term
DoCmd.FindRecord sText, acAnywhere, False, acDown, True, acCurrent
DoCmd.FindNext
End Sub
Obviously, I am missing something. Can someone lend some insight or an alternative approach.
Upvotes: 1
Views: 3938
Reputation: 97101
Seems you want to find the first record where any field matches the search text.
In that case, use acAll
instead of acCurrent
for the sixth argument (OnlyCurrentField) to DoCmd.FindRecord
.
FindRecord
will be examining the form's controls, and that includes txtSearch
. So clear out that text box's value immediately before calling FindRecord
. Otherwise every row in the form's Record Source will be interpreted as a match. That happens because there is no way to tell FindRecord
to "look for a match in every control except txtSearch
."
That explanation should be clearer if you test your original code with the form in Continuous Form view (temporarily). With that code, FindRecord
always put you at the first record. And then DoCmd.FindNext
put you at the second record.
Anyway here is code tested in Access 2010 which does what I think you want. I used the text box's After Update event instead of a command button.
Private Sub txtSearch_AfterUpdate()
Dim strSearch As String
If Not IsNull(Me!txtSearch.Value) Then
strSearch = Me!txtSearch.Value 'a text box where user enters search term
' txtSearch contains the search text ...
' so remove it to avoid matching the first (and every) record
Me!txtSearch.Value = Null
DoCmd.FindRecord FindWhat:=strSearch, _
Match:=acAnywhere, _
MatchCase:=False, _
Search:=acDown, _
SearchAsFormatted:=True, _
OnlyCurrentField:=acAll ' instead of acCurrent
' restore search text to text box
Me!txtSearch.Value = strSearch
End If
End Sub
Upvotes: 2
Reputation: 27634
I think HansUp has posted the solution... but since I was coming up with a different way of searching (via RecordsetClone
and FindFirst
), I'll post it anyway, maybe it is of use. :)
Private Sub cmdFind_Click()
Static RS As Recordset
Static sText As String
Dim curText As String
Dim newSearch As Boolean
Dim sCrit As String
curText = Nz(Me.txtSearch)
If curText = "" Then Exit Sub
' If text hasn't changed, use FindNext
If curText = sText Then
newSearch = False
Else
sText = curText
newSearch = True
End If
' First call?
If RS Is Nothing Then
Set RS = Me.RecordsetClone
newSearch = True
End If
' The field you are searching in
sCrit = "[Text1] LIKE '*" & sText & "*'"
If newSearch Then
RS.FindFirst sCrit
Else
RS.FindNext sCrit
End If
If Not RS.NoMatch Then
' If found, navigate to the record
Me.Bookmark = RS.Bookmark
Else
MsgBox "No (more) matches)", vbInformation
End If
End Sub
Upvotes: 3