|
VBA code to Find a Record on any open form or subform in Access. Often called on AfterUpdate event of Combo Box.
In this example, the first column of the unbound (no ControlSource) combobox to Find Contact in the form header isn't visible. It stores the CID, contact ID, which is the AutoNumber primary key of the table that the form is based on.
The combobox AfterUpdate event calls FindRecordN and sends the form reference (Me) and the key fieldname ("CID"). All other parameters are optional. The value to find is whatever is chosen in the ActiveControl (the combobox).
FindRecordN is also used for the "Go to Head" (contact) and "Go Back" command buttons since the table has a self-join to another contact record for the head of household or company that a contact is associated with.
Example Access database file has one form, one module with FindRecordN code, and a few tables.
FindRecordN_Contact_250901_s4p__ACCDB.zip (90 kb, unzips to an Access ACCDB database file. )
mod_FindRecordN_s4p__BAS.zip (2 kb, unzips to an Access BAS file with VBA code. )
This may be used freely, but you may not sell it in whole or in part. You may include it in applications you develop for others provided you keep attribution, mark your modifications, and share this source link.
Remember to UNBLOCK files you download to remove the Mark of the Web. Here are steps to do that: https://msaccessgurus.com/MOTW_Unblock.htm
Using With pForm and End With enhances performance and makes code easier to read. Anything starting with a dot (.) between these two statements is a property or method of the passed form.
FindRecordN is often called on the AfterUpdate event of an unbound combo box or listbox to pick a record to find. In these cases, the key ID to find will be read from the active control. If the active control is Null then the code exits because there is nothing to look for. Unless pbClear is set to False, the combo box (or whatever control is active) will be cleared after the value is read.
When pnKeyID is -99, the active control has the key value to find, which is the default. So if you might want to actually find a record whose ID is -99, then modify the code to use a different number as an indicator.
If a value (other than -99) for pnKeyID is sent, then the active control does not matter, and nothing will be set to Null either. So FindRecordN can be called to find a record where the key ID to find is determined in code. It can also be used to find a record on a subform, or another open form.
In most cases, the key ID will be a Long Integer, but you can make another version where it is a string and add delimiters where necessary. Name it something like FindRecordStr. Or perhaps make a function called FindRecordWhere that takes a Where clause with anything you want.
A copy of the form recordset, the RecordsetClone, is searched for the key field being equal to the key value. If a record is found, RecordsetClone.NoMatch is False ... and Not False is True. That record is made active on the form by setting the Bookmark to be the same as the bookmark found in the RecordsetClone.
You could also search the form recordset directly (instead of using RecordsetClone). However using the clone leaves the current record active in the event what you're looking for isn't found. And its considered better practice.
If the record to find is found in the RecordsetClone, if there are unsaved changes to the record on the form (Dirty), they are saved before leaving the active record. It is a good idea to specifically save a dirty record before moving the record pointer.
If a control name to set focus to is specified, that control is made active and the code exits.
Although this is defined to be a function that returns True or False, I rarely use the return value and normally treat this like a Sub (that doesn't return a value).
Returns True if the record is found or False if it isn't.
Find a Record on any open form with a long integer primary key.
Option Compare Database Option Explicit ' module name: mod_FindRecordN_s4p '*************** Code Start ***************************************************** ' Purpose : Find a Record on an open form for a key field. ' perhaps call on unbound combo or listbox AfterUpdate ' Author : crystal (strive4peace) ' Return : Boolean ' This code: https://msaccessgurus.com/VBA/Code/Form_FindRecordN.htm ' LICENSE : ' You may freely use and share this code, but not sell it. ' Keep attribution. Mark your changes. Use at your own risk. '------------------------------------------------------------------------------- ' FindRecordN '------------------------------------------------------------------------------- Function FindRecordN(pForm As Form _ ,psKeyFieldname As String _ ,Optional psCtrlName_SetFocus As String = "" _ ,Optional pnKeyID As Long = -99 _ ,Optional pbClear As Boolean = True _ ) As Boolean '080817 s4p, 250901 'PARAMETERs ' pForm is the form to find a record on. ' psKeyFieldname is the name of the primary key field. ' psCtrlName_SetFocus is the control name ' to set focus to after finding. ' pnKeyID is the Long Integer value ' of the primary key value to find. ' If not sent, the ActiveControl value will be used. ' pbClear is True to clear the ActiveControl value ' after reading. ' You may not want to do this if control is a listbox. ' If pnKeyID is specified, no value will be cleared 'set up Error Handler On Error GoTo Proc_Err 'initialize return value to FALSE FindRecordN = False With pForm 'if value not sent, check ActiveControl If pnKeyID = -99 Then 'if nothing is picked in the active control, exit If IsNull(.ActiveControl) Then Exit Function 'set value to look up by what is selected pnKeyID = .ActiveControl 'clear the choice to find If pbClear Then .ActiveControl = Null End If 'save current record if changes were made If .Dirty Then .Dirty = False 'find the first value that matches .RecordsetClone.FindFirst psKeyFieldname _ & "= " _ & pnKeyID 'if a matching record was found, then move to it If Not .RecordsetClone.NoMatch Then .Bookmark = .RecordsetClone.Bookmark 'DoEvents 'uncomment if necessary 'set return value to TRUE FindRecordN = True Else GoTo Proc_Exit End If If psCtrlName_SetFocus <> "" Then 'controlname to set focus to, optional .Controls(psCtrlName_SetFocus).SetFocus End If End With 'pForm Proc_Exit: On Error GoTo 0 Exit Function Proc_Err: Resume Proc_Exit End Function '*************** Code End *******************************************************
Option Compare Database Option Explicit '250901 '*************** Code Start ***************************************************** ' cbf: f_FindRecordN_Contacts '------------------------------------------------------------------------------- ' Purpose : demonstrate uses of FindRecordN ' Author : crystal (strive4peace) ' This code: https://msaccessgurus.com/VBA/Code/Form_FindRecordN.htm ' Code List: https://msaccessgurus.com/code.htm ' LICENSE : ' You may freely use and share this code, but not sell it. ' Keep attribution. Mark your changes. Use at your own risk. '------------------------------------------------------------------------------- ' Find / Go to '------------------------------------------------------------------------------- Private Sub Find_Contact_AfterUpdate() '250831 strive4peace 'find record for whatever value is in the combobox 'set focus to the MainName control after finding Call FindRecordN(Me, "CID", "MainName") End Sub Private Sub cmd_GoBack_Click() '250831 Dim nCID_last As Long 'PK value of last record to go back to nCID_last = TempVars!tvCID_last If nCID_last <> 0 Then 'before leaving record, save PK value of current record 'to come back to TempVars!tvCID_last = Nz(Me.CID,0) 'find record, set focus to the Note control Call FindRecordN(Me, "CID", "NoteCtc",nCID_last) End If End Sub Private Sub cmd_GotoHead_Click() '250831 Dim nCID As Long With Me.CID_ 'parent contact nCID = Nz(.Value,0) If nCID = 0 Then .SetFocus MsgBox "Choose a Head contact if you want to go there" _ ,, "Head contact not filled" .Dropdown Exit Sub End If End With 'store CID before moving for Go Back TempVars!tvCID_last = CLng(Nz(Me.CID,0)) 'find record Call FindRecordN(Me, "CID", "NoteCtc",nCID) End Sub '------------------------------------------------------------------------------- ' Form '------------------------------------------------------------------------------- Private Sub Form_Load() '181008 strive4peace 'sort by name Me.OrderBy = "[MainName] & [NameA] & [NameB]" Me.OrderByOn = True End Sub Private Sub Form_Current() '181012 strive4peace 'for highlighting current record Me.CurrentID = Nz(Me.CID,0) End Sub '------------------------------------------------------------------------------- ' Close '------------------------------------------------------------------------------- Private Sub cmd_Close_Click() '250831 With Me If .Dirty Then .Dirty = False End With DoCmd.Close acForm,Me.Name End Sub '------------------------------------------------------------------------------- ' Checkboxes and textbox 'labels' '------------------------------------------------------------------------------- Private Sub IsACTIV_Click() '181011 s4p With Me.IsACTIV .Value = Not .Value End With End Sub Private Sub IsACTIV_txtLabel_Click() '181011 s4p With Me.IsACTIV .Value = Not .Value End With End Sub Private Sub IsHuman_Click() With Me.IsHuman .Value = Not .Value End With End Sub Private Sub IsHuman_txtLabel_Click() '181011 s4p With Me.IsHuman .Value = Not .Value End With End Sub '------------------------------------------------------------------------------- ' Controls for Conditional Formatting '------------------------------------------------------------------------------- Private Sub txt_InactiveGray_GotFocus() '250831 'if gray background for inactive gets focus, move it Me.MainName.SetFocus End Sub Private Sub txtHighlight_Click() '181012 s4p 'if highlight to indicate current record gets focus, move it Me.MainName.SetFocus End Sub '------------------------------------------------------------------------------- ' drop combo lists '------------------------------------------------------------------------------- Private Sub Find_Contact_MouseUp( _ Button As Integer,Shift As Integer _ ,X As Single,Y As Single) '250831 Call DropMe End Sub Private Sub Title_GotFocus() '250831 Call DropMeIfNull End Sub Private Sub Title_MouseUp( _ Button As Integer,Shift As Integer _ ,X As Single,Y As Single) '250831 Call DropMeIfNull End Sub Private Sub Sufx_GotFocus() '250831 Call DropMeIfNull End Sub Private Sub Sufx_MouseUp( _ Button As Integer,Shift As Integer _ ,X As Single,Y As Single) '250831 Call DropMeIfNull End Sub Private Sub CatID_GotFocus() '250831 Call DropMeIfNull End Sub Private Sub CatID_MouseUp( _ Button As Integer,Shift As Integer _ ,X As Single,Y As Single) '250831 Call DropMeIfNull End Sub Private Sub Gender_GotFocus() '250831 Call DropMeIfNull End Sub Private Sub Gender_MouseUp( _ Button As Integer,Shift As Integer _ ,X As Single,Y As Single) '250831 Call DropMeIfNull End Sub Private Sub CID__GotFocus() '250831 Call DropMeIfNull End Sub Private Sub CID__MouseUp( _ Button As Integer,Shift As Integer _ ,X As Single,Y As Single) '250831 Call DropMeIfNull End Sub Private Function DropMeIfNull( _ ) As Boolean ' s4p, Drop list for Combo Box if no value 'usually used for a Combo Box 'so if nothing is filled, the list will drop On Error Resume Next ' With Screen.ActiveControl With Me.ActiveControl If IsNull(.Value) Then .Dropdown End With End Function Private Function DropMe() 's4p. Drop list for Combo Box On Error Resume Next ' Screen.ActiveControl.Dropdown Me.ActiveControl.Dropdown End Function '*************** Code End *******************************************************
Download MyContacts, a free Access database for managing personal contact information.
here's the link to copy:
https://msaccessgurus.com/VBA/Code/Form_FindRecordN.htm
or, in older browsers,
http://msaccessgurus.com/VBA/Code/Form_FindRecordN.htm
This handy procedure makes it quick and easy to implement functionality to find records. Pass a reference to any form or subform that's open. FindRecordN is generally used several times in Access projects that I develop or help others to develop.
The "N" at the end of FindRecordN means that it expects a number for the key value — and specifically, a long integer.
Do you like those big checkboxes? And "labels" that are bold or not using conditional formatting? Have a look to see how it's done ... hint: look at the Format code on the property sheet too.