VBA - 使用类的文本名创建新对象

时间:2009-06-29 10:45:36

标签: vba excel-vba excel

有没有办法使用类的文本名称将对象设置为新的类实例?

我将有一个类库,根据其他变量,我想在运行时获取其中一个类。

E.g。我有“CTest1”,“CTest2”,“CTest3”

我的功能类似于下面的

Function GetTestClass(lngClassNo as long) as Object

 Dim strClassName as String    
 strClassName = "CTest" & CStr(lngClassNo)

 Set GetTestClass = New instance of class(strClassName)

End Function

6 个答案:

答案 0 :(得分:4)

VBA没有任何反映,所以我认为这是不可能的。你不得不做以下事情我害怕:

Function GetTestClass(lngClassNo as long) as Object

    Select Case lngClassNo
    Case 1
        Set GetTestClass = New CTest1
    Case 2
        Set GetTestClass = New CTest2
    ...

    End Select

End Function

除非你的CTest类是在COM DLL中定义的,否则你可以使用CreateObject语句。您需要使用VB6来创建这样的DLL,但是您无法在Excel,Access等中创建DLL。

Function GetTestClass(lngClassNo as long) as Object

    Set GetTestClass = CreateObject("MyDll.CTest" & lngClassNo)

End Function

答案 1 :(得分:3)

你可以使用元编程来做到这一点,虽然看起来确实很糟糕。 下面是一个使用几个辅助函数的示例(为简洁起见省略):

Public Function CreateInstance(typeName As String) As Object
    Dim module As VBComponent
    Set module = LazilyCreateMPCache()

    If Not FunctionExists(typeName, module) Then
        Call AddInstanceCreationHelper(typeName, module)
    End If

    Dim instanceCreationHelperName As String
    instanceCreationHelperName = module.name & ".GetInstanceOf" & typeName
    Set CreateInstance = Application.Run(instanceCreationHelperName)
End Function

Sub AddInstanceCreationHelper(typeName As String, module As VBComponent)
   Dim strCode As String
   strCode = _
   "Public Function GetInstanceOf" & typeName & "() As " & typeName & vbCrLf & _
       "Set GetInstanceOf" & typeName & " = New " & typeName & vbCrLf & _
   "End Function"
   Call AddFunction(strCode, module)
End Sub

答案 2 :(得分:2)

VB类定义实际上是在幕后定义COM接口,因此可以使用implements关键字将数据类型定义为具有具体实现的抽象接口定义。

要获得任何类型的多态性,您必须这样做,否则您将遇到投射问题。使用VB执行此操作有点繁琐但技术上可行。如果你想深入了解Dan Appleman或Matthew Kurland的一些高级VB书籍。我不确定它们是否仍在印刷中,但它们可能通过亚马逊商城推出。

这适用于VB6,我相当确定它适用于VBA。

答案 3 :(得分:2)

嗨,我知道这是一个旧帖子,但如果你还需要答案,请看这里

http://www.codeproject.com/Articles/164036/Reflection-in-VBA-a-CreateObject-function-for-VBA

它应该回答你的问题。

答案 4 :(得分:0)

您可以使用集合类或对象数组来执行此操作。所有对象都在一个数组中。

在您的类中有一个.Name属性,当您创建它的实例时,请执行以下操作:

Dim CTest() as New CTest
For n = 1 to 10
    Redim Preserve CTest(n)
    CTest(n).Name = "CTest" & CStr(n)
Next l

快速而肮脏。上面的示例将在单个对象数组中返回10个CTest对象。您也可以放弃.Name并使用CTest(n)。

答案 5 :(得分:0)

CallByName功能可以帮到你。我们假设项目中有一些类模块:clsSample0clsSample1clsSample2。添加一个名为clsSpawner的新类模块,它将所有目标类列为与e具有相同名称的公共变量。 G。 instance_前缀,并使用New关键字声明:

Public instance_clsSample0 As New clsSample0
Public instance_clsSample1 As New clsSample1
Public instance_clsSample2 As New clsSample2

在模块中添加Function Spawn()代码:

Function Spawn(sClassName) As Object

    Set Spawn = CallByName(New clsSpawner, "instance_" & sClassName, VbGet)

End Function

使用以下代码测试它:

Sub TestSpawn()

    Dim objSample0a As Object
    Dim objSample0b As Object
    Dim objSample1 As Object
    Dim objSample2 As Object

    Set objSample0a = Spawn("clsSample0")
    Set objSample0b = Spawn("clsSample0")
    Set objSample1 = Spawn("clsSample1")
    Set objSample2 = Spawn("clsSample2")

    Debug.Print TypeName(objSample0a)            ' clsSample0
    Debug.Print TypeName(objSample0b)            ' clsSample0
    Debug.Print objSample0a Is objSample0b       ' False
    Debug.Print TypeName(objSample1)             ' clsSample1
    Debug.Print TypeName(objSample2)             ' clsSample2

End Sub

它是如何工作的? Spawn函数实例化clsSpawner并调用clsSpawner实例返回请求的属性,实际clsSpawner实例由于{{1}声明而创建目标类的新实例} keyword并返回引用。