Excel VBA 将函数或子程序存储在数组中

Excel VBA store functions or subroutines in an array

在C/C++中,当我有一堆函数(指针)时,我可以将它们存储在数组或向量中,然后按一定顺序一起调用其中一些。可以在 VBA 中做类似的事情吗?

谢谢!

是的,但我不推荐它。 VBA 并不是真正为它而建。您已使用 Excel 标记此问题,因此我将描述如何针对该 Office 产品完成此操作。一般概念适用于大多数 Office 套件,但每个不同的产品对 Application.Run 方法都有不同的语法。

首先,了解动态调用过程的两种不同方法 (sub/function) 以及何时使用它们很重要。

Application.Run

Application.Run 将 运行 子程序或调用存储在标准 *.bas 模块中的函数。

第一个参数是过程的名称(作为字符串传入)。之后,您最多可以传递 30 个参数。 (如果您的程序需要更多,为了代码的热爱而重构。

关于 Application.Run 还有两件重要的事情需要注意。

  1. 您不能使用命名参数。参数必须按位置传递。
  2. 作为参数传递的对象被转换为值。这意味着如果您尝试 运行 一个需要将默认属性作为参数的对象的过程,您可能会遇到意外问题。

    Public Sub Test1()
        Application.Run "VBAProject.Module1.SomeFunction"
    End Sub
    

外卖:

使用标准模块时使用 Application.Run。

VBA.Interaction.CallByName

CallByName执行一个对象的方法,或者sets/gets一个属性一个对象。

它将要调用方法的对象的实例作为参数,以及方法名称(同样是字符串)。

Public Sub Test2()
    Dim anObj As SomeObject
    Dim result As Boolean

    result = CallByName(anObj, "IsValid")
End Sub

外卖:

当你想调用一个class的方法时使用CallByName

没有指针。

如您所见,这些方法都不使用实际指针(至少不使用外部指针)。它们接受字符串,然后使用这些字符串找到指向您要执行的过程的指针。因此,您需要知道要执行的过程的 确切 名称。您还需要知道需要使用哪种方法。 CallByName 有额外的负担需要您要调用的对象的实例。无论哪种方式,您都可以将这些名称存储为数组或集合中的字符串。 (哎呀,连字典都说得通。)

因此,您可以将它们硬编码为字符串,或者尝试在 运行 时提取适当的过程名称。为了提取过程名称,您需要通过 Microsoft Visual Basic for Applications Extensibility 库与 VBIDE 本身进行交互。在这里解释所有这些需要太多的代码和工作,但我可以为您指出一些很好的资源。

文章和 SE 问题:

  1. Chip Pearson's Programming The VBA Editor
  2. Extending the VBA Extensibility Library
  3. Ugly workaround to get the vbext_ProcKind is breaking encapsulation
  4. Automagic testing framework for VBA
  5. How to get the procedure or function name at runtime
  6. Import Lines of Code
  7. Meta Programming in VBA: The VBIDE and Why Documentation is Important

我的一些问答代码:

  1. vbeCodeModule
  2. vbeProcedure
  3. vbeProcedures

解决方法是枚举并使用 switch 语句。您可以将枚举类型(长整型)存储在数组中。例如:

Enum FType
    func1
    func2
    func3
End Enum

Sub CallEnumFunc(f As FType, arg As String)
    Select Case f
        Case func1: MyFunction1(arg)
        Case func2: MyFunction2(arg)
        Case func3: MyFunction3(arg)
    End Select
End Sub

Dim fArray(1) As FType
fArray(0) = func1
fArray(1) = func2
CallEnumFunc fArray(1), "blah"