That's correct, I'm trying to create a new instance of an object. (otherwise I'd just use
Code:
docmd.openform frmname.
)
The compiler error with
Code:
Set frm = New Form(frmName)
is "expected end of statement" and it highlights the opening bracket after New Form.
There must be a way to do this. i know I can reference controls using Me.Controls("controlname"), there must be a way with objects such as forms and reports.
I've got this working without strings using the following:
Code:
Public clnRm As New Collection
Private Sub Command0_Click()
Dim rpt As Report
'Open a new instance, show it, and set a caption.
Set rpt = New Report_rptName
rpt.Visible = True
rpt.Caption = rpt.Hwnd & ", opened " & Now()
'Append it to our collection.
clnRm.Add Item:=rpt, Key:=CStr(rpt.Hwnd)
Set rpt = Nothing
End Sub
The report is called rptName. This works fine and allows me to open multiple instances.
The problem is i'm doing this loads and want to write a function so I can use it with different reports (rather than copy the same code 8 times)
So the line I'm stuck at is
Code:
Set rpt = New Report_rptName
Because that's the one that contains the report's name.
The furthest I've managed is :
Code:
Public clnRm As New Collection
Private Sub Command0_Click()
Dim rpt As Report
'Open a new instance, show it, and set a caption.
DoCmd.OpenReport "rptName", acViewPreview
Set rpt = Reports("rptName")
rpt.Visible = True
rpt.Caption = rpt.Hwnd & ", opened " & Now()
'Append it to our collection.
clnRm.Add Item:=rpt, Key:=CStr(rpt.Hwnd)
Set rpt = Nothing
End Sub
This works for the first one opened, but the second report it opens can't be added to the collection because it has the same rpt.Hwnd value (because docmd.openreport just brings focus to the one already open). So the key is the "New" part, and I can't work it out.
If anyone knows a good help file about the "new" function than please point me to it and I'll be happy to read.
EDIT: I have just tried
Code:
Dim rpt As NEW Report
but still says "the key is already associated with this collection" because it's opening the same instance of the report :-(
OK, slow down, you started out by requiring this for Forms but have shifted it to Reports.
I’ve seen this attempted before with no eloquent solution available in Access.
What I think it will boil down to is an admittedly ineloquent workaround.
I think you will find that, in the end, a Select Case construct is required.
That Select Case construct will require 'hard coding' the names of the Form or Report to the right of New.
So, let's skip the details of the mechanics for the moment and allow me to ask a few questions about functionality.
Do you really want multiple concurrent instances of the same Form or Report?
In other words, do you want 75 concurrent instances of the same Form or Report?
If you can open multiple concurrent instances of the same Form or Report what do you want to happen when you close an instance?
Do you want to close that instance or all 75 instances?
As I have the mechanics at the moment: -
Code:
Option Explicit
Option Compare Text
' Needs to be Public to reserve after procedure termination.
Public MyForms() As Form
Public Sub TestOpen()
OpenFormInstance "frmTemplateForm" ' Valid Form name
OpenFormInstance "frmCustomerForm" ' Valid Form name
OpenFormInstance "frmChris" ' Invalid Form name for test
End Sub
Public Sub TestClose()
CloseFormInstance "frmTemplateForm" ' Valid Form name
CloseFormInstance "frmCustomerForm" ' Valid Form name
CloseFormInstance "frmChris" ' Invalid Form name for test
End Sub
Public Sub OpenFormInstance(ByVal strFormName As String)
' Open another instance of the Form by the passed name.
' This means that multiple instances of the same Form are allowed.
' Do not attempt to open an invalid Form name.
' Author : ChrisO
' Version: 1, 26 Oct 2010.
Dim FormInstance As Form
Select Case strFormName
Case "frmTemplateForm"
Set FormInstance = New Form_frmTemplateForm
Case "frmCustomerForm"
Set FormInstance = New Form_frmCustomerForm
Case Else
MsgBox "Invalid argument passed." & vbNewLine & _
"Form '" & strFormName & "' not in list!"
End Select
If Not FormInstance Is Nothing Then
IncrementUpperbound MyForms()
Set MyForms(UBound(MyForms)) = FormInstance
MyForms(UBound(MyForms)).Caption = MyForms(UBound(MyForms)).Name & " MyForms(" & UBound(MyForms) & ")"
MyForms(UBound(MyForms)).Visible = True
End If
End Sub
Public Sub CloseFormInstance(ByVal strFormName As String)
' Close all instances of the Form by the passed name.
' Do not attempt to close an invalid Form name.
' Author : ChrisO
' Version: 1, 26 Oct 2010.
Dim intIndex As Integer
Dim blnUsed As Boolean
For intIndex = LBound(MyForms) To UBound(MyForms)
If Not MyForms(intIndex) Is Nothing Then
If MyForms(intIndex).Name = strFormName Then
Set MyForms(intIndex) = Nothing
End If
End If
Next intIndex
End Sub
Public Sub IncrementUpperbound(ByRef vntArray As Variant)
' It's just plain interesting why this avoids an error.
' Author : ChrisO
' Version: 1, 26 Oct 2010.
ReDim Preserve vntArray(UBound(vntArray) + 1)
End Sub
But the mechanics rely on the functionality required.
nice solution! I guess I could just use a select statement.
Sorry I switched to reports it's just the code for that was much tidier. and to your question about why i want multiple instances, it's very useful if you have a list of 4 or 5 hundred people and are doing something with only 5 of them (which for some reason the filters can't bring them on one page) to open a report for each of them and do whatever it is you want to do. Or say you are interrupted by a phone call and don't want to close everything you're doing, you can just open another report to sort out the problem.
it's the client's request
It's interesting you use an array instead of a collection. Is there any advantage to this? It seems you are grouping the forms by the form name, so it does not allow just one instance to be closed. is this correct? Whereas using a collection, it's possible to close just one instance using the hwnd value (which in my case is important).
>>It's interesting you use an array instead of a collection. Is there any advantage to this?<<
Not really, it’s just the way I did it. If you prefer a collection then stick with it. Not that there’s that much difference between a collection and an array.
>>It seems you are grouping the forms by the form name<<
Yes, but that is just the way I did it. Thinking of the magical number 75 again, if a user did open 75 instances of the same Form they may want to close all instances of that Form in one hit. It would be a bit of a pain having to manually close 75 instances.
If on the other hand you already have the facility to only close a specific instance of a Form then don’t throw it away. I don’t see any reason you could not retain both methods. One method to close a specific instance and another method to block delete.
And so to another question; is there anything else you may need help with?
If so then please post a small demo (in Access 2003) and we can then work from the same perspective.