0

Suppose I have a simple VBA project containing a UserForm called UserForm1

If I pass UserForm1 to a function as a Userform type variable I cannot access all the members of the UserForm, for example the the .Height property, as you see in this simple example.

In order to get this working I need to pass the UserForm as an Object, but that's pretty annoying since I lose all the autocomplete features of the IDE.

    Sub CATMain()

        Call printFormHeight_Works(UserForm1)
        Call printFormHeight_Broken(UserForm1) '--> error


    End Sub


    Sub printFormHeight_Broken(ByRef form As UserForm)

        Debug.Print form.Caption '---> works!
        Debug.Print form.Height '---> Run-time error 438: Object doesn't support this property or method

    End Sub

    Sub printFormHeight_Works(ByRef form As Object)

        Debug.Print form.Caption '---> works!
        Debug.Print form.Height  '---> works!

    End Sub

So my questions are:

  1. Why I have to pass the Userform as an Object?
  2. Is there a better way to pass a Userform to a function and be able to access all its members?
Federico Destefanis
  • 968
  • 1
  • 16
  • 27

1 Answers1

2

In your example, UserForm1 is not only the name of the userform, but it's also the class type. As such, you can pass the userform either by class type (ie. UserForm1) or by generic object (ie. Object).

When passing it by class type, the signature for the function would be...

Sub printFormHeight_Works(ByRef form As UserForm1) 'class type is UserForm1

When passing it by generic type, the signature for the function would be...

Sub printFormHeight_Works(ByRef form As Object) 'class type is Object

As you've already seen, when passing it by class type or generic object, all the properties and methods are available. However, the IntelliSense is only available when passing it by class type.

The advantage with passing it by generic object, though, is that you can pass it two or more different class types. So, for example, if you have two userforms, UserForm1 and UserForm2, you have two class types. And, so the function can accept either userform. The actual class type gets resolved at run-time.

Now, when you declare the parameter as UserForm, it's a whole different class. And, as you've already seen, the properties and methods change, and are somewhat limited. Specifically, the Show method is not available. I don't know in what context one would use it, but I'm sure someone here on SO will be able to provide an explanation.

Domenic
  • 7,844
  • 2
  • 9
  • 17
  • thx @Domenic, as you pointed out the rationale behind my printFormHeight signatures is to accept any UserForm of my project, not only UserForm1. Still the solution to pass the form as an Object seems to me fairly limited. But I understand that UserForm1 is a class by itself (and this answer my first question) – Federico Destefanis Apr 17 '20 at 15:20
  • I think the only real disadvantage with declaring it as Object is that it get's resolved as runtime, and so it's less efficient. But in practical terms, it may not make much difference. And, as far as having access to the IntelliSense, simply declare it as the specific class when writing your code so that you have access to it, and then change it to Object when finished. – Domenic Apr 17 '20 at 15:49