John,
I've been giving some more thought to your question, and it occurred to me
that you might want to control these forms from Form1, and who's to say how
many you want to instantiate. So I fiddled around a bit and came up with the
following solution. You might find it a bit complex at first, but when you
take an in-depth look at it, you'll see it's really not that hard. With this
strategy, you can instantiate as many Form2's as you like, plus you can
automate them as you please.
The first thing is that we need to uniquely identify each instance of Form2,
so I decided to use GUIDs.
'************************
'Place the following code into a standard module.
'************************
Type GUID
Data1 As Long
Data2 As Integer
Data3 As Integer
Data4(7) As Byte
End Type
Declare Function CoCreateGuid Lib "OLE32.DLL" (pGuid As GUID) As Long
Public Const S_OK = 0 ' return value from CoCreateGuid
Public Function GetGUID() As String
Dim lResult As Long
Dim lGUID As GUID
Dim sGUID As String
Dim sGUID1 As String
Dim sGUID2 As String
Dim sGUID3 As String
Dim iDataLen As Integer
Dim sStringLen As Integer
Dim iCtr As Integer
On Error GoTo GetGUID_Err
GetGUID = "00000000" 'Return zeros if the function is unsuccessful
lResult = CoCreateGuid(lGUID)
If lResult = S_OK Then
sGUID1 = Hex$(lGUID.Data1)
sStringLen = Len(sGUID1)
iDataLen = Len(lGUID.Data1)
sGUID1 = LeadingZeros(2 * iDataLen, sStringLen) & _
sGUID1 'First 4 bytes (8 hex digits)
sGUID2 = Hex$(lGUID.Data2)
sStringLen = Len(sGUID2)
iDataLen = Len(lGUID.Data2)
sGUID2 = LeadingZeros(2 * iDataLen, sStringLen) & _
Trim$(sGUID2) 'Next 2 bytes (4 hex digits)
sGUID3 = Hex$(lGUID.Data3)
sStringLen = Len(sGUID3)
iDataLen = Len(lGUID.Data3)
sGUID3 = LeadingZeros(2 * iDataLen, sStringLen) & _
Trim$(sGUID3) 'Next 2 bytes (4 hex digits)
For iCtr = 0 To 7
sGUID = sGUID & Format$(Hex$(lGUID.Data4(iCtr)), "00")
Next iCtr
'sGUIDn contains the last 8 bytes of the GUID (16 hex digits)
GetGUID = sGUID1 & sGUID2 & sGUID3 & sGUID
End If
Exit_GetGUID:
Exit Function
GetGUID_Err:
DoCmd.Beep
MsgBox "Error " & Err.Number & vbCrLf & vbCrLf & _
Err.Description, vbOKOnly + vbExclamation, _
"Could not retrieve GUID"
Resume Exit_GetGUID
End Function
Function LeadingZeros(iExpectedLen As Integer, iActualLen As Integer) As
String
LeadingZeros = String(iExpectedLen - iActualLen, "0")
End Function
'************************
'Now create two forms; one called frmForm1,
'and the other called frmForm2, and place a
'command button on each (both named Command0).
'On frmForm1, 'add a textbox called Text1.
'************************
'Now add the following code to frmForm1
'************************
Private frm As Form_frmForm2 'The form to multi-instantiate
Private colForm2 As Collection 'The form collection
Private Sub Command0_Click()
'Instantiate the new form instance
Set frm = New Form_frmForm2
'Make it visible
frm.Visible = True
'Set a circular reference to frmForm1
Set frm.ParentForm = Me
'Destroy the local reference
Set frm = Nothing
End Sub
Public Sub NotifyFormOpen(GUID As String)
'This sub is called from frmForm2's Close event
'Add the newly created form to the forms collection
colForm2.Add frm, GUID
Refresh the counter to show how many we current have
Me.Text1 = colForm2.Count
End Sub
Public Sub NotifyFormClose(GUID As String)
'This sub is called from frmForm2's Open event
On Error Resume Next
'Release the form's circular reference to frmForm1
Set colForm2(GUID).ParentForm = Nothing
'Remove the form from the collection
colForm2.Remove GUID
'Refresh the counter
Me.Text1 = colForm2.Count
End Sub
Private Sub Form_Load()
'Instantiate the form collection
Set colForm2 = New Collection
End Sub
Private Sub Form_Unload(Cancel As Integer)
On Error Resume Next
'Release the form reference
Set frm = Nothing
'Release the Collection object and all the objects it contains
Set colForm2 = Nothing
End Sub
'************************
'Now add the following code to frmForm2
'************************
Private sGUID As String 'The form's unique GUID (identifier)
Private oParent As Form 'An object variable to contain a
'circular reference to the calling form
Private Sub Command0_Click()
'Cose the current form instance
DoCmd.Close
End Sub
Private Sub Form_Load()
'Get the GUID and store it locally
sGUID = GetGUID
End Sub
Public Sub Form_Unload(Cancel As Integer)
On Error Resume Next
'Call the parent form's NotifyFormClose event
oParent.NotifyFormClose sGUID
'Release the local object reference
Set oParent = Nothing
End Sub
Public Property Get GUID() As String
'Set the GUID
GUID = sGUID
End Property
Public Property Set ParentForm(fm As Form)
'Instantiate the local circular reference to the calling form
Set oParent = fm
'If we've just created the reference, call the parent form's
'NotifyFormOpen event
If Not oParent Is Nothing Then
oParent.NotifyFormOpen sGUID
End If
End Property
'************************
'Whenever you want to do anything with one of the instances of frmForm2,
'you can refer to it through the Collection object, like so:
' colForm2(sGUID).public_method_or_object
I hope this helps.
Graham R Seach
Microsoft Access MCP, MVP
Sydney, Australia
Microsoft Access 2003 VBA Programmer's Reference
http://www.wiley.com/WileyCDA/WileyTitle/productCd-0764559036.html