Results 1 to 12 of 12

Thread: [RESOLVED] Source Event from Access Subform

  1. #1

    Thread Starter
    Fanatic Member
    Join Date
    Jun 2008
    Location
    Portland, OR, USA
    Posts
    659

    Resolved [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 . . .)

  2. #2
    Head Hunted anhn's Avatar
    Join Date
    Aug 2007
    Location
    Australia
    Posts
    3,669

    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
    • Don't forget to use [CODE]your code here[/CODE] when posting code
    • If your question was answered please use Thread Tools to mark your thread [RESOLVED]
    • Don't forget to RATE helpful posts

    • Baby Steps a guided tour
    • IsDigits() and IsNumber() functions • Wichmann-Hill Random() function • >> and << functions for VB • CopyFileByChunk

  3. #3

    Thread Starter
    Fanatic Member
    Join Date
    Jun 2008
    Location
    Portland, OR, USA
    Posts
    659

    Cool 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!

  4. #4

    Thread Starter
    Fanatic Member
    Join Date
    Jun 2008
    Location
    Portland, OR, USA
    Posts
    659

    Smile 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!

  5. #5
    Head Hunted anhn's Avatar
    Join Date
    Aug 2007
    Location
    Australia
    Posts
    3,669

    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.
    • Don't forget to use [CODE]your code here[/CODE] when posting code
    • If your question was answered please use Thread Tools to mark your thread [RESOLVED]
    • Don't forget to RATE helpful posts

    • Baby Steps a guided tour
    • IsDigits() and IsNumber() functions • Wichmann-Hill Random() function • >> and << functions for VB • CopyFileByChunk

  6. #6

    Thread Starter
    Fanatic Member
    Join Date
    Jun 2008
    Location
    Portland, OR, USA
    Posts
    659

    Smile 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!

  7. #7
    Head Hunted anhn's Avatar
    Join Date
    Aug 2007
    Location
    Australia
    Posts
    3,669

    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
    • Don't forget to use [CODE]your code here[/CODE] when posting code
    • If your question was answered please use Thread Tools to mark your thread [RESOLVED]
    • Don't forget to RATE helpful posts

    • Baby Steps a guided tour
    • IsDigits() and IsNumber() functions • Wichmann-Hill Random() function • >> and << functions for VB • CopyFileByChunk

  8. #8

    Thread Starter
    Fanatic Member
    Join Date
    Jun 2008
    Location
    Portland, OR, USA
    Posts
    659

    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.

  9. #9
    Head Hunted anhn's Avatar
    Join Date
    Aug 2007
    Location
    Australia
    Posts
    3,669

    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
    • Don't forget to use [CODE]your code here[/CODE] when posting code
    • If your question was answered please use Thread Tools to mark your thread [RESOLVED]
    • Don't forget to RATE helpful posts

    • Baby Steps a guided tour
    • IsDigits() and IsNumber() functions • Wichmann-Hill Random() function • >> and << functions for VB • CopyFileByChunk

  10. #10

    Thread Starter
    Fanatic Member
    Join Date
    Jun 2008
    Location
    Portland, OR, USA
    Posts
    659

    Thumbs up 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!

  11. #11
    Head Hunted anhn's Avatar
    Join Date
    Aug 2007
    Location
    Australia
    Posts
    3,669

    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.
    • Don't forget to use [CODE]your code here[/CODE] when posting code
    • If your question was answered please use Thread Tools to mark your thread [RESOLVED]
    • Don't forget to RATE helpful posts

    • Baby Steps a guided tour
    • IsDigits() and IsNumber() functions • Wichmann-Hill Random() function • >> and << functions for VB • CopyFileByChunk

  12. #12

    Thread Starter
    Fanatic Member
    Join Date
    Jun 2008
    Location
    Portland, OR, USA
    Posts
    659

    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
  •  



Click Here to Expand Forum to Full Width