|
-
Jun 21st, 2008, 11:23 AM
#1
Thread Starter
Fanatic Member
[RESOLVED] Source Event from Access Subform
OK, I have never posted one of these before, but here goes.
I am using access/VBA to build the front end of a database application. I am 99% self-taught with coding and OOP, so please bear with me.
My model is based on a treeview control providing a string reference to a form name, which then tells a parent form which (of many) subforms to "load" into the "subform" control:
strSfmName = TvNode.Text
Me.chdSfm.SourceObject = strSfmName
Currently, once the Sfm is loaded, the parent then sets an object reference to it:
Set Sfm = Me.chd.Form
Now the Parent form "knows" about the Sfm and can control it.
The bad juju is that, right now the Sfm ALSO needs to set a reference to the parent, in order that it can "tell" the parent when it is done with whatever it is doing, and pass info back. THis ACTUALLY occurs as a call from the parent as follows:
(Call from the parent form):
Call Sfm.SetParentRef(Me)
(Procedure on child):
Private frmParent As Form 'Declare a form object
Public Sub SetParentRef(ByVal frm As Form)
If not frm = Nothing Then
Set frmParent = frm
End If
I understand that this may potentially result in a circular reference/memory leakage problem (and is just bad programming practice!).
I would prefer that the PARENT always know "who" the child is, but that the child need not know who the parent is, and instead raise an eevent to tell the parent it is "done" and to come "get the mail" (Access properties to retrieve information".
Accesss does not seem to provide a way for me to source custom events from the loaded Sfm instance which can be "heard" by the parent.
Any ideas? (and did what I just described make sense? i am VERY new at this . . .)
-
Jun 22nd, 2008, 06:34 PM
#2
Re: Source Event from Access Subform
No need to set Parent ref. A subform always can find its Parent by using Me.Parent.
If a form is a subform, its Me.Parent property will return a (parent) Form, otherwise it will cause error 2452.
Code:
'== ON CHILD FORM ========
Private frmParent As Form
Private Sub Form_Load()
On Error Resume Next
Set frmParent = Me.Parent
On Error GoTo 0
If frmParent Is Nothing Then
MsgBox Me.Name & " has no parent"
Else
MsgBox "The Parent Of " & Me.Name & " is " & frmParent.Name
End If
End Sub
-
Jun 22nd, 2008, 08:11 PM
#3
Thread Starter
Fanatic Member
Re: Source Event from Access Subform
Thanks for takinig the time to reply. I was beginning to think I did something wrong! I am sure there is some ettiquette on these forums that I don't know yet (like not writing a novel everytime I post, eh?).
I knew about that(that the Sfm can find it's parent . . .). The problem is that I couldn't find a way for the subform to test for it transparently:
If (I Have a parent) then
Do THIS(something)
Else
Move on as a stand-along form
End If
Everything I have tried raises the error you mention in the case where no parent exists, or the test itself causes an error by trying to reference an object that isnt there:
If Me.Parent = nothing Then . . . Etc (and variations on this)
Any thoughts?
More to the point, most of this excersice is about trying to raise a custom event from the subform that will be "heard" by the parent, without the subform having to know about a parent at all (or an external form calling the sfm as a stand-alone . . .). If you or anyone can help with THAT, the issue would be moot.
I have found different ways to accomplish this by setting references, etc, but they all feel clumsy. I am trying to learn "good" coding practices!
My understanding is that I am running into a problem created by Access' use of the "subform container" control, by which Access thinks the subform is just another control. I also (think) I get that when I graduate to REAL vb, thing will be different. Am I asking too much from VBA to accomplish this in an elegant manner? I think I may be trying to use the access forms in a way for which they were not intended!
-
Jun 22nd, 2008, 08:16 PM
#4
Thread Starter
Fanatic Member
Re: Source Event from Access Subform
OK. I didn't read closely enough. You used the "is nothing" test. I am almost positive I tried that and got the "object not set" error. I'm going to try that now, just to make sure.
In the meantime, any info about the custom events issue would be very, VERY appreciated!
-
Jun 22nd, 2008, 08:32 PM
#5
Re: Source Event from Access Subform
You cannot use ... = Nothing, but that keyword must be used with "Is":
... Is Nothing
With my previous code, after the form is loaded whether as stand-alone or as a subform, by using an If statement you will know the form has Parent or not.
Code:
If frmParent Is Nothing Then
'...
Else
'...
End If
Another way you can do is to create a function MyParent() that will return the Parent form if the Parent form exists otherwise it will return Nothing.
Code:
Option Compare Database
Option Explicit
Function MyParent() As Form
On Error Resume Next
Set MyParent = Me.Parent
End Function
Private Sub Command1_Click()
Dim frmParent as Form
Set frmParent = MyParent()
If frmParent Is Nothing Then
MsgBox Me.Name & " has no parent"
'-- do whatever you want here
Else
MsgBox "The Parent of " & Me.Name & " is " & frmParent.Name
'-- do whatever you want here
End If
End Sub
Last edited by anhn; Jun 22nd, 2008 at 09:34 PM.
-
Jun 22nd, 2008, 09:08 PM
#6
Thread Starter
Fanatic Member
Re: Source Event from Access Subform
Thanks!
Another one of those things that I now feel I should have been able to figure out myself!
OK. So now the Raising events issue. This may have solved my circular reference problem, but I am still stumped by the inability to raise an event from the subform and be heard by the parent.
Anyone?
ps. These forums are great. I really appreciate the time some of you experienced folks must put in here to help us newbies along. As soon as I figure out how and where to add to your rating thing, I will. If only I could sit and pick one y'alls brain for an hour or two!
-
Jun 22nd, 2008, 09:34 PM
#7
Re: Source Event from Access Subform
* Create a Public Sub in parent form, such as: Public Sub CallFromMyChid()
* Put this in the subform:
Code:
Private Sub Command1_Click()
Dim frmParent as Form
On Error Resume Next
Set frmParent = Me.Parent
On Error Goto 0
If Not frmParent Is Nothing Then '-- I have a Parent
Call frmParent.CallFromMyChid
Else '-- I have no Parent
'-- do whatever you want here
End If
End Sub
-
Jun 22nd, 2008, 10:03 PM
#8
Thread Starter
Fanatic Member
Re: Source Event from Access Subform
Thanks again!
In this case, you have confirmed the approach I have been taking (almost exactly, with regard to the public sub on the parent, called from the child).
My mistake was in setting the reference to the parent at the Sfm module level, and letting it persist through the Sfm's scope. At the same time, of course, the parent has a standing refernce to the child as well. That was working, just fine, but I read somewhere about the cirular reference/memory leakage thing, and decided I was making a novice's mistake.
I believe the way you describe solves that problem by only referencing the parent long enough to call the "I'm done now" sub, and then terminates.
Maybe I am getting the hang of this.
-
Jun 22nd, 2008, 11:23 PM
#9
Re: Source Event from Access Subform
Is that your problem solved? If that, use Thread Tools on the top of the page to mark your thread as Resolved.
It will help other to undestand your problem easier and you can get help quicker, you should post your actual code instead of just ask the theory and use "parent" and "child" and "tell" and "heard". For some that's hard to imagine.
If you intend to refer or call the Parent many times from a subform (and that subform also can be opened as a stand-alone at another time) then you can do it this way:
Suppose that you have 2 forms: Form1 and Form2, Form2 may be opened as a stand-alone or Form2 may be a subform of Form1.
On loading of Form2, you need to check only once whether it has a Parent or not and store the Parent's name in a variable that can be used at any time in Form 2.
In Form2 module:
Code:
Dim ParentName as String
Sub Form_Load()
On Error Resume Next
ParentName = Me.Parent.Name
'-- if this is a stand-alone form then the above line fails,
'-- and ParentName = "" as default.
On Error Goto 0
'-- other code here if you want
End Sub
Private Sub Command1_Click()
'-- your code here
If ParentName <> "" Then
'-- CallFromMyChid is a Public Sub in the Parent form.
Call Me.Parent.CallFromMyChid
Else
'-- your other code here
End If
'-- your other code here
End Sub
More flexible, if Form2 can be a subform of Form1 or Form3 (or more):
Code:
Private Sub Command1_Click()
'-- your code here
If ParentName = "Form1" Then
'-- CallFromChid1 is a Public Sub in Form1.
Call Me.Parent.CallFromChid1
ElseIf ParentName = "Form3" Then
'-- CallFromChid2 is a Public Sub in Form3.
Call Me.Parent.CallFromChild2
Else
'-- your other code here
End If
'-- your other code here
End Sub
-
Jun 23rd, 2008, 12:00 AM
#10
Thread Starter
Fanatic Member
Re: Source Event from Access Subform
OK, thanks again so much, and for the "ettiquett" pointers.
Even further, you have confirmed my technique, and all of this was very validating for me. I had been doing it EXACTLY the way you described from jump, except, as mentioned above (tesing for Me.Parent and terminating the parent reference until needed again-I was letting it persist). I just thought I had to be doing something WRONG.
I will try to use code examples instead, and I will make sure to mark this as resolved. I guess i AM also looking for theory. I seem to be at a level where I know many ways to attempt coding something, but not always the issues around each. The theory part is where I am lacking.
Thanks again for your time. I think I added the reputation points the way I'm supposed to!
-
Jun 23rd, 2008, 12:10 AM
#11
Re: [RESOLVED] Source Event from Access Subform
You have done the right thing when you rate the post that help you.
But your reputation points was not counted or added because you are too new to the forums.
-
Jun 23rd, 2008, 12:18 AM
#12
Thread Starter
Fanatic Member
Re: [RESOLVED] Source Event from Access Subform
So, Here is the code, as I wrote it previous to this post. This is the RELEVANT code on the Main form:
Code:
RELEVANT Code on the main form, which recieves property settings from a treeview control:
Public Sub NodeChange()
'Selection of node on a treeview Sfm references this procedure to
'provide navigation information and Sfm information.
Dim SfmNav As Form
Dim CurrentNavParentID As Long
Dim CurrentNavChildID As Long
Set SfmNav = Me.chdNavMenu.Form
Me.Painting = False
CurrentNavParentID = lNavParentID
With Me
.NavParentID = SfmNav.NavParentID
.NavChildID = SfmNav.NavChildID
.NavParentText = SfmNav.NavParentText
.NavChildText = SfmNav.NavChildText
.SfmMainRef = SfmNav.SfmMainRef
.SfmDetailRef = SfmNav.SfmDetailRef
End With
Set SfmNav = Nothing
'++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
'Control Which Sfm is Displayed in the chdMain Control
'++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
If CurrentNavParentID <> lNavParentID Then
'Don't change sourceobjct if the NavParentID has not changed
chdMain.SourceObject = strSfmMainRef
Set sfmMain = Me.chdMain.Form
'Set the reference to the subform at this form's module level
Call sfmMain.DimensionForm(Me.chdMain)
Call sfmMain.SetNavParentText(strNavParentText)
Call sfmMain.SetNavChildText(strNavChildText)
Set sfmMain = Nothing
End If
If CurrentNavChildID <> lNavChildID Then
Set sfmMain = Me.chdMain.Form
Call sfmMain.SetNavChildText(strNavChildText)
'++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
'Control which Sfm is displayed in the chdDetailControl of SfmMain
'++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
If SfmExists(sfmMain) Then
'Test to see if there is a Detail-level Sfm on SfmMain
If strSfmDetailRef <> "" Then
sfmMain.chdDetail.SourceObject = strSfmDetailRef
Set sfmDetail = sfmMain.chdDetail.Form
Call sfmDetail.SetAsSfm(sfmMain)
'Tell sfmDetail who it's parent is
Call sfmDetail.DimensionForm(sfmMain.chdDetail)
'Dimension SfmDetail to fit the chdDetail control on Sfm Main
Call sfmMain.SetNavChildText(strNavChildText)
Else
sfmMain.chdDetail.SourceObject = "sfmDetailEMPTY"
'If no form name reference is provided, load the EMPTY SfmDetail form.
End If
End If
Call sfmMain.SetAsSfm(Me)
'Tell SfmMain Who it's parent is.
Set sfmMain = Nothing
Set sfmDetail = Nothing
End If
Me.Painting = True
End Sub
Following is the Procedure on the Subform, which is called from the main form in the preceeding example. I am going to change this to incorporate the test Anhn described, so that I don't need the persisting module-level variable frmParent:
Code:
Public Sub SetAsSfm(ByVal TheParentForm As Form)
'Set form up to function as a subform. Set the value of the frmParent variable
'to the value of the parent form. Reference the value (global?) of the parent
'property ID.
Set frmParent = TheParentForm
'lCountyID = basDefaults.COUNTY_ID_DEFAULT
Call Me.NewCountyID(lCountyID, lAMIRegionID)
End Sub
Wow. That was long. Hopefully this may help someone else . . . Even though this is resolved, I am HAPPY to hear ANY feedback or commentary on this . . .
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|