San*_*arn 2 vb6 excel vba ms-office
我可以动态遍历所有预声明的对象吗?
这是我已经解决了一段时间的问题。理想情况下,我将遍历所有类并检查它们是否实现了某些接口。如果确实如此,则对它们执行一些代码。
目前,我必须提供一些要执行的类数组:
ClassesToCheck = Array(Task_Class1,Task_Class2,Task_Class3,Task_Class4, ...)
Dim klass as object
For each klass in ClassesToCheck
if klass.implements(ITask) then
Call klass.execute()
end if
next
Run Code Online (Sandbox Code Playgroud)
在理想的世界中,我会这样做:
Dim klass as object
For each klass in GET_PREDECLARED_CLASS_OBJECTS_FROM_MEMORY()
if klass.implements(ITask) then
Call klass.execute()
end if
next
Run Code Online (Sandbox Code Playgroud)
我不希望有任何简单的方法来执行此操作,但是我已经对VBA运行时内存进行了一些研究/探索...我认为应该可以,并使用VBA6.DLL找到了一些VB6示例。但是,不幸的是,Microsoft Office本身没有提供此DLL。但是,VBA6.DLL可能被“编译为” Microsoft Office本身。所以方法/字段也应该保存在内存中的某个地方,您只需要知道它们在哪里使用指针数学即可(这是我的理论)
我不认为有人对此有任何经验吗?
一个VB_PredeclaredId属性,使您的Class1标识用这个名字自动指全球范围内的对象,例如,UserForm1是一类模块的名称(一个设计师,但是这部分是无关紧要的),并且它是通过催生了一个全球性的,AUTOMAGIC对象的名称VBA在运行时,并且编译器知道Class1.DoStuff合法,因为它知道Class1已VB_PredeclaredId设置为True。
感谢Wayne Phillips(vbWatchDog)和其他贡献者的工作和贡献,Rubberduck充分利用了此内部API。
如链接代码(C#)所示,您可以通过将指针变成具有以下特定布局的结构,ITypeLib从其References集合中获取VBA项目的名称:
[StructLayout(LayoutKind.Sequential)]
internal struct VBEReferencesObj
{
IntPtr _vTable1; // _References vtable
IntPtr _vTable2;
IntPtr _vTable3;
IntPtr _object1;
IntPtr _object2;
public IntPtr _typeLib; // <--- here's the pointer you want
IntPtr _placeholder1;
IntPtr _placeholder2;
IntPtr _refCount;
}
Run Code Online (Sandbox Code Playgroud)
在VBA中,这是用户定义的Type,可能如下所示:
Public Type VBEReferencesObj
vTable1 As LongPtr
vTable2 As LongPtr
vTable3 As LongPtr
object1 As LongPtr
object2 As LongPtr
typelibPointer As LongPtr '<~ only this one matters
placeholder1 As LongPtr
placeholder2 As LongPtr
refCount As LongPtr
End Type
Run Code Online (Sandbox Code Playgroud)
一旦有了指向的指针ITypeLib,您就应该能够获得VBA项目的类型库。
从那里开始,您将要遍历类型,并从那里确定类型是否TYPEFLAGS已TYPEFLAG_PREDECLID打开(我们在此处进行操作)。
显然,这是很多极易发生崩溃的反复试验编码,我不建议您进行任何此类编码,但是在任何情况下,即使不建议这样做也是可能的。
随时学习Rubberduck.VBEEditor.ComManagement.TypeLibs命名空间。