Search for subform record based on text box

carmens 6 Reputation points
2022-12-12T18:31:50.943+00:00

I am trying to bring up a form record based on text entered in a text box.

The form "Furnace + Header Data Form" is a parent form, with 2 subforms called "Header Data Form" and "Surrogate Data Form". This question is in relation to the "Header Data Form" subform.
The parent form is used to enter data on different furnace runs, which is connected to the table "Furnace Run Data". Each furnace run will have several headers in it, and each header has a serial number. I added a subform called "Header Data Form", which will allow the user to enter information specific to each header serial number. Data that is entered into the "Header Data Form" subform adds data to the "Header Data" table and is connected to the furnace data table via the Furnace Run ID. The Furnace Run ID is on both the parent form and as an invisible field on the Header Data subform. All fields on the Header Data Form are connected to the Header Data Table.

As a side note, there is a button within this subform to add a new record. Once the button is clicked, a new record with the furnace data and header data is saved and the header data subform is cleared. When you enter more data into the header data form and click the add button, another line (with the same Furnace Run ID) will be added to the header data table. No data is added to the furnace table. This all works great. There are multiple records in the Header Data table for each Furnace Run ID.

Initially, I was trying to find the record based on a text field named "Header SN Field" on the subform named "Header Data Form". This text field is connected to the "Header SN" Field from the "Header Data" table. Upon clicking the search button (on the Header Data subform), I wanted to use the text typed into the Header SN Field to search for the previous record in the Header Data table that has Header SN (field in Header Data table) = Header SN Field (field in form where user enters text). I could get this to run with no errors, but I kept getting the message saying that no matching record was found, even though there definitely is an existing record with the matching Header SN. My code for this is below.

Private Sub Search_SN_Button_Click()
If ([Header SN Placeholder] & vbNullString) = vbNullString Then Exit Sub
Dim strCriteria As String
Dim rs As DAO.Recordset

Set rs = Me.RecordsetClone  
  
strCriteria = "[Header SN]='" & Me.[Header SN Field] & "'"  
  
rs.FindFirst strCriteria  
  
If rs.NoMatch Then  
    MsgBox "Sorry, no such record '" & [Header SN Field] & "' was found.", _  
           vbOKOnly + vbInformation  
Else  
    Me.Bookmark = rs.Bookmark  
End If  
rs.Close  
txtGoTo = Null  

End Sub

After searching a bit, I thought the solution might be to have a text box and search button on the main form instead. The text box on the main form is called "HeaderSN". I am still getting the message that there is no existing record that matches. My code for this is below.
Private Sub Search_Header_SN_Record_Click()
If (HeaderSN & vbNullString) = vbNullString Then Exit Sub
Dim strCriteria As String
Dim rs As DAO.Recordset

Set rs = Me.[Header Data Form].Form.RecordsetClone  
  
strCriteria = "Header SN = '" & Me.HeaderSN & "'"  
  
rs.FindFirst strCriteria  
  
If rs.NoMatch Then  
    MsgBox "Sorry, no such record '" & [HeaderSN] & "' was found.", _  
           vbOKOnly + vbInformation  
Else  
    Me.[Header Data Form].Form.Bookmark = rs.Bookmark  
End If  
rs.Close  
txtGoTo = Null  

End Sub

Can someone please help me with this? I have tried a million different ways to do this and have been searching for days on different forums but I can't figure it out.

Microsoft 365 and Office | Access | Development
Developer technologies | Visual Basic for Applications

Locked Question. You can vote on whether it's helpful, but you can't add comments or replies or follow the question.

31 answers

Sort by: Oldest
  1. Ken Sheridan 3,581 Reputation points
    2022-12-15T21:32:04.137+00:00

    The reason for filtering the form rather than navigating to a specific record in my demo is that, in my case, there can be more than one parent record which matches the search criterion, so navigating to a record would just go to the first match. It makes more sense in that context to filter the form so that all of the matching records are together. In yours you could write the code to move the form to the first matching record, as there will be only one record which matches the criterion.

    A subform control is a control in a parent form which houses the subform. The subform itself is the source object of the subform control. The control might or might not have the same name as the subform itself.

    Where my code refers to ctrl this is an object variable. In my case it returns a reference to the ActiveControl because the code is in the combo box's AfterUpdate event procedure so the ActiveControl is the combo box. The default property of a control is its Value property, so when the code refers to ctrl without specifying any property of it, it is interpreted as a reference to the current value of the control, which in this case is the value of the ContactID field to which the combo box is bound, although the ContactID column is hidden and you see the contact's name from the second column of its RowSource. It would equally well work for a text box, though, because that will probably contain a string rather than a number, the value would need to be wrapped in literal quotes characters, e.g.

    WHERE ContactName = """ & ctrl & """)"  
    

    In this each literal quotes character is represented by a contiguous pair of quotes characters, "", which is how a quotes character can be included in a string itself delimited by quotes characters. Some people use a single quote character, ' instead, but that would not work with names like mine in its original non-anglicized form, Cináed O'Siridean, because it includes a single quote character as an apostrophe.

    You are quite right, the IN operator does return a TRUE or FALSE value. ProjectID is the primary key of the parent form's table, so the expression will return TRUE if the ProjectID of a record in the Projects table has at least one match in the subform's ContactProjects table where the ContactID matches the value of the combo box. The record will thus be returned when the parent form is filtered. Where there is no match it will return FALSE, and then the record won't be returned.

    Was this answer helpful?

    1 person found this answer helpful.
  2. carmens 6 Reputation points
    2022-12-19T18:07:06.277+00:00

    @Ken Sheridan
    Update - got it to work a bit more. Instead of having a button and the text box on the subform, I added a text box named HeaderSN and a search button on the parent form. The subform control in my case is the same as the name of the subform (Header Data Form). I used the code you used (see below), but now I am only getting data to fill in the fields in the parent form and not the subform. What am I missing here? Is this where the bookmark action would come into play? Why does the main form not need to be bookmarked but the subform does?

    For future reference, is it possible to do this where the text box and/or the search button are on the subform instead of the parent form?

    Private Sub Search_Header_SN_Record_Click()
    Const MESSAGETEXT = "No matching records found."
    Dim ctrl As Control
    Dim strFilter As String

     Set ctrl = Me.[HeaderSN]  
        'HeaderSN is text field on parent form  
     strFilter = "[Furnace Run ID] IN(SELECT [Furnace Run ID] " & _  
         "FROM [Header Data] WHERE [Header SN] = """ & ctrl & """)"  
          
     If Nz(ctrl, 0) = 0 Then  
         ' turn off filter  
         Me.FilterOn = False  
         Me.[Header Data Form].Form.FilterOn = False  
     Else  
         If Not IsNull(DLookup("[Header SN]", "[Header Data]", "[Header SN] = '" & ctrl & "'")) Then  
             ' filter form to name selected in text box  
             Me.Filter = strFilter  
             Me.FilterOn = True  
                  
             ' filter subform to selected Header SN  
             Me.[Header Data Form].Form.Filter = "[Header SN] = '" & ctrl & "'"  
             Me.[Header Data Form].Form.FilterOn = True  
         Else  
             ' inform user if no matching records found and show all records  
             MsgBox MESSAGETEXT, vbInformation, "Warning"  
             Me.FilterOn = False  
             Me.Requery  
             Me.[Header Data Form].Form.FilterOn = False  
         End If  
     End If  
    

    End Sub

    Was this answer helpful?

    1 person found this answer helpful.
    0 comments No comments
  3. Ken Sheridan 3,581 Reputation points
    2022-12-19T18:31:41.963+00:00

    Before you can call the FindFirst method of the subform's recordset clone you need to navigate to the correct record in the parent form. This will reload the subform's recordset with the rows which reference the then current row in the parent form. Until you do that the subform's recordset will be restricted to those rows which match the now current row in the parent form, which is unlikely to be the correct row.

    In my demo the parent form is filtered to the row or rows whose primary key value is the value of the relevant foreign key in the subform's table where the value of the sought column matches that entered in the unbound control in the parent form. This is done by means of the IN operator and a subquery built in the code in the unbound control's AfterUpdate event procedure. Rather than filtering the subform the FindFist method could be called if you are seeking a value which references only one row in the parent form's recordset..

    In my case the FindFirst method is then called in the subform's Current event procedure, but if you wish to call it by means of a button in the subform you can do, but to move the parent form to the relevant record first you'd need to reference the parent form by means of the Parent property of the subform, and find relevant record in that recordset's clone before synchronizing the clone's bookmark with the parent form's bookmark. Then you can call the FindFirst method of the subform's recordset's clone, and synchronize the bookmarks to move to the relevant row in the subform.

    Was this answer helpful?

    2 people found this answer helpful.
    0 comments No comments
  4. carmens 6 Reputation points
    2022-12-19T19:03:22.437+00:00

    @Ken Sheridan

    The current code I have (button and text box on parent form), based on the second example in your first response, does not fill in any fields in the subform, just the parent form (code in my last response). What am I missing? My ultimate goal is for this button/text box to be on the subform (questions on this below), but it might take me a bit longer to figure out so I am ok with it being on the main form if I can get it to fill fields in both the main form and the subform.

    My initial intention of having the button in the subform and not in the parent form was to avoid having two boxes that list the same thing. I was trying to use the text box "Header SN Field" in the subform, which is bound to the "Header SN" field on the "Header Data" record table. This text box is what is used when a user wants to enter a new record, but I was trying to use the same text box for the search button as well.
    Since my sub form is also used to enter data, I don't think I want the subform's bookmark/filter code to be on current event or on after update, since the user might be entering a new record instead of searching a record. If I want the button and text box to be on the subform, how do I reference the parent form and find the parent forms recordset? What do you mean by synchronizing the clone's bookmark with the parent form's bookmark? Can you give an example?

    Thank you for all the help!

    Was this answer helpful?

    1 person found this answer helpful.
    0 comments No comments
  5. Ken Sheridan 3,581 Reputation points
    2022-12-19T19:17:02.977+00:00

    To return a reference to the subform in its own module use the Me keyword. To reference the parent form in the subform's module use Me.Parent.

    What do you mean by synchronizing the clone's bookmark with the parent form's bookmark? Can you give an example?

    I already did in one of my earlier replies:

    If Not IsNull(Me.cboLastname) Then
    With Me.fsubContacts.Form
    .RecordsetClone.FindFirst "ContactID = " & Me.cboLastname
    If Not .RecordsetClone.NoMatch Then
    .Bookmark = .RecordsetClone.Bookmark
    End If
    End With
    End If

    Was this answer helpful?

    2 people found this answer helpful.
    0 comments No comments