只是一个我似乎无法找到答案的问题.
我是以编程方式创建用户表单,我发现如果我将对象声明为"MSForms.Userform"类型,似乎无法设置高度和宽度,因为这些属性不存在,并且内部高度/ insidewidth是只读属性.
我发现如果我将它声明为通用类型"对象",我可以设置高度和宽度属性并完全按照我的意愿使用它.
因此,在我初始化对象后,我检查了本地窗口,差异似乎是:
所以我的问题是,使用不同的声明语句有什么区别?
谢谢!
编辑:添加了一些示例代码,以便您可以看到oject在声明方式不同时的行为方式.
(我无法正确显示此代码块 - 即使声明为基本语言)
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
Run Code Online (Sandbox Code Playgroud)
Rub*_*uck 10
当您导入组件到项目中,将它命名UserForm1
和可能 UserForm2
分别.
oForm == UserForm1
oForm1 == UserForm2
在过程运行之前,如果不知道特定对象类型,则可以使用Object数据类型声明对象变量.使用Object数据类型创建对任何对象的泛型引用.
你已经声明了这样的变量:
Dim oForm As MSForms.UserForm
Dim oForm1 As Object
Run Code Online (Sandbox Code Playgroud)
因此,初始化对象时会发生的事情oForm
被初始化为UserForm,而运行时确定Object oForm1
是UserForm1的实例,这不是同一个事情.
尝试在初始化之前更改oForm1的组件名称,您应该很快就会发现它们之间存在差异.
现在,如果您希望将类型安全性声明为通用表单并且您想要访问该Width
属性,则可以将UserForm强制转换为Object并像这样访问它.
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)
Run Code Online (Sandbox Code Playgroud)
这是我们在实现多个接口时经常使用的技巧.编译器只允许您使用在声明类对象的特定类型中定义的属性.
那有什么区别?实际上,在将事物声明为Object时,您没有智能感知.你也没有类型安全.这样做完全有效(虽然不推荐.)
Dim foo As New Baz
Dim bar As New Qux
Dim var As Object
Set var = foo
Set var = bar
Run Code Online (Sandbox Code Playgroud)
当您使用后期绑定时,对象确实非常方便,以避免添加对项目的引用.如果没有添加引用,您将被迫使用未知类型.
Dim xl As Object
Set xl = CreateObject("Excel.Application")
Run Code Online (Sandbox Code Playgroud)
另一个很大的区别是你将它留给运行时来确定变量将是什么类型的对象.正如您所发现的,它有时(很少,但有时)会产生令人惊讶的结果.