Introduction
A Subform on a Main Form is a common design pattern used to display multiple related records alongside a single record from the main form. For example, order details linked to orders, bank accounts with their transactions, or student IDs with their mark lists. In short, nearly all databases with one-to-many relationships use this approach, as it provides a convenient way to view a large amount of related information in one place.
When a form is opened with a table or query as its record source, Access loads a parallel Recordset in memory, with each record uniquely bookmarked. This allows us to search and navigate through the virtual recordset without directly interacting with the underlying table or query. However, when a record is added or updated in this virtual recordset, the change is automatically saved back to the actual table. This in-memory recordset is known as the form’s RecordsetClone.
Working with Recordset Clone.
The sample VBA code below demonstrates how to work with a form’s RecordsetClone to locate a record based on specific criteria. In this example, we search for an order using its ProductID and then move the form’s current record pointer to that record:
Private Sub FindPID_Click() 'Find Record matching Product ID Dim m_find, rst As Recordset 'validation check of search key value m_find = Me![xFind] If IsNull(m_find) Then Me.FilterOn = False Exit Sub End If 'validation check of search key value If Val(m_find) = 0 Then MsgBox "Give Product ID Number..!" Exit Sub End If 'Find a record that matches the ProductID 'and make that record current using the recordset bookmark. If Val(m_find) > 0 Then Set rst = Me.RecordsetClone 'declare the recordset of the form rst.FindFirst "ProductID = " & m_find If Not rst.NoMatch Then '<if record found then make that record current Me.Bookmark = rst.Bookmark End If rst.Close End If End Sub
We already have a blog post demonstrating how to search and filter data on a form using the RecordsetClone object. You can check that article [here].
In the earlier example, we worked with the RecordsetClone of the main form directly from its own module. But what if we need to access the RecordsetClone of a subform from the main form?
The key point to remember is this:
-
The subform displays only those records that are related to the current record on the main form.
-
Therefore, the subform’s RecordsetClone will contain only this filtered set of records—not all records from the underlying table or query.
By contrast, the RecordsetClone of the main form always includes all records from its record source, making it possible to search or update across the entire Recordset. For the subform, however, you can work only with the records currently visible in the subform for the active main form record.
Accessing Sub-Form Recordset from Main Form.
Let us try an example to learn how to access the sub-form record set from the main form and update records.
Import the following two Tables from the Northwind (or Northwind.mdb) database:
- Orders
- Order Details
Create a New Field for testing purposes.
Open the Order Details Table in the design view.
Add a new field: Sale Value with Data Type: Number and Field Size: Double.
Save the Order Details Table with the new field.
Design the Main form for the Orders Table in column format.
If you have used the Form Wizard and created a Split Form, then delete the Datasheet sub-form or table (Access 2007). Display the Property Sheet of the Form, find the Default View property, and change the Split Form value to Single Form.
Create a Sub-Form.
Design a Datasheet Sub-Form for Order Details Table.
Expand the Footer of the Sub-Form and create a Text box there.
Change the Name Property value to TotSale.
Write the expression =Sum([Sale Value]) in the Control Source property.
Save and close the Form with the name: Order Details.
Insert the Order Details sub-form in the Detail Section of the Orders Form below the Orders Form controls. See the image given below:
Sub-Form Link with the Main form.
While the Sub-Form is still in the selected state, display its Property Sheet (F4).
Set the Link Master Field property value to [Order ID].
Change the Link Child Field property value to [Order ID].
Add a Command Button above the sub-form as shown on the design above
.Display the Property Sheet of the Command Button (F4 or Alt+Enter.
Change the Name property value to cmdUpdate
Select the On Click Event property and select [Event Procedure] from the drop-down list.
Click on the Build (...) button at the right end of the property to open the VBA Module of the Form.
Copy and paste the following VBA Code into the VBA Module, overwriting the skeleton lines of the Sub-Routine there.
Sub-form Module Code.
Private Sub cmdUpdate_Click() Dim rst As dao.Recordset Dim m_UnitPrice As Double Dim m_Discount As Double Dim m_Quantity As Long Dim m_SaleValue As Double 'Address the recordset on the Sub-Form [Order Details] Set rst = [Order Details].Form.RecordsetClone rst.MoveFirst Do While Not rst.EOF m_UnitPrice = rst![Unit Price] m_Discount = rst![Discount] m_Quantity = rst![Quantity] m_SaleValue = m_Quantity * ((1 - m_Discount) * m_UnitPrice) rst.Edit rst![SaleValue] = m_SaleValue rst.Update [Order Details].Form.Bookmark = rst.Bookmark rst.MoveNext Loop rst.Close Set rst = Nothing End Sub
Create a Textbox to the right of the Command Button.
Set the Caption property value of the Child Label to Order Value:
Write the expression =[Order Details].[Form]![totSale]. This expression brings the Summary Value from the Text box, in the Footer Section of the sub-form, into the Order Form.
Save and close the Orders Form.
Open the Order Form.
- Open the Orders Form in Normal View.
If the Sale Value column is not visible in the datasheet, use the bottom scroll bar to move to the right. Locate the Sale Value column, then click and hold the mouse button, drag the column to the left, and drop it within the visible area.
Now you can see that the subform displays the records related to the current Order ID on the main form. However, the new text box we created to the right of the command button is still empty because the [Sale Value] field on the datasheet has not yet been updated.
Click on the Command Button to calculate and update the Sale Value of each record on the Datasheet Sub-Form.
Now you will see that the Sale Value column of all records on the subform has been updated, and the summary value of these records is displayed in the text box to the right of the command button. Only the Order Detail records related to the current Order ID on the Orders form are updated. If you move to another record in the Orders table, its related Sale Value records will remain unchanged until you click the command button again.
In the code, the statement:
creates a reference to the RecordsetClone object of the subform [Order Details]. The following lines calculate the Sale Value (after applying any discount) and update it into the new field [Sale Value] in the Order Details table.
The line:
sets the subform’s Bookmark equal to the current record’s Bookmark in the recordset clone. This ensures that the record being processed in the recordset clone also becomes the current record on the subform.
If the subform contains many records, you may notice visible movement of the cursor as it rapidly shifts from one record to another, starting at the first record and progressing through to the last, while the update operation runs.
No comments:
Post a Comment
Comments subject to moderation before publishing.