It is quite frequently needed to open an auxiliary form from a main one to enter some information. Data entered in the auxiliary form is expected to appear in the main one and optionally treated in some way, the aixiliary form is expected to give some feedback to the main one etc.
This howto displays several approaches.
The examples has been implemented in the attached database.
A particular implementation of the approaches described above or combinations thereof depends on particular circumstances allowing to reveal advantages and to tolerate drawbacks of each one.
This howto displays several approaches.
- The first method is applicible when the auxiliary form is expected to provide an enhanced interface to a record the main form is pointed to. For example a bigger Textbox to enter long text, Calendar control etc.
The main idea of the method is to bind the aixiliary form and its control(s) to the same datasource as that of the main one.
Main form code
[code=vb]
'opens child form and binds its control to the same datasource
'as the main one
'data in both forms synchronized because they both bound
'to the same data source
Private Sub btnOpenChildFor m1_Click()
DoCmd.OpenForm "frmChild1"
With Forms!frmChild1
'set ControlSource of child form control to
'the same as im main one
.txb.ControlSou rce = Me.txb.ControlS ource
'set child form Recordset to the same as the main one
Set .Recordset = Me.Recordset
'make child form modal
.Modal = True
End With
End Sub
[/code]
Child form (frmChild1) code
[code=vb]
Private varOldValue As Variant 'holds control original value
Private Sub btnCancel_Click ()
Me.txb = varOldValue 'restore original value
CloseMe
End Sub
Private Sub btnSubmit_Click ()
CloseMe
End Sub
Private Sub CloseMe()
DoCmd.Close acForm, Me.Name
End Sub
Private Sub txb_BeforeUpdat e(Cancel As Integer)
'store control original value before first update occur
If IsEmpty(varOldV alue) Then varOldValue = Me.txb.OldValue
End Sub
[/code]
Note: Child form could be optionally bound to a clone of main form recordset. That gives an opportunity to effectively use Me.Undo method in the child form but requires additional logic to refresh main form manually. - The second method gives more opportunities for data validation performed in a main form. The main idea of the method is to pass reference(s) to the main form control(s) to a child form via property to give it an opportunity to write back to the main form.
Main form code
[code=vb]
'opens child form and passes reference to main form control
'via child form property
'data in main form will be updated by child form
Private Sub btnOpenChildFor m2_Click()
DoCmd.OpenForm "frmChild2"
With Forms!frmChild2
'pass reference to main form control
'to child form via its property
Set .ConnectedTextB ox = Me.txb
'make child form modal
.Modal = True
End With
End Sub
[/code]
Child form (frmChild2) code
[code=vb]
'form global variable to store reference to main form control
Private objConnectedTex tBox As Access.TextBox
'code to get property value
Public Property Get ConnectedTextBo x() As Access.TextBox
Set ConnectedTextBo x = objConnectedTex tBox
End Property
'code to set property value
Public Property Set ConnectedTextBo x(ByRef objNewValue As Access.TextBox)
Set objConnectedTex tBox = objNewValue
'set child form control value to that of main form
Me.txb.Value = objNewValue.Val ue
End Property
Private Sub btnCancel_Click ()
CloseMe
End Sub
Private Sub btnSubmit_Click ()
With Me
'write child form control value back to main form one
.ConnectedTextB ox.Value = .txb.Value
End With
CloseMe
End Sub
Private Sub CloseMe()
DoCmd.Close acForm, Me.Name
End Sub
[/code] - The main idea of the third method is to let a child form to invoke code in the main one via events and to pass values to it. The main form code makes the rest which provides high flexibility to how a data entered in the child form is being treated in the main form.
Main form code
[code=vb]
'object of Form_frmChild3 type is declared with events
Dim WithEvents frmChild3 As Access9db.Form_ frmChild3
'opens child form and waits for its events
'data in main form will be updated according to what
'child form will return via events
Private Sub btnOpenChildFor m3_Click()
DoCmd.OpenForm "frmChild3"
Set frmChild3 = Forms!frmChild3
With frmChild3
'pass main form control value to child form control
.txb = Me.txb
'make child form modal
.Modal = True
End With
End Sub
Private Sub frmChild3_Input Cancelled()
MsgBox "Input cancelled"
'destroy reference to frmChild3 no longer valid
Set frmChild3 = Nothing
End Sub
Private Sub frmChild3_Value Submitted(varVa lue As Variant)
'set main form control value to what child form returned
Me.txb.Value = varValue
MsgBox "Input submitted"
'destroy reference to frmChild3 no longer valid
Set frmChild3 = Nothing
End Sub
[/code]
Child form (frmChild3) code
[code=vb]
'events declaration
Event ValueSubmitted( varValue As Variant)
Event InputCancelled( )
Private Sub btnCancel_Click ()
RaiseEvent InputCancelled
CloseMe
End Sub
Private Sub btnSubmit_Click ()
RaiseEvent ValueSubmitted( Me.txb.Value)
CloseMe
End Sub
Private Sub CloseMe()
DoCmd.Close acForm, Me.Name
End Sub
[/code]
Note: Child form control(s) and/or form object could be declared with events in the main form module to handle correspondent event(s). That however goes slightly off size of this single howto. :D
The examples has been implemented in the attached database.
A particular implementation of the approaches described above or combinations thereof depends on particular circumstances allowing to reveal advantages and to tolerate drawbacks of each one.