Just a question that I can't seem to find an answer on.
I'm programmatically creating a userform, and I've found if I declare my object as the type "MSForms.Userform" there seems to be no way to set the height and width, as these properties don't exist, and insideheight / insidewidth are read only properties.
What I found was if I declare it as the generic type "object", I can set the height and width properties and use it exactly as I want.
So, after I initialize the object, I checked the locals window and the difference seems to be:
So my question is, what is the difference in using the different declare statments?
Thanks!
EDIT: Added some sample code so you can see how the oject act's differently when declared differently.
(I can't get this code block to display properly - even with the language declared as basic)
Sub TestUserForm()
'NOTE: You need to add a reference to Microsoft Visual Basic
' for Applications Extensibility 5.3
'Declare variables
Dim oForm As MSForms.UserForm
Dim oForm1 As Object
Dim oComp As VBComponent
Dim oComp1 As VBComponent
'Create new form objects in the VBA project programmatically
Set oComp = Application.VBE.ActiveVBProject.VBComponents.Add(ComponentType:=vbext_ct_MSForm)
Set oComp1 = Application.VBE.ActiveVBProject.VBComponents.Add(ComponentType:=vbext_ct_MSForm)
'Initailize an object of each new form
Set oForm = VBA.UserForms.Add(oComp.Name)
Set oForm1 = VBA.UserForms.Add(oComp1.Name)
'Compare what happends when trying to set the width and height properties
With oForm1 'This works
.Height = 200
.Width = 100
End With
With oForm1 'This does not work
.Properties("Width") = 100
.Properties("Height") = 200
End With
With oForm 'This does not work
.Height = 200
.Width = 100
End With
With oForm 'This does not work
.Properties("Width") = 100
.Properties("Height") = 200
End With
'Remove the forms from the project
Application.VBE.ActiveVBProject.VBComponents.Remove oComp
Application.VBE.ActiveVBProject.VBComponents.Remove oComp1
End Sub
When you import the components into the project it will name it UserForm1
and probably UserForm2
respectively.
oForm == UserForm1
oForm1 == UserForm2
Now, looking at the MSDN docs for Object we find that:
You can declare an object variable with the Object data type when the specific object type is not known until the procedure runs. Use the Object data type to create a generic reference to any object.
You've declared the variables like so:
Dim oForm As MSForms.UserForm
Dim oForm1 As Object
So what happens when you initialize the objects is oForm
gets initialized as a UserForm, while the runtime determines that the Object oForm1
is an instance of UserForm1, which is not the same thing.
Try changing the component name of oForm1 prior to initializing it and you should pretty quickly see the difference.
Now, if you want the type safety of declaring as a generic form and you want to access the Width
property, you can cast your UserForm as an Object and access it like so.
Dim FormAsForm As UserForm
Dim FormAsObject As Object
Set FormAsForm = New UserForm1
Set FormAsObject = FormAsForm
FormAsObject.Width = 200
Debug.Print TypeName(FormAsForm)
Debug.Print TypeName(FormAsObject)
This is a trick we use often when implementing multiple interfaces. The compiler will only allow you to use properties that are defined in the particular type the class object is declared as.
So what's the difference? Practically speaking, you get no intellisense when declaring things as Object. You also get no type safety. It's perfectly valid to do this (although not recommended.)
Dim foo As New Baz
Dim bar As New Qux
Dim var As Object
Set var = foo
Set var = bar
Object does come in extremely handy when you're using late binding to avoid adding references to your project though. Without the adding a reference, you're forced into using an unknown type.
Dim xl As Object
Set xl = CreateObject("Excel.Application")
The other big difference is you're leaving it up to the runtime to determine what kind of object the variable will be. As you discovered, it will sometimes (rarely, but sometimes) produce surprising results.