2014-10-16 150 views
2

只是一个问题,我似乎无法找到答案。将用户窗体声明为对象与MSForms.Userform之间的区别?

我正在编程创建一个用户窗体,我发现如果我声明我的对象为“MSForms.Userform”类型,似乎没有办法设置高度和宽度,因为这些属性不存在,insideheight/insidewidth是只读属性。

我发现的是,如果我将其声明为泛型类型“对象”,我可以设置高度和宽度属性并按照我的意愿使用它。

所以,以后我初始化对象,我查了当地人窗口和差异似乎是:

  • 当类型“对象”将初始化类型的实例“UserForm1”
  • 声明
  • 当类型“MSForms.Userform”,宣布它将初始化类型“窗体”的一个实例

所以我的问题是,是什么在使用不同的申报statments区别?

谢谢!

编辑:添加了一些示例代码,以便您可以看到如何声明不同的方式时,对象的行为是不同的。当您导入组件到项目

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 
+1

'UserForm1'是UserForm'的'特定实例,并且只在您的VBA项目的存在。类似于'Sheet1'和'Worksheet' – 2014-10-16 16:08:59

+0

蒂姆,我想我明白你在说什么,但仍然困惑于声明对象类型的差异。我在原始问题中添加了一些示例代码,以便您可以看到我在说什么。 – CBRF23 2014-10-16 19:42:11

+1

不同之处在于,至少有一部分是当你将它声明为一个对象时VB不会试图验证它的类型。你不明智,正如你看到它可以改变你如何访问属性。当你声明某种类型的东西时,VB会获得关于该类型的信息,并为你提供intellisense中的属性和方法。它也会阻止你将oForm设置为不是UserForm的东西。 – jac 2014-10-16 20:24:11

回答

5

将它命名分别为UserForm1可能UserForm2 -
(即使声明为基础的语言,我不能得到这个代码块才能正常显示)。

oForm == UserForm1

OFORM1 == UserForm2

现在,看着MSDN docs for Object我们发现:

可以声明与对象数据的对象变量在特定对象类型未知时才键入,直到该过程运行。使用对象数据类型来创建对任何对象的通用引用。

你声明的变量,像这样:

Dim oForm   As MSForms.UserForm 
Dim oForm1   As Object 

所以,当你初始化对象是oForm被初始化为用户窗体,当运行时确定对象oForm1是发生了什么UserForm1的实例,这是不一样的事情。

尝试在初始化之前更改oForm1的组件名称,并且您应该很快看到差异。

现在,如果你想声明的通用形式的类型安全,你要访问的Width属性,你可以投你的用户窗体为对象,以及访问它像这样。

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) 

这是我们在实现多个接口时经常使用的技巧。编译器将只允许您使用在声明类对象的特定类型中定义的属性。


那么有什么区别?实际上,当你将对象声明为事物时,你不会有智能感知。你也没有类型安全。这是完全有效的做到这一点(虽然不推荐)。

Dim foo As New Baz 
Dim bar As New Qux 
Dim var As Object 

Set var = foo 
Set var = bar 

对象不进来非常方便,当你使用后期绑定,以避免添加引用到您的项目,虽然。如果没有添加引用,您将被迫使用未知类型。

Dim xl As Object 
Set xl = CreateObject("Excel.Application") 

另一个很大的区别是你将它留给运行时间来确定变量是什么类型的对象。正如你发现的那样,它有时(很少,但有时)会产生令人惊讶的结果。

+1

ckuhn2003,谢谢你对两种情况下发生的事情的详细解释。对我了解正在发生的事情非常有帮助。 提供的示例很容易理解。 谢谢! – CBRF23 2014-10-17 19:07:05

+0

不客气! – RubberDuck 2014-10-17 19:14:00

1

我觉得你有你对差异答案:

  • 一个是类UserForm1的用户窗体对象,包裹在一个Object对象(类型对象/ UserForm1),可在PROC否则以后可以设定成什么,
  • 另一个是UserForm2类的UserForm对象。

但是,编译器将只允许使用属性/方法对于现有类型的类对象被声明为:

  • 对象有.WIDTH和.Height属性,因此OFORM1将允许您访问VBE组件UserForm2的实例化形式的这些属性(看看HERE进一步了解这一点),但oForm不会。
  • UserForms有一个.Show/.Hide方法,所以将有oForm显示VBE组件UserForm1的实例化/加载形式,但oForm1不会。

我已经做了一些测试,我只是想在我认为的修正过程宁可指向:

Dim FormAsForm As **UserForm1*** 
Dim FormAsObject As Object 

Set FormAsForm = New UserForm1 
Set FormAsObject = FormAsForm 

FormAsObject.Width = 200 

Debug.Print TypeName(FormAsForm) 
Debug.Print TypeName(FormAsObject) 

这里宣布FormAsForm为UserForm1,而不是用户窗体造成此错误在我的身边:

运行时错误 '438':对象不支持此属性或方法

然而,使用这个,FormAsForm已经加载并显示一次后。显示,然后卸载,FormAsForm从类型UserForm11/UserForm11降级到UserForm11/UserForm,并且不能用.Show再次显示。任何应该工作方法会造成这样的错误:

错误 '-2147418105':自动化错误

错误 '-2147418105':ERREUR自动化:L'appelé(serveur [PAS应用serveur])N” est pas pas disponible et a disparu; aucune connexion n'est valide。 L'appel peut-êtreétéexécuté。

当然,变量类型我只是给了来自当地人VBE窗口被读取,因为类型名(FormAsForm)只会带来一个:

运行时错误“13”:类型不匹配

对于记录,?TypeName(FormAsObject)在downcast后返回UserForm,而.Show方法会导致相同的“自动化错误”。

empty

这整个的一部分,我无法解释......

相关问题