passing a ParamArray to another sub that accepts a ParamArray

ffffloyd

New Member
Joined
Feb 10, 2018
Messages
5
I have a number of subroutines that accept a ParamArray for an indeterminate number of parameters, viz:
Code:
Sub CheckList(ParamArray vList())
'
' checks stuff
'
End Sub


Sub PrintList(sMessage as String, ParamArray vList())
'
' prints stuff
'
    CheckList vList
    CheckList vList()
    CheckList Array(vList())
End Sub

It doesn't seem to matter how I try to pass the array from PrintList to CheckList, I always seem to end up with something other than the array I started with. It starts off as an array of variants and appears to become a one element array of (an array of variants). That is, in CheckList, vList(0) contains the original array that was passed to PrintList.

This can go more than one level deep. In actuality, PrintList may be called directly or it may be called by another subroutine that has a ParamArray vList(). When that happens, CheckList receives a one element array of (a one element array of (an array of variants)).

It seems messy to have to write code to potentially unpack the array at each level. What is the way of passing a ParamArray to a ParamArray and ending up with exactly the same ParamArray?

Cross-posted here:
https://www.excelforum.com/excel-pr...to-another-sub-that-accepts-a-paramarray.html
 

Excel Facts

Square and cube roots
The =SQRT(25) is a square root. For a cube root, use =125^(1/3). For a fourth root, use =625^(1/4).
Hi this is an example:

Code:
Sub Test()
Dim vList As Variant
    
    CheckList "abc", "3", "x"

End Sub


Sub CheckList(ParamArray vList())
'
' checks stuff
'

MsgBox "All parameters: " & Join(vList, ", ")
MsgBox "Second parameter: " & vList(1)

End Sub
 
Upvote 0
Thanks PGC but I am afraid you haven't understood the question.

Instead of calling CheckList, call PrintList.

PrintList then attempts to call CheckList passing the ParamArray it received as a parameter to CheckList's ParamArray. Thus:
Code:
Sub CheckList(ParamArray vList())
'
' checks stuff
'
End Sub


Sub PrintList(sMessage as String, ParamArray vList())
'
' prints stuff
'
    CheckList vList
    CheckList vList()
    CheckList Array(vList())
End Sub

PrintList "Try this", "abc", 3, "x"

PrintList would receive sMessage = "Try This" and vList = ("abc", 3, "x")

But, no matter which of those calls to CheckList I try, CheckList never receives vList = ("abc", 3, "x"). The best I can tell from the Watch Window, under at least some of those conditions, CheckList receives vList = (("abc", 3, "x"), Unknown). In other words, vList(0) is the original ParamList in its entirety and vList(1) is... I don't know.

Sure, I could unpack the array from vList(0) in CheckList but that seems terribly inefficient, especially when (in the actual program rather than a simple example) there are calls to calls to calls and some of them may be recursive. There must surely be a way of receiving a ParamList (as for PrintList) and then passing that ParamList to another subroutine's ParamList (as for CheckList) and receiving it in the same form. That is the syntax I am asking if anyone knows.
 
Upvote 0
Not sure if this is what you want, but it's simpler and seems to work.

Code:
Sub Main()
    PrintList "Try this", "abc", 3, "x"
End Sub

Sub CheckList(vList As String)
    Dim myArr As Variant
    myArr = Split(vList)
    MsgBox myArr(0)
    MsgBox myArr(1)
End Sub

Sub PrintList(sMessage As String, ParamArray vList())
'
' prints stuff
'
    CheckList Join(vList())
End Sub

M.
 
Upvote 0
Thanks Marcelo, but I lose the type information then. Everything is transformed to a string. The types are an implicit part of what I am checking.
 
Upvote 0
There must surely be a way of receiving a ParamList (as for PrintList) and then passing that ParamList to another subroutine's ParamList (as for CheckList) and receiving it in the same form. That is the syntax I am asking if anyone knows.

Hi

Sorry, i think I understand now what you mean.

In my opinion: no, there is no such syntax.

If you really want/need it, a workaround is to check the number of parameters and choose the right syntax.

Notice that

- it's not pretty to look at,
- ... but not terribly inefficient since it's just an test.

Ex. CheckList receives a ParamArray and passes it on to CheckList1:

Code:
Sub Test()
    
    CheckList "abc", "3", "x"
    CheckList "abc"
    CheckList "abc", "3"

End Sub


Sub CheckList(ParamArray vL())

Select Case UBound(vL)

    Case 0: CheckList1 vL(0)
    Case 1: CheckList1 vL(0), vL(1)
    Case 2: CheckList1 vL(0), vL(1), vL(2)

End Select

End Sub

Sub CheckList1(ParamArray vL())

MsgBox "All parameters: " & Join(vL, ", ")

End Sub

Short of this, the only other way I can think of would be to create a new module in runtime, add to it the code to execute the sub, execute it, and then remove the module. Now this could be terribly inefficient.
 
Upvote 0
I have been experimenting since, and have had some success making that last parameter an Optional Variant. I then pass it an Array and it becomes an Array of Variants, just like ParamArray would be. The advantage then though is that all the elements are immediately accessible as array elements, not all bunched up together in element zero. It still requires some wizardry when going to multiple levels, and I am working on a Pack() function for just that purpose. I haven't completed it yet, but I hope to post it when I do so that others may benefit.
 
Upvote 0
This is one way to do it. Note the two ways that CheckList can be passed arguments

Code:
Sub CheckList(ParamArray vList() As Variant)
    Dim myElements As Variant
    
    If TypeName(vList(0)) Like "*()" Then
        myElements = vList(0)
    Else
        myElements = vList
    End If
    
    'do stuff to myElements
    
End Sub


Sub outerRoutine(ParamArray vStuff() As Variant)
    ' do stuff
    
    CheckList vStuff
    
    'do other
End Sub


Sub otherRoutine()
    ' something
    
    CheckList "a", "b", "c"
    
    ' else
End Sub
 
Upvote 0
Now you lost me.

If it's OK to change the syntax you can pass the ParamArray directly as an array.

The parameters will not be "all bunched up together in element zero".

You don't lose the types of the elements, which is what I understood you want to keep.

Code:
Sub Test()
    
    CheckList "abc", 3, False

End Sub


Sub CheckList(ParamArray vL())
Dim v As Variant
v = vL

    CheckList1 v

End Sub

Sub CheckList1(vL As Variant)
Dim j As Long

For j = 0 To UBound(vL)
    MsgBox "Parameter " & j + 1 & ": " & TypeName(vL(j))
Next j

End Sub
 
Upvote 0

Forum statistics

Threads
1,215,427
Messages
6,124,831
Members
449,190
Latest member
rscraig11

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top