将 Variant 数组中的元素作为参数传递给 ParamArray

Gre*_*reg 5 vba parameter-passing wrapper user-defined-functions paramarray

背景

\n

我正在创建一个名为 的 VBA 函数 (UDF) MyUDF(),它包装CallByName().

\n

我希望精确模仿 的签名和参数行为CallByName()。此外,MyUDF()必须将其Args()参数复制到模块化变量ArgsCopy\xe2\x80\x94 一个Variant数组 \xe2\x80\x94 ,然后将其元素MyUDF()作为进一步的参数传递给CallByName()传递给。

\n

不要问为什么 \xe2\x80\x94 这是一个很长的故事。

\n

参考

\n

CallByName()在 VBA 编辑器中显示如下

\n

2

\n

文档中是这样描述的:

\n
\n

句法

\n

CallByName (对象,过程名称,调用类型, [args()]_)

\n

CallByName函数语法具有以下命名参数

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n
部分描述
目的必需:变体对象)。将在其上执行函数的对象的名称。
进程名必需:变体字符串)。包含对象的属性或方法名称的字符串表达式。
呼叫类型要求:常数vbCallType类型的常量,表示正在调用的过程的类型。
参数()可选:变体数组)。
\n
\n

看来“ args()”实际上是一个ParamArray,而不是一个简单的Variant数组,但没有进一步的文档,我不能完全确定。

\n

格式

\n

我的初步设计是以下形式:

\n
\' Modular variable.\nPrivate ArgsCopy() As Variant\n\n\n\' Wrapper function.\nPublic Function MyUDF( _\n    ByRef Object As Object, _\n    ByRef ProcName As String, _\n    CallType As VbCallType, _\n    ParamArray Args() As Variant _\n)\n    \' ...\n    \n    \' Copy the argument list to the modular variable.\n    ArgsCopy = Args\n    \n    \' ...\n    \n    \' Pass the arguments (and modular variable) to \'CallByName()\'.\n    MyUDF = VBA.CallByName( _\n        Object := Object, _\n        ProcName := ProcName, _\n        CallType := CallType, _\n        Args := ArgsCopy _\n    )\nEnd Function\n
Run Code Online (Sandbox Code Playgroud)\n

显示签名

\n

与 相比CallByName()MyUDF()在 VBA 编辑器中显示如下,并以 结尾ParamArray Args() As Variant

\n

5

\n

只有将Args()a改为ParamArray数组Variant( ByRef Args() As Variant) 才能使它们显示相同:

\n

6

\n

然而,后者会与下面描述的 的功能行为CallByName()发生冲突。

\n

参数行为

\n

不幸的是,不能通过名称 ( )ArgsCopy传递,因为显然是 a并且因此只接受未命名的参数:ArgsArgs := ArgsCopyArgsParamArray

\n
VBA.CallByName( _\n    Object, ProcName, CallType, _\n    ArgsCopy(0), ArgsCopy(1), ..., ArgsCopy(n) _\n)\n
Run Code Online (Sandbox Code Playgroud)\n

笔记

\n

CallByName()请忽略返回 a的事实Variant,它可能(或可能不是)Object一定是Set。我已经在我的实际代码中考虑到了这一点

\n

问题

\n

我如何构建MyUDF(),特别是它的Args()论点,使得

\n
    \n
  1. CallByName()它的签名在参数的TypeOptionality 方面都模仿 的签名;
  2. \n
  3. 它准确地传递给CallByName()中列出的任意一组参数Args()?
  4. \n
\n

理想情况下,MyUDF()还将

\n
    \n
  1. 在Mac和 Windows上都能正常工作;
  2. \n
  3. 显示类似CallByName()像在 VBA 编辑器中
  4. \n
\n

6

\n

2

\n

第三和第四个标准是额外的,但我不要求它们。

\n

建议

\n

Visual Basic (VB)建议您可以将参数传递给 it,ParamArray如上所示MyUDF():参数是与 类型相同的数组中的元素ParamArray,并且该数组作为单个参数提供。但是,我在VB A中既没有找到记录也没有找到等效的实验。

\n

我确实在 Stack Overflow 上找到了这三个 VBA 问题,但我缺乏在这里应用他们的经验的经验。

\n
    \n
  1. 将参数数组传递给 CallByName VBA
  2. \n
  3. 将数组传递给 ParamArray
  4. \n
  5. 如何在 Mac OS 上从 Framework 文件查看接口规范
  6. \n
\n

更改方法签名

\n

第一个问题有一个解决方案,它改变了 的方法签名CallByName(),这样它Args()就是一个参数:一个Any数组。

\n

然而,我不熟悉Any”类型第三个问题(未回答)让我怀疑这个预处理器“魔法”是否可以在Mac上工作:

\n
\n
#If VBA7 Or Win64 Then\n  Private Declare PtrSafe Function rtcCallByName Lib "VBE7.DLL" ( _\n    ByVal Object As Object, _\n    ByVal ProcName As LongPtr, _\n    ByVal CallType As VbCallType, _\n    ByRef args() As Any, _\n    Optional ByVal lcid As Long) As Variant\n#Else\n  Private Declare Function rtcCallByName Lib "VBE6.DLL" ( _\n    ByVal Object As Object, _\n    ByVal ProcName As Long, _\n    ByVal CallType As VbCallType, _\n    ByRef args() As Any, _\n    Optional ByVal lcid As Long) As Variant\n#End If\n
Run Code Online (Sandbox Code Playgroud)\n
\n
Public Function CallWithArgs( _\n    ByRef Object As Object, _\n    ByRef ProcName As String, _\n    CallType As VbCallType, _\n    ByRef Args() As Variant _\n)\n   CallWithArgs = rtcCallByName(Object, ProcName, CallType, Args)\nEnd Function\n
Run Code Online (Sandbox Code Playgroud)\n