• Hi All

    Please note that at the Chandoo.org Forums there is Zero Tolerance to Spam

    Post Spam and you Will Be Deleted as a User

    Hui...

  • When starting a new post, to receive a quicker and more targeted answer, Please include a sample file in the initial post.

Scope of a user form declared public

BobBridges

Active Member
I'm getting into user forms in Excel for the first time, and I'm puzzled by the way it behaves in one regard.

I've created a form that I named RoMOpts. I don't usually name the object variable the same as the class name, but in this case I did: In the main module I declared an variable named RoMOpts as Public, then set RoMOpts = New RoMOpts. Inside the RoMOpts module I refer to its controls as chkVest, radSts and so on; in other modules it's necessary to qualify the references: RoMOpts.chkVest, RoMOpts.radSts and so on.

So far, so good. But the scope of Public RoMOpts apparently doesn't extend to the code in another class module. When I invoke a method of that class and try to watch the values of RoMOpts, I'm told that the object hasn't yet been set. Then when the code first refers to RoMOpts.radSts, the Watch window is suddenly aware of RoMOpts—but all its values are the defaults, not the current values as set by the operator (me, I mean). I get the impression that it's watching a different object, not the one I declared Public.

Aren't Public variables available to other class modules? Sure, they are. But not this one. Is it because I've named the object the same as the class, or are user forms different in this regard, or what? Anyone know?
 
Yes, it is because you named the variable the same as the class and because the userform is auto instancing, which creates a conflict. You;'d have to refer to the variable using modulename.variablename syntax but it's much better to just rename your variable.
 
Which is what I did after posting the question yesterday, and of course that solved the problem; I just didn't understand why. "Auto-instancing", that explains it (assuming I understand what it means). Is that documented anywhere? I looked through a lot of the documentation on user forms and didn't see it. As so often happens, it was while carefully defining the problem during the above post that I got a clearer idea of what might be going wrong.

I did qualify the variable name with the object name—referring to it as RoMOpts.radSts and so forth—but inside that other class it was simply pointing to a different copy of RoMOpts. And if you object "Wait, I didn't say the object name, I said the module name", remember the module and the object are both named RoMOpts; they're the same.

And thanks, by the way.
 
But the module is named RoMOpts, too; that's what I keep saying. According to you, that's the cause of the problem (and I've confirmed that by renaming the variable). Do you mean I have to refer to "RoMOpts.RoMOpts.radSts"?

But, as you say, simpler to change the variable name:
Code:
Set ofrm = New RoMOpts
 
Why do you have a variable named RoMOpts of type RoMOpts declared in the class module RoMOpts??
 
It wasn't quite that complicated. I had a user form named RoMOpts, and when I set a variable to point to it ("Set <var> = New RomOpts") I named the variable "RoMOpts" too.

Inside the RoMOpts module I could refer to the controls by their unqualified names, such as "radSts". In the main module I could refer to them using their qualified variable name, eg "RoMOpts.radSts". But in another class module, where I expected to be able to refer to RoMOpts.radSts, I found that it wasn't working properly. I eventually discovered that "RoMOpts.radSts" did indeed point to the controls of a user form named RoMOpts—but it was a different instance of the user form! (this despite the fact that I had declared the variable RoMOpts public), so that its controls didn't match what the operator had chosen when the main routine displayed it.

I solved this, as you suggested, by naming the public variable "ofrm" instead of "RoMOpts", and then referring in that other class module to ofrm.radSts etc.

It occurs to me this morning that if user forms are auto-instancing, as you said in your first post, that maybe I don't have to point a variable to it at all? I don't think I'll go back and change a working program at this late date, but maybe next time I have to do something with a user form I'll experiment with that idea.
 
Then my original answer stands - you would need to refer to the RoMOpts variable via the module it was declared in.

Although userforms are auto-instancing (which is why you can simply write code like userform1.show), it is not generally regarded as best practice to use that auto-instance, sio I definitely wouldn't switch to it if you are currently using variables. Just don't give variables the same name as their class, or module, or project, or anything else really :)
 
Right, I normally don't. I just couldn't think of a great name, in this case, that fits my usual naming standards, since "frm" is hardly specific. But since the program uses only one user form I suppose "ofrm" is safe enough.

I can't tell about one thing you're telling me: Do I misunderstand, or do you? You say "you would need to refer to the RoMOpts variable via the module it was declared in". That sounds like you're saying ...

Oh, wait, I get it; I just noticed the italics. (They're not as obvious in Arial.) The module in which I declared "Public RoMOpts" is ... I forget what I named it just now, but let's pretend it's named "mMain". To refer in other modules to that instance of RoMOpts, I would have to use "mMain.RoMOpts.<controlname>". Ah, that makes sense, thanks. I won't do that, of course; I'll continue to use ofrm.<controlname>.
 
Back
Top