Results 1 to 6 of 6
  1. #1
    pdanes is offline Competent Performer
    Windows Vista Access 2007
    Join Date
    Sep 2019
    Posts
    208

    Public variables in form module

    I've got a weird one, and am completely at a loss as to what to think of it.

    I have a form with two subforms, and app-wide public variables to refer to all the attendant machinery – form, subform containers and subforms:


    Code:
    Public FD As Form_Data, FD_DSC_F As Form_DataDS, FD_EC_F As Form_DataEdit, CP_FD As AccessObject
    Public FD_DSC As control, FD_EC As control
    FD is the main form, FD_EC and FD_DSC are the subform containers, and FD_DSC_F and FD_EC_F are the subforms.
    On startup, the variables are populated:
    Code:
    Set FD = Form_Data ' Main form
    Set FD_DSC = FD.DataDS ' Datasheet subform control
    Set FD_DSC_F = FD_DSC.Form ' Datasheet subform within control
    Set FD_EC = FD.DataEdit ' Edit subform control
    Set FD_EC_F = FD_EC.Form ' Edit subform within control
    The subforms contain public variables that I use to indicate status – mdl_ is my personal coding style to indicate module-level public variables:
    Code:
    Public mdl_eDf_NovyZaznam As Boolean
    Public mdl_eDf_UpravujemeZaznam As Boolean
    Public mdl_eDf_NeulozeneZmeny As Boolean
    Public mdl_eDf_LzeUlozit As Boolean
     
    Public mdl_eDf_DruhChanged As Boolean
    Public mdl_eDf_OblastChanged As Boolean
    Public mdl_eDf_ChUVChanged As Boolean
    I started getting some unexpected results, and traced it down to the fact that references to these module-level public variables are different depending on how I refer to them, and seemingly, the form variables do not fully reference the form to which they are supposed to point. For instance, the code:
    Code:
    Set FD = Form_Data
    seems to work, since executing this in break mode:
    Code:
    ?fd is form_data
    does in fact return true. However, the code:
    Code:
    Set FD_EC_F = FD_EC.Form
    seems to me should set a pointer to the form, but executing this in break mode:
    Code:
    ?fd_ec_f is form_dataedit
    returns false. When I manually make visible changes to the form in break mode, using either method gives me the same results. For instance, both of the following turn the subform's background black:
    Code:
    fd_ec_f.section(0).backcolor=0
    form_dataedit.Section(0).BackColor=0
    However, here is a copy from the immediate window in break mode:
    Code:
    ?Form_dataedit.mdl_eDf_UpravujemeZaznam
    True
    ?FD_EC_F.mdl_eDf_UpravujemeZaznam
    False
    This should be referring to the exact same public variable in the form's code module, and the two methods clearly refer to the same form, since both of them have the same visible effects on the form's displayed properties. But referring to these public variables of that same form gives different results. In fact, manually executing these two statements in break mode:
    Code:
    fd_ec_f.mdl_eDf_UpravujemeZaznam = True
    form_dataedit.mdl_eDf_UpravujemeZaznam = False
    results in each 'version' of the variable getting set, and subsequent examination of 'each' variable shows the value that was last written to it, independent of the other.

    How can this be? I found no mention of such behavior anywhere, except one blurb stating that the preferred way of doing this is by using property Get and Let functions, rather than public variables, that such variable are considered sub-standard coding practice. No explanation of why, though, and no indication that such constructs should not function properly.

    Forms are class instances, and classes very specifically DO allow public variables. Can anyone enlighten me on what is going on here, before I go jump off the roof?

  2. #2
    ranman256's Avatar
    ranman256 is offline VIP
    Windows Vista Access 2010 32bit
    Join Date
    Apr 2014
    Location
    Kentucky
    Posts
    9,525
    I didn't think forms could have public vars.
    put them in a module.

  3. #3
    pdanes is offline Competent Performer
    Windows Vista Access 2007
    Join Date
    Sep 2019
    Posts
    208
    They can - forms are a class, (which is why you can have multiple instances of a form open simultaneously) and classes can have public variables. You refer to them with the dot notation, same as any class. And they work. What I'm stuck on is why they are working in this case as if there were partially a second instance - some aspects of the form are working properly from both direct reference and an object variable, and some are working as if there were two separate instances - one direct and a separate one referred to by the object variable. That doesn't seem right, and I don't understand why it's happening.

  4. #4
    pdanes is offline Competent Performer
    Windows Vista Access 2007
    Join Date
    Sep 2019
    Posts
    208
    Found it, looks like:
    Code:
    Set FD = Form_Data ' Main form
    Set FD_DSC = FD.DataDS ' Datasheet subform control
    Set FD_DSC_F = Form_DataDS ' Datasheet subform within control
    Set FD_EC = FD.DataEdit ' Edit subform control
    Set FD_EC_F = Form_DataEdit ' Edit subform within control
    This is the proper way to do it.

    I was using in lines 3 and 5 a reference via the main form's subform control, instead of a direct reference to the actual forms that I am using as subforms, and that caused the screwy behavior. That is, instead of this:
    Code:
    ' This works correctly
    Set FD_DSC_F = Form_DataDS ' Datasheet subform within control
    Set FD_EC_F = Form_DataEdit ' Edit subform within control
    I was using this:
    Code:
    ' This does NOT work correctly
    Set FD_DSC_F = FD_DSC.Form ' Datasheet subform within control
    Set FD_EC_F = FD_EC.Form ' Edit subform within control
    and that reference, 'through' the subform control gives some sort of duality of the subform. Again, changing visual aspects of the subform worked via both the object variable and via a direct reference, but referring to the public variables in the subform apparently referred to two different instances of those public variables, since each method of reference could set a value and subsequently retrieve it, independent of the other.

    I still don't understand what is going on here. I could sort of see that it would be not working if the subforms were instantiated after the initial reference to them, but these lines of code are in the main form, and that is instantiated only AFTER the subforms, so by the time this code executes, the subforms should be comfortably in place, ready to act in all ways as a normal, single instance of a class. Where the 'second', ghost instance is coming from I haven't a clue.

    I now have it working as I want, and as it should be according to all documentation I have read on the subject. But if anyone can clue me in on what was going on, even well down the road from when I am posting this, I would be very grateful to hear it.

  5. #5
    accesstos's Avatar
    accesstos is offline Expert
    Windows XP Access 2007
    Join Date
    Dec 2018
    Location
    Greece
    Posts
    551
    This is not the proper way. You refers directly to the class, not to the instance of the class, that's why you face weird behavior. That sounds like:
    Code:
    Dim ws As Worksheet
        
    Set ws = Worksheet
    Try to insert more than one DataEdit as subforms in the main form or create some instances of the class Form_DataEdit using the keyword "New" and check where the class Form_DataEdit refers.

    Proper declarations:
    Code:
    Dim FD As Form_Data
    
    Set FD = Me
    'or
    Set FD = New Form_Data
    'or
    Set FD = Forms("Data")
    Code:
    Dim FD_EC_F As Form_DataEdit
    
    Set FD_EC_F = FD.DataEdit.Form
    'or
    Set FD_EC_F = New Form_DataEdit 'Creates a new stand alone form DataEdit, not a subform (member of a form).
    In your code, you have to use the pointer to the subform or the subform itself, not the class of the pointer/subform.
    Code:
    FD_EC_F.mdl_eDf_UpravujemeZaznam = True
    'or 
    FD.DataEdit.Form.mdl_eDf_UpravujemeZaznam = True
    Subforms are not stand alone forms. You can not refer to a subform with an expression like Forms("SubformName").

    PS: For the members of a class, I prefer the use of Property Get/Set/Let methods instead of public variables.

  6. #6
    pdanes is offline Competent Performer
    Windows Vista Access 2007
    Join Date
    Sep 2019
    Posts
    208
    Quote Originally Posted by accesstos View Post
    This is not the proper way. You refers directly to the class, not to the instance of the class, that's why you face weird behavior.
    I don't understand. I refer to the a class when I am instantiating a new reference to something. I do not use the NEW keyword, because that would create a new instance of the class. Access has already created the instance on its own, when the form opens. All I want to do is set up a reference to an already existing instance – the open subform.

    That sounds like:
    Code:
    Dim ws As Worksheet
        
    Set ws = Worksheet
    Yes, that is the way to refer to an existing instance of a worksheet. The same way here, I refer to an already existing instance of the running subform.

    Try to insert more than one DataEdit as subforms in the main form or create some instances of the class Form_DataEdit using the keyword "New" and check where the class Form_DataEdit refers.
    Why would I do that? That would give me multiple instances, and that is exactly what I do NOT want. In fact, the whole point of this post was that Access was acting like it had several instances, instead of the one that I want – the one and only instance – the subform of the main form.

    Proper declarations:
    Code:
    Dim FD As Form_Data
    
    Set FD = Me
    'or
    Set FD = Forms("Data")
    That works properly for the main form, and in fact, that is what I wound up having to do for the subforms as well.


    Code:
    Dim FD_EC_F As Form_DataEdit
    Yes, this works correctly, and is how I now have it.

    Code:
    Set FD_EC_F = FD.DataEdit.Form
    That did NOT work properly, and was the source of my problem.


    Code:
    'or
    Set FD = New Form_Data
    'or
    Set FD_EC_F = New Form_DataEdit 'Creates a new stand alone form DataEdit, not a subform (member of a form).
    I did not try this, but I cannot imagine that it would work correctly. I very much do NOT want a new instance. That is the result I had, in some weird half-baked fashion, and that is what I wanted to get rid of.

    In your code, you have to use the pointer to the subform or the subform itself, not the class of the pointer/subform.
    Code:
    FD_EC_F.mdl_eDf_UpravujemeZaznam = True
    'or 
    FD.DataEdit.Form.mdl_eDf_UpravujemeZaznam = True
    That is true, and that is how I refer to the subforms, and read or modify the values of the public variables in the subforms. But it wasn't working properly, because of the way I initialized the variable pointing to the subform. Now that I have the subform pointers initialized correctly, by referring DIRECTLY to the subform, all works properly.


    Subforms are not stand alone forms. You can not refer to a subform with an expression like Forms("SubformName").
    I have to. If I do it the way you suggest, I get the incorrect behavior. Initializing it this way, by referring directly to the form on start-up is what finally made it behave properly.

    PS: For the members of a class, I prefer the use of Property Get/Set/Let methods instead of public variables.
    I found one other statement by someone saying that was the preferred way, but with no explanation as to why. Obviously, it allows you more control over the activities of the variable, but if I have no need for additional control, it seems an unnecessary complication to me. Do you have some specific reason WHY that would be preferable, or is it just your own style?

Please reply to this thread with any new information or opinions.

Similar Threads

  1. Replies: 1
    Last Post: 04-12-2020, 12:52 PM
  2. Replies: 1
    Last Post: 10-16-2019, 03:45 PM
  3. Using Public variables between forms/queries/reports
    By dcrake in forum Sample Databases
    Replies: 2
    Last Post: 12-25-2015, 05:44 PM
  4. VBA Public variables
    By jmitchelldueck in forum Programming
    Replies: 5
    Last Post: 08-20-2015, 12:03 PM
  5. public variables
    By zul in forum Programming
    Replies: 3
    Last Post: 08-23-2011, 11:11 AM

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Other Forums: Microsoft Office Forums