-
Dec 31st, 2019, 03:09 PM
#1
Thread Starter
Fanatic Member
[RESOLVED] Passing a ParamArray from one routine to another
In my code I'm passing in a ParamArray to a routine. I'm then trying to pass the ParamArray to a second routine but I'm not able to access the array elements in this second routine. it appears that the ParamArray is not properly passed to the second routine? When I inspect the ParamArray from within the second routine, the values are not in the array.
How do I pass a ParamArray to multiple routines?
Code:
Private Sub CallerRoutine()
Call ProcOne(1,2,3)
End Sub
Private Sub ProcOne (ParamArray varValues() as Variant)
Call ProcTwo(varValues)
End Sub
Private Sub ProcTwo (ParamArray varValues() as Variant)
Dim intVar as integer
intVar = varValues(0) <-- This fails with a Type Mismatch error
End Sub
-
Dec 31st, 2019, 03:21 PM
#2
Re: Passing a ParamArray from one routine to another
For the record (not that it helps much), but this works:
Code:
Call ProcTwo(varValues(0), varValues(1), varValues(2))
Not sure of all the nuances with usage of a ParamArry, but perhaps things need to be passed "itemized", if you will.
-
Dec 31st, 2019, 06:16 PM
#3
Hyperactive Member
Re: Passing a ParamArray from one routine to another
This is one way to do it
Code:
Private Sub CallerRoutine()
ProcOne 1, 2, 3
End Sub
Private Sub ProcOne(ParamArray varValues() As Variant)
ProcTwo Array(varValues)(0)
End Sub
Private Sub ProcTwo(varValues As Variant)
Dim intVar0 As Variant, intVar1 As Variant, intVar2 As Variant
intVar0 = varValues(0) ' = 1
intVar1 = varValues(1) ' = 2
intVar2 = varValues(2) ' = 3
End Sub
Note: Avoid using the Call statement; it is outdated and not necessary
Also, don't convert Variant to Integer; just use the Variant variable
-
Jan 1st, 2020, 02:13 AM
#4
Re: Passing a ParamArray from one routine to another
[VB6] VB6.tlb - Passing a ParamArray without Copying
Originally Posted by DEXWERX
The Issue: How do you access a ParamArray, and pass it to another function,
without copying it.
The Answer: Pointer magic. ParamArrays are really just a
Variant Array - managed by the runtime. For whatever reason though - the
runtime / ide doesn't allow you to get at it's address easily, or even pass it
to another function without making a copy
Read more...
-
Jan 1st, 2020, 05:58 AM
#5
Re: Passing a ParamArray from one routine to another
If the amount of "expected max-Params" is reasonably low (below 16 or so),
then one of the best performing ways is, to use a "Select-based Call-cascade"...
(which will also not break the ByRef-Backtransport of changed Params - without resorting to Pointer-Hacks).
Code:
Private Sub Form_Load()
CallerRoutine
End Sub
Private Sub CallerRoutine()
Dim p1 As Integer: p1 = 1
Dim p2 As Integer: p2 = 2
Dim p3 As Integer: p3 = 3
ProcOne p1, p2, p3
Debug.Print p1; p2; p3 'should print 10, 20, 30
End Sub
Private Sub ProcOne(ParamArray P() As Variant)
Select Case UBound(P) + 1 'a ByRef-capable call-cascade for up to 5 arguments
Case 0: ProcTwo
Case 1: ProcTwo P(0)
Case 2: ProcTwo P(0), P(1)
Case 3: ProcTwo P(0), P(1), P(2)
Case 4: ProcTwo P(0), P(1), P(2), P(3)
Case 5: ProcTwo P(0), P(1), P(2), P(3), P(4)
End Select
End Sub
Private Sub ProcTwo(ParamArray P() As Variant)
Dim i As Long
For i = 0 To UBound(P)
P(i) = P(i) * 10 'change the input, to test whether ByRef-backtransport works
Next
End Sub
And yes, such a cascade looks "unwieldy and big" - but it's not needed all that often, it performs well, -
and is relatively fast to "generate" in your Code-Editor, when you start creating the last line (with the most params),
then validating it for any index-errors - followed by copy&pasting it "upwards" - followed by shortening the param-list.
HTH
Olaf
-
Jan 1st, 2020, 09:53 AM
#6
Thread Starter
Fanatic Member
Re: Passing a ParamArray from one routine to another
Thanks all for your excellent and varied solutions.
-
Jan 2nd, 2020, 06:18 PM
#7
Hyperactive Member
Re: [RESOLVED] Passing a ParamArray from one routine to another
Or you can do it from the other side - if you know that ProcTwo might be called through multiple layers:
Private Sub ProcTwo(ParamArray varValues() As Variant)
Dim intVar As Integer
Dim varUnwoundParam As Variant
varUnwoundParam = varValues
If IsArray(varUnwoundParam) And Not IsMissing(varUnwoundParam) Then
If IsArray(varUnwoundParam(0)) Then varUnwoundParam = varUnwoundParam(0)
End If
intVar = varUnwoundParam(0)
End Sub
That would break ByRef-ness, and if you want to cover all of the bases, the unwinding should be in a Do While loop, not just a single if/then.
-
Apr 11th, 2023, 06:39 AM
#8
Re: [RESOLVED] Passing a ParamArray from one routine to another
how to write code for any type args,and change arg
Compilation error:
ByRef parameter type mismatch
ProcOne = Add(P(0), P(1))
Code:
Private Sub Form_Load()
CallerRoutine
End Sub
Function Add(a As Long, b As Long)
Add = a + b
a = a + 100
End Function
Private Sub CallerRoutine()
Dim a As Long, b As Long
a = 11
b = 22
Dim c As Long
c = ProcOne(a, b)
Debug.Print a; b; c
End Sub
Private Function ProcOne(ParamArray P() As Variant) As Long
Select Case UBound(P) + 1 'a ByRef-capable call-cascade for up to 5 arguments
Case 0:
Case 1:
Case 2
Dim v As Long
v = P(0)
ProcOne = Add(v, P(1) + 0)
P(0) = v
'how to write code for any type args,and change arg?
'ProcOne = Add(P(0) + 0, P(1) + 0)
End Select
End Function
Private Function DoAdd(ParamArray P() As Variant)
Dim i As Long
DoAdd = Add(P(0), P(1))
End Function
Last edited by xiaoyao; Apr 13th, 2023 at 11:27 PM.
-
Apr 12th, 2023, 12:09 AM
#9
Re: Passing a ParamArray from one routine to another
Originally Posted by Schmidt
and is relatively fast to "generate" in your Code-Editor, when you start creating the last line (with the most params),
then validating it for any index-errors - followed by copy&pasting it "upwards" - followed by shortening the param-list.
Or you could ask AI to do it for you in no time. ChatGPT did this for me in about 15 seconds:-
Code:
Private Sub ProcOne(ParamArray P() As Variant)
Select Case UBound(P) + 1 'a ByRef-capable call-cascade for up to 16 arguments
Case 0: ProcTwo
Case 1: ProcTwo P(0)
Case 2: ProcTwo P(0), P(1)
Case 3: ProcTwo P(0), P(1), P(2)
Case 4: ProcTwo P(0), P(1), P(2), P(3)
Case 5: ProcTwo P(0), P(1), P(2), P(3), P(4)
Case 6: ProcTwo P(0), P(1), P(2), P(3), P(4), P(5)
Case 7: ProcTwo P(0), P(1), P(2), P(3), P(4), P(5), P(6)
Case 8: ProcTwo P(0), P(1), P(2), P(3), P(4), P(5), P(6), P(7)
Case 9: ProcTwo P(0), P(1), P(2), P(3), P(4), P(5), P(6), P(7), P(8)
Case 10: ProcTwo P(0), P(1), P(2), P(3), P(4), P(5), P(6), P(7), P(8), P(9)
Case 11: ProcTwo P(0), P(1), P(2), P(3), P(4), P(5), P(6), P(7), P(8), P(9), P(10)
Case 12: ProcTwo P(0), P(1), P(2), P(3), P(4), P(5), P(6), P(7), P(8), P(9), P(10), P(11)
Case 13: ProcTwo P(0), P(1), P(2), P(3), P(4), P(5), P(6), P(7), P(8), P(9), P(10), P(11), P(12)
Case 14: ProcTwo P(0), P(1), P(2), P(3), P(4), P(5), P(6), P(7), P(8), P(9), P(10), P(11), P(12), P(13)
Case 15: ProcTwo P(0), P(1), P(2), P(3), P(4), P(5), P(6), P(7), P(8), P(9), P(10), P(11), P(12), P(13), P(14)
Case 16: ProcTwo P(0), P(1), P(2), P(3), P(4), P(5), P(6), P(7), P(8), P(9), P(10), P(11), P(12), P(13), P(14), P(15)
End Select
End Sub
Query:-
Private Sub ProcOne(ParamArray P() As Variant)
Select Case UBound(P) + 1 'a ByRef-capable call-cascade for up to 5 arguments
Case 0: ProcTwo
Case 1: ProcTwo P(0)
Case 2: ProcTwo P(0), P(1)
Case 3: ProcTwo P(0), P(1), P(2)
Case 4: ProcTwo P(0), P(1), P(2), P(3)
Case 5: ProcTwo P(0), P(1), P(2), P(3), P(4)
End Select
End Sub
The text above is VB6 code. I want you to extend it from 5 to 16 parameters.
I'm enjoying living in a world of AI
EDIT:
I just noticed it even changed the comment to reflect the change. I didn't even have to tell it to do that. God I love this AI!
Last edited by Niya; Apr 12th, 2023 at 12:19 AM.
-
Apr 13th, 2023, 11:23 PM
#10
Re: [RESOLVED] Passing a ParamArray from one routine to another
but the sencode function:ProcTwop need same types ,how do it?
-
Apr 13th, 2023, 11:40 PM
#11
Re: [RESOLVED] Passing a ParamArray from one routine to another
I'm not sure why nobody correctly answered your question.
Here's the code you posted with one added line and additional comments. I also change the entry to Form_Load for easier execution.
Code:
Option Explicit
Private Sub Form_Load()
Call ProcOne(1, 2, 3) ' Passes the 1, 2, 3 as an array.
End Sub
Private Sub ProcOne(ParamArray varValues() As Variant)
' The varValues comes in as a 1, 2, 3 variant array.
Call ProcTwo(varValues) ' This places varValues() as the first item in a NEW array.
End Sub
Private Sub ProcTwo(ParamArray varValues() As Variant)
' Now varValues is a NEW variant array with only one item.
' That one item is the original varValues() array.
' Proof:
Debug.Print LBound(varValues), UBound(varValues)
' The above reports 0, 0 which is one item in the array.
' Again, it's the original varValues() array from above.
Dim intVar As Integer
intVar = varValues(0) ' So OF COURSE this will error.
' You can't put a variant array into an integer!!!
End Sub
Now, you've been given some options around this in the above posts. But, if you want to use your existing logic, you can just do the following:
Code:
Option Explicit
Private Sub Form_Load()
Call ProcOne(1, 2, 3)
End Sub
Private Sub ProcOne(ParamArray varValues() As Variant)
Call ProcTwo(varValues)
End Sub
Private Sub ProcTwo(ParamArray varValues() As Variant)
Dim intVar As Integer
intVar = varValues(0)(0)
Debug.Print intVar ' Reports: 1
Debug.Print varValues(0)(1) ' Reports: 2
Debug.Print varValues(0)(2) ' Reports: 3
End Sub
So, all seems copacetic to me, and makes perfect sense.
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
-
Apr 13th, 2023, 11:46 PM
#12
Re: [RESOLVED] Passing a ParamArray from one routine to another
This also works:
Code:
Option Explicit
Private Sub Form_Load()
Call ProcOne(1, 2, 3)
End Sub
Private Sub ProcOne(ParamArray varValues() As Variant)
Call ProcTwo(varValues)
End Sub
Private Sub ProcTwo(ParamArray varValues() As Variant)
Call ProcThree(varValues(0))
End Sub
Private Sub ProcThree(ParamArray varValues() As Variant)
Call ProcFour(varValues(0))
End Sub
Private Sub ProcFour(ParamArray varValues() As Variant)
Debug.Print varValues(0)(0) ' Reports: 1
Debug.Print varValues(0)(1) ' Reports: 2
Debug.Print varValues(0)(2) ' Reports: 3
End Sub
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
-
Apr 13th, 2023, 11:51 PM
#13
Re: [RESOLVED] Passing a ParamArray from one routine to another
And this works as well:
Code:
Option Explicit
Private Sub Form_Load()
Call ProcOne(1, 2, 3)
Call ProcTwo(1, 2, 3) ' Call ProcTwo directly.
End Sub
Private Sub ProcOne(ParamArray varValues() As Variant)
Call ProcTwo(varValues)
End Sub
Private Sub ProcTwo(ParamArray varValues() As Variant)
Dim varNewValues() As Variant
If IsArray(varValues(0)) Then
varNewValues = varValues(0)
Else
varNewValues = varValues
End If
Debug.Print varNewValues(0) ' Reports: 1
Debug.Print varNewValues(1) ' Reports: 2
Debug.Print varNewValues(2) ' Reports: 3
End Sub
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
-
Apr 14th, 2023, 12:10 AM
#14
Re: [RESOLVED] Passing a ParamArray from one routine to another
If the objective function has multiple data types and needs to modify several values in the parameters, it may become more complex.
The main purpose is to use anycall for calling based on the function address. The number of parameters is not fixed, and the target function being called is not an existing function in the module. For example, for 5 parameters, 1-2 parameters still need to return values.
-
Apr 14th, 2023, 08:08 AM
#15
Re: [RESOLVED] Passing a ParamArray from one routine to another
Originally Posted by xiaoyao
If the objective function has multiple data types and needs to modify several values in the parameters, it may become more complex.
Actually, nothing in posts #11, #12, nor #13 is dependent on the data types, so I'm not sure what you're trying to say. Regarding the rest of your post, that's precisely why I posted #13 ... and again, nothing was dependent on the parameter data type.
The only downside to post #13, is that is is going to make a copy of the data. However, with the limit on the number of parameters in ParamArray, I don't see this as a problem.
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
-
Apr 14th, 2023, 08:42 AM
#16
Re: [RESOLVED] Passing a ParamArray from one routine to another
Originally Posted by Elroy
Actually, nothing in posts #11, #12, nor #13 is dependent on the data types, so I'm not sure what you're trying to say. Regarding the rest of your post, that's precisely why I posted #13 ... and again, nothing was dependent on the parameter data type.
The only downside to post #13, is that is is going to make a copy of the data. However, with the limit on the number of parameters in ParamArray, I don't see this as a problem.
You should just ignore them. I'm convinced they are akin to ChatGPT, if ChatGPT had a traumatic AI injury.
-
May 31st, 2023, 01:24 PM
#17
Addicted Member
Re: Passing a ParamArray from one routine to another
Offtopic:
Originally Posted by Ordinary Guy
Note: Avoid using the Call statement; it is outdated and not necessary
That's your opinion, as in VB6 it certainly isn't outdated. Because something is not necessary doesn't mean you shouldn't use it, especially in regard to readability. But readability is in the eye of the beholder ofcourse.
Personally I think not using the Call doesn't improve the readability. And I think it is very ugly not using because when using functions you'll have to use the parentheses anyway, so IMHO it's a mess if you sometimes use it and sometimes you dont'.
I would agree with you if you could also use the parentheses without using Call, but VB6 isn't VB.Net
Code:
'Ugly code
Private Sub CallerRoutine()
Dim i As Integer
ProcOne 1, 2, 3
i = FunctionOne(1, 2, 3)
End Sub
'Nicer code
Private Sub CallerRoutine()
Dim i As integer
Call ProcOne(1, 2, 3)
i = FunctionOne(1, 2, 3)
End Sub
'Not possible in VB6
Private Sub CallerRoutine()
Dim i As Integer
ProcOne(1, 2, 3)
i = FunctionOne(1, 2, 3)
End Sub
Originally Posted by Ordinary Guy
Also, don't convert Variant to Integer; just use the Variant variable
Depends ofcourse on what you are gonna do with it in the rest of the function.
If you do a lot with the variable in the rest of the function it certainly is better to convert it to the value/variable instead of using it as the variant as in example, because of 2 things:
1. variants are slow, so when needed a lot of times in the function, then it's better to convert it to the original type.
2. it is an array entry, so it will be slower because of each time you need to use it, it will have to look it up, which is another hit on performance.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|