作者:mobiledu2502859367 | 来源:互联网 | 2023-05-24 13:47
请考虑以下代码:
Public Sub VBACompilerIsMad()
Dim Ap As Application
Dim Wb As Workbook
Dim Ws As Worksheet
Debug.Print Ap.XXX ' No compile error
Debug.Print Wb.XXX ' No compile error
Debug.Print Ws.XXX ' Compile error
End Sub
当我编译它时,我得到一个编译器错误,用于引用一个不存在的成员Worksheet
.但是,如果我注释掉最后一行,则没有编译器错误,即使它们既Application
没有Workbook
方法或属性也没有XXX
.这是因为如果我声明Ap
,并Wb
作为Object
变量.
为什么编译器处理Application
/ Workbook
不同Worksheet
?
有没有像这样的其他类,编译器似乎对待它们好像Object
?
1> GSerg..:
正如我已经解释过的那样(分别是kudos),这是一个COM功能.
默认情况下,COM假定接口是可扩展的,也就是说,它允许在运行时添加成员.如果这不是所需的行为,则可以将该 [nonextensible]
属性应用于接口定义,该接口定义声明接口仅接受在类型库中显式定义的方法.
dispinterface _Application
并且dispinterface _Workbook
没有在Excel类型库中设置此标志dispinterface _Worksheet
.
同样,ADO的dispinterface _Connection
没有[nonextensible]
,dispinterface _Command
确实.
要了解哪些是可扩展的,请TypeLib Info
在项目的引用中添加引用并运行:
Dim t As tli.TLIApplication
Set t = New tli.TLIApplication
Dim ti As tli.TypeLibInfo
Set ti = t.TypeLibInfoFromFile("excel.exe")
Dim i As tli.InterfaceInfo
For Each i In ti.Interfaces
If (i.AttributeMask And tli.TYPEFLAG_FNONEXTENSIBLE) <> tli.TYPEFLAG_FNONEXTENSIBLE Then
Debug.Print i.Name
End If
Next
您将看到几乎所有接口都是可扩展的,因此大多数接口都被推出调试窗口,您只能看到最后的接口.更改<>
到=
打印那些不能扩展,也有少得多他们.
来吧小伙子们.这个出色的答案需要更多的认可.
@ vba4all奖励赏金,我再给它一个!:)
2> KekuSemau..:
一点假设:
您可以像 ADODB.Connection对象一样调用存储过程(如底部).(在几个 msdn网站上的这个例子看起来很奇怪).
所以在VBS/VBA中有一些像'匿名/动态方法'的机制.它可能是这里为类Application
和Workbook
类激活的类似机制- 虽然我没有看到确切的位置和方式.
一个测试支持基本的想法:
我已经测试了这个参考Microsoft ActiveX Data Objects 2.8 Library
:
Public Sub testCompiler()
Dim cn As ADODB.Connection
Dim cmd As ADODB.Command
Debug.Print cn.XXX
Debug.Print cmd.XXX
End Sub
cn.XXX
也没有抛出一个编译错误,cmd.XXX
确实.
+1用于解决*"是否还有其他这样的类,编译器似乎将它们视为对象?"*问题的一部分:)