Comments inline.
--
Ken Snell
<MS ACCESS MVP>
Garret said:
Alright, let me try and explain the idea again. Shipments contain
Components, and Components have to have certain Dimensions inspected
to make sure the Components of the Shipment are in tolerance, so they
are good to use. The Dimensions to be inspected are different for
each Component (because "Components" covers a wide range of objects),
so the Dimensions that each Component has to have inspected are
represented in the parent-child tables of tblComponents and
tblDimensions (form and subform for frmComponents).
Now, to mimic a Shipment, there is a main form with a combobox at the
top that looks up all the Components from tblComponents. So the user
first selects an item from this combobox to determine which Component
came in the Shipment, and so as a result, is indirectly selecting
which Dimensions should appear in the subform to be inspected.
Currently, code in the After_Update of this combobox limits the values
(changes the Rowsource) of the combobox of the subform to only those
Dimensions that belong to the Component selected. Does this make
sense?
So this code has to go somewhere after the user selects the Component
on the main form, but it cannot run on a record that is not new, or
there will be many duplicate records, and hence errors, in the
subform.
OK, so you can use the AfterUpdate event of that first combo box on the
Main Form to run the code:
Private Sub MainFormItemComboBox_AfterUpdate()
Dim lngItem As Long
If Me.NewRecord = True Then
DoCmd.Echo False
With Me.SubformName.Form.RecordsetClone
For lngItem = 0 To Me.ComboBoxName.ListCount - 1
.AddNew
.Fields("Component_No").Value = Me.Component_No.Value
.Fields("Dimension_No").Value =
Me.ComboBoxName.ItemData(lngItem)
.Update
Next lngItem
End With
DoCmd.Echo True
End If
End Sub
Note that using the code on the AfterUpdate event assumes a couple of
things:
(1) The user will never select the wrong item in that combo box, which
would cause a lot of bad records to be added to the subform for that
mistaken choice. (This is why I strongly suggest that you put a command
button on the main form and let the user click it to show that the
selection is the one desired, and then use the Click event of the button
to run the above code.)
(2) The main form's record will be saved to the table before the code
runs, else you'll get relational integrity errors because there is no
parent record yet for the records being added to the subform. If you need
to ensure that this happens, the code should be changed to this:
Private Sub MainFormItemComboBox_AfterUpdate()
Dim lngItem As Long
If Me.NewRecord = True Then
Me.Dirty = False ' save main form's record
DoCmd.Echo False
With Me.SubformName.Form.RecordsetClone
For lngItem = 0 To Me.ComboBoxName.ListCount - 1
.AddNew
.Fields("Component_No").Value = Me.Component_No.Value
.Fields("Dimension_No").Value =
Me.ComboBoxName.ItemData(lngItem)
.Update
Next lngItem
End With
DoCmd.Echo True
End If
End Sub
This is what I wanted to do but didn't know how, so I kept on
struggling with the monster I had created. Here is the code I use to
populate the combobox with values after the Component is selected on
the main form. (Code is used in the combobox's After_Update)
Private Sub cboComponent_No_AfterUpdate()
strComponent_No = Me.cboComponent_No
Me!sbfInspection.Form!cboDimension_No.RowSource = _
"SELECT Component_No, Dimension_No " & _
"FROM tblValidComponentDimensions " & _
"WHERE Component_No= '" & strComponent_No & "'" & _
"ORDER BY Dimension_No;"
'Update the combobox
Me!sbfInspection.Form!cboDimension_No.Requery
Me!sbfInspection.Form.Refresh
End Sub
OK, so building on the code noted above, we'd change it to use a recordset
instead of the second combobox:
Private Sub MainFormItemComboBox_AfterUpdate()
Dim dbs As DAO.Database
Dim rst As DAO.Recordset
Dim lngItem As Long
Dim strSQL As String
If Me.NewRecord = True Then
Me.Dirty = False ' save main form's record
DoCmd.Echo False
strSQL = _
"SELECT Component_No, Dimension_No " & _
"FROM tblValidComponentDimensions " & _
"WHERE Component_No= '" & strComponent_No & "'" & _
"ORDER BY Dimension_No;"
Set dbs = CurrentDb
Set rst = dbs.OpenRecordset(strSQL, dbOpenDynaset, dbReadOnly)
If rst.EOF = False And rst.BOF = False Then
rst.MoveFirst
Do While rst.EOF = False
With Me.SubformName.Form.RecordsetClone
.AddNew
.Fields("Component_No").Value = Me.Component_No.Value
.Fields("Dimension_No").Value = rst!Dimension_No.Value
.Update
End With
rst.MoveNext
Loop
End If
rst.Close
Set rst = Nothing
dbs.Close
Set dbs = Nothing
DoCmd.Echo True
End If
End Sub
Yes, Ken, that sounds right, and thats exactly what I want to do.
Each Dimension has a corresponding Tool that is used to measure it.
The Tool data is stored as another field in the same table where the
Dimensions are stored (tblDimensions). In the Inspection subform of
the Shipments form, it would be useful to display this Tool value so
that the user can do the measuring without having to look it up on the
Components form + Dimensions subform.
To show the Tool data on the subform, add a textbox to the subform. Use
this expression as its Control Source (replace my generic names with real
names):
=DLookup("NameOfToolFieldInTable", "tblDimensions", "Dimension_No='" &
[NameOfTextBoxHoldingDimensionNumberValue] & "'")