The fact that you are calling the FindFirst method rather than filtering the form suggests that the SONO column is a candidate key of the form's underlying table. If so the combo box's RowSource should return rows which are guaranteed to exist in the table, so the user will not be able to select an unknown value. To cater for the user typing in an unknown value the control's NotInList event procedure can give the user the option of inserting a new row into the table. The following example from one of my demo files is for navigating to a row in a form bound to a Contacts table. Firstly the control's RowSource is:
SELECT
ContactID,
FirstName & " " & LastName,
1 As SortColumn,
LastName,
FirstName
FROM
Contacts
UNION
SELECT
0,
"<New Contact>",
0,
"",
""
FROM
Contacts
ORDER BY
SortColumn,
LastName,
FirstName;
The control's AfterUpdate event procedure is:
Private Sub cboGotoContact_AfterUpdate()
Const MESSAGETEXT = "No matching record"
Dim ctrl As Control
Set ctrl = Me.ActiveControl
If Not IsNull(ctrl) Then
If ctrl = 0 Then
' go to new record and move focus to FirstName control
DoCmd.GoToRecord acForm, Me.Name, acNewRec
Me.FirstName.SetFocus
Else
With Me.RecordsetClone
.FindFirst "ContactID = " & ctrl
If Not .NoMatch Then
' go to record by synchronizing bookmarks
Me.Bookmark = .Bookmark
Else
MsgBox MESSAGETEXT, vbInformation, "Warning"
End If
End With
End If
End If
End Sub
and its NotInList event procedure is:
Private Sub cboGotoContact_NotInList(NewData As String, Response As Integer)
Dim ctrl As Control
Dim strMessage As String
Dim strFirstName As String, strLastName As String
Set ctrl = Me.ActiveControl
strMessage = "Add " & NewData & " to list?"
strFirstName = Left(NewData, InStr(NewData, " ") - 1)
strLastName = Mid(NewData, InStr(NewData, " ") + 1)
'if user confirms insert move form to new record
' and insert values into first and last name controls
If MsgBox(strMessage, vbYesNo + vbQuestion) = vbYes Then
Response = acDataErrContinue
ctrl.Undo
DoCmd.GoToRecord acForm, Me.Name, acNewRec
Me.FirstName = strFirstName
Me.LastName = strLastName
Else
Response = acDataErrContinue
ctrl.Undo
End If
End Sub
Where the column whose values are listed in the combo box is not a candidate key, the following example is again for a contacts form, but in this case to return rows where the LastName column's value is that selected in the combo box. The control's RowSource in this case is:
SELECT
LastName,
FROM
Contacts
UNION
SELECT
"All Names",
FROM
Contacts
ORDER BY
SortColum,
LastName;
Its AfterUpdate event procedure filters the form to those rows matching the selected value. The code calls the DLookup function to determine if any such rows exist, and if this returns a value filters the form, or if a Null is returned informs the user of the failure to match the match the value entered:
Private Sub cboLastname_AfterUpdate()
Const MESSAGETEXT = "No matching records found."
Dim ctrl As Control
Dim strFilter As String
Set ctrl = Me.ActiveControl
strFilter = "LastName = """ & ctrl & """"
If ctrl = "All names" Then
' turn off filter
Me.FilterOn = False
Else
If Not IsNull(DLookup("ContactID", "Contacts", strFilter)) Then
' flter form to name selected in combo box
Me.Filter = strFilter
Me.FilterOn = True
Else
' inform user if no matching records found and show all records
MsgBox MESSAGETEXT, vbInformation, "Warning"
Me.FilterOn = False
Me.Requery
End If
End If
End Sub
In this example no opportunity is given for the user to insert a new row, but an alternative to the above approach would, subject to user confirmation, be to use the control's NotInList event procedure to move the form to an empty new record, and assign the value of the NewData argument to a LastName control.
You'll find the above examples in FindRecord.zip in my Dropbox public databases folder at: