Question

I'm running a VBA macro from SolidWorks. The form doubles as an input for two types of document. In the UserForm.Initialize subroutine I'm changing the name of the UserForm's Caption depending on which document type is open. Whenever I do this though, the program reruns UserForm.Initialize, and when it's all done, it carries on from where it left of, effectively running twice.

Does anyone know a way around this bizarre behaviour? I tried putting the FormName.Caption command into its own Sub but the result is the same.

Many thanks.

Was it helpful?

Solution

I can't replicate the problem and I don't know what SolidWorks is, so that may have something to do with it. Perhaps you can post a made-up example that shows Initialize being called twice.

My guess would be that it's related to auto-instantiating variables. When you use UserForm1, you are instantiating an object variable called UserForm1 that points to an object, also called UserForm1. It's similar to using the New keyword in a Dim statement. You never defined UserForm1 (the variable), but VBA did and the first time you use it, it instantiates automatically.

You should try to use the Me keyword when working inside the userforms class module (userforms are classes just like other objects except that they have a user interface element). In the Initialize event, say

Me.Caption = "blah"

instead of

UserForm1.Caption = "blah"

It could be (just a theory that I wasn't able to prove) that the flag that gets set to say "I'm pointing to a real instance" isn't set by the time you change the Caption property, and that by using the auto-instantiating variable UserForm1, you are forcing another instantiation.

Even better, don't use auto-instantiating variables, convenient though they are (and don't use the New keyword in a Dim statement either). You can control when your variables are created and destroyed and it's a best practice. Something like this in a standard module

Sub uftst()

    Dim uf As UserForm1

    Set uf = New UserForm1 'you control instantiation here

    'Now you can change properties before you show it
    uf.Caption = "blech"
    uf.Show

    Set uf = Nothing 'overkill, but you control destruction here

End Sub

Note that if the ShowModal property is set to False that the code will continue to execute, so don't destroy the variable if running modeless.

OTHER TIPS

As Dick suggested, you should be able to stop the behavior by making sure to use me.caption instead of Userform1.caption.

Here's a way you can replicate the issue for those who are curious:

Create a Userform (Userform1) make sure you set ShowModal to false or you won't be able to see this.

In a module add the following:

Option Explicit
Sub ShowUserForm()
    Dim uf As UserForm1
    Set uf = New UserForm1
End Sub

In UserForm1 list the following code:

Option Explicit
Private Sub UserForm_Initialize()
    UserForm1.Caption = "I'm UserForm1!" 'This will call the Initialize method of Userform1 not Me.
    Me.Caption = "I'm Me!" 
    Me.Show
End Sub

Run ShowUserForm. You now have two Userforms with different captions.

Incidentally, if you have an Initialize method like I displayed adding Set uf = Nothing to the ShowUserForm sub actually fails to close either form.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top