VBA中的自定义回调

Jos*_*nig 14 vba callback

注意标签:VBA,而不是VB6,而不是VB.NET.

这特定于MS Access中的VBA.我在一个名为"Enumerable"的模块中构建了一组方法.它做了许多令人联想到.NET中的Enumerable类和接口的事情.我想要实现的一件事是ForEach方法,与.NET Enumerable.Select方法类似.

我构建了一个使用Application.Run方法为每个元素调用函数的版本,但Application.Run仅适用于用户定义的方法.例如,以下工作:

' User-defined wrapper function:
Public Function MyReplace( _
    Expression As String, Find As String, StrReplace As String, _
    Optional Start As Long = 1, _
    Optional Count As Long = 1, _
    Optional Compare As VbCompareMethod = vbBinaryCompare)
    MyReplace = Replace(Expression, Find, StrReplace, Start, Count, Compare)
End Function

' Using Application.Run to call a method by name
Public Sub RunTest()
    Debug.Print Run("MyReplace", "Input", "In", "Out")
End Sub
Run Code Online (Sandbox Code Playgroud)

RunTest按预期打印"输出".以下不起作用:

Debug.Print Run("Replace", "Input", "In", "Out")
Run Code Online (Sandbox Code Playgroud)

它抛出运行时错误430:"类不支持自动化或不支持预期的接口".这是预期的,因为文档声明Application.Run仅适用于用户定义的方法.

VBA确实有一个AddressOf运算符,但只有在将函数指针传递给外部API函数时才有效; 使用AddressOf创建的函数指针在VBA中不可使用.同样,这在文档中有说明(或者参见例如VBA - CallBacks =少量美元少于几美元?).

那么有没有其他方法来识别和调用使用变量的方法?或者我的回调尝试是否会通过Application.Run方法限制为用户定义的函数?

Jos*_*nig 5

一周内没有其他答案......为了解决这个问题,我能想到的最好:

  1. 我构建了一个帮助器模块,为了调用,它将ParamArray解析为单个参数CallByName.如果你将ParamArray传递给CallByName它,它会将所有参数混合成一个实际的,Array并将其传递给你试图调用的方法中的第一个参数.
  2. 我构建了两个ForEach方法:一个调用Application.Run,另一个调用CallByName.如问题中所述,Application.Run仅适用于用户定义的全局(公共模块)方法.反过来,CallByName只适用于实例方法,并需要一个对象参数.

这仍然让我无法Trim()通过名称直接调用内置全局方法(例如).我的解决方法是构建只调用内置全局方法的用户定义的包装器方法,例如:

Public Function FLeft( _
   str As String, _
   Length As Long) As String
    FLeft = Left(str, Length)
End Function

Public Function FLTrim( _
   str As String) As String
    FLTrim = LTrim(str)
End Function

Public Function FRight( _
   str As String, _
   Length As Long) As String
    FRight = Right(str, Length)
End Function

...etc...
Run Code Online (Sandbox Code Playgroud)

我现在可以用这些来做这样的事情:

' Trim all the strings in an array of strings
trimmedArray = ForEachRun(rawArray, "FTrim")

' Use RegExp to replace stuff in all the elements of an array
' --> Remove periods that aren't between numbers
Dim rx As New RegExp
rx.Pattern = "(^|\D)\.(\D|$)"
rx.Global = True
resultArray = ForEachCallByName(inputArray, rx, "Replace", VbMethod, "$1 $2")   
Run Code Online (Sandbox Code Playgroud)

  • @ user357269对于VBA中的第一类函数的实现(例如,可以存储在变量中,传递给函数并匿名调用的函数),请参阅[this](http://codereview.stackexchange.com/questions/138557 /功能的框架). (4认同)