Background
I am creating a VBA function (UDF) called MyUDF(), which wraps CallByName().
I wish to mimic precisely the signature and parametric behavior of CallByName(). Furthermore, MyUDF() must copy its Args() argument to a modular variable ArgsCopy — a Variant array — whose elements are then passed by MyUDF() as further arguments to CallByName().
Don't ask why — it's a long story.
Reference
CallByName() displays in the VBA editor like so

and it is described in the documentation like so:
Syntax
CallByName (object, procname, calltype, [args()]_)
The CallByName function syntax has these named arguments:
Part Description object Required: Variant (Object). The name of the object on which the function will be executed. procname Required: Variant (String). A string expression containing the name of a property or method of the object. calltype Required: Constant. A constant of type vbCallType representing the type of procedure being called. args() Optional: Variant (Array).
It appears that "args()" is actually a ParamArray, rather than a simple Variant array, but without further documentation, I can't be perfectly sure.
Format
My tentative design is of the following form:
' Modular variable.
Private ArgsCopy() As Variant
' Wrapper function.
Public Function MyUDF( _
ByRef Object As Object, _
ByRef ProcName As String, _
CallType As VbCallType, _
ParamArray Args() As Variant _
)
' ...
' Copy the argument list to the modular variable.
ArgsCopy = Args
' ...
' Pass the arguments (and modular variable) to 'CallByName()'.
MyUDF = VBA.CallByName( _
Object := Object, _
ProcName := ProcName, _
CallType := CallType, _
Args := ArgsCopy _
)
End Function
Displayed Signature
In contrast to CallByName(), MyUDF() displays in the VBA editor like so, and concludes with ParamArray Args() As Variant:

Only by changing Args() from a ParamArray to a Variant array (ByRef Args() As Variant) can we make them display identically:

However, the latter would clash with the functional behavior described below for CallByName().
Parametric Behavior
Unfortunately, one cannot pass ArgsCopy to Args by name (Args := ArgsCopy), since Args is apparently a ParamArray and would thus accept only the unnamed arguments:
VBA.CallByName( _
Object, ProcName, CallType, _
ArgsCopy(0), ArgsCopy(1), ..., ArgsCopy(n) _
)
Note
Please disregard the fact that CallByName() returns a Variant, which may (or may not) be an Object that must be Set. I have already accounted for this in my actual code.
Question
How do I construct MyUDF(), and especially its Args() argument, such that
- its signature mimics that of
CallByName(), in both theTypeandOptionality of its parameters; and - it accurately passes to
CallByName()any arbitrary set of arguments listed inArgs()?
Ideally, MyUDF() will also
- work properly on both Mac and Windows; and
- display like
CallByName()in the VBA editor:


This 3rd and 4th criteria are a bonus, but I don't require them.
Suggestions
Visual Basic (VB) suggests that one may pass arguments to its ParamArray as in MyUDF() above: the arguments are elements in an array of the same type as the ParamArray, and this array is supplied as a single argument. However, I have found neither a documented nor an experimental equivalent in VBA.
I did find these three VBA questions on Stack Overflow, but I lack the experience to apply their lessons here.
- Passing an array of Arguments to CallByName VBA
- Pass array to ParamArray
- How to view interface spec from Framework files on Mac OS
Change Method Signature
That first question has a solution, which changes the method signature for CallByName(), such that Args() is a single argument: an Any array.
However, I am unfamiliar with the "Any" type, and the third question (unanswered) makes me doubt this preprocessor "magic" could work on a Mac:
#If VBA7 Or Win64 Then Private Declare PtrSafe Function rtcCallByName Lib "VBE7.DLL" ( _ ByVal Object As Object, _ ByVal ProcName As LongPtr, _ ByVal CallType As VbCallType, _ ByRef args() As Any, _ Optional ByVal lcid As Long) As Variant #Else Private Declare Function rtcCallByName Lib "VBE6.DLL" ( _ ByVal Object As Object, _ ByVal ProcName As Long, _ ByVal CallType As VbCallType, _ ByRef args() As Any, _ Optional ByVal lcid As Long) As Variant #End If
Public Function CallWithArgs( _
ByRef Object As Object, _
ByRef ProcName As String, _
CallType As VbCallType, _
ByRef Args() As Variant _
)
CallWithArgs = rtcCallByName(Object, ProcName, CallType, Args)
End Function