Results 1 to 17 of 17

Thread: [RESOLVED] Passing a ParamArray from one routine to another

  1. #1

    Thread Starter
    Fanatic Member
    Join Date
    Aug 2011
    Location
    Palm Coast, FL
    Posts
    628

    Resolved [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

  2. #2
    PowerPoster
    Join Date
    Nov 2017
    Posts
    3,341

    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.

  3. #3
    Hyperactive Member
    Join Date
    Mar 2017
    Posts
    500

    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

  4. #4
    Hyperactive Member
    Join Date
    Aug 2017
    Posts
    380

    Re: Passing a ParamArray from one routine to another

    [VB6] VB6.tlb - Passing a ParamArray without Copying

    Quote Originally Posted by DEXWERX View Post
    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...

  5. #5
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,384

    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

  6. #6

    Thread Starter
    Fanatic Member
    Join Date
    Aug 2011
    Location
    Palm Coast, FL
    Posts
    628

    Re: Passing a ParamArray from one routine to another

    Thanks all for your excellent and varied solutions.

  7. #7
    Hyperactive Member
    Join Date
    Jan 2018
    Posts
    289

    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.

  8. #8
    PowerPoster
    Join Date
    Jan 2020
    Posts
    4,262

    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.

  9. #9
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    8,703

    Re: Passing a ParamArray from one routine to another

    Quote Originally Posted by Schmidt View Post
    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.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  10. #10
    PowerPoster
    Join Date
    Jan 2020
    Posts
    4,262

    Re: [RESOLVED] Passing a ParamArray from one routine to another

    but the sencode function:ProcTwop need same types ,how do it?

  11. #11
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    10,518

    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.

  12. #12
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    10,518

    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.

  13. #13
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    10,518

    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.

  14. #14
    PowerPoster
    Join Date
    Jan 2020
    Posts
    4,262

    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.

  15. #15
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    10,518

    Re: [RESOLVED] Passing a ParamArray from one routine to another

    Quote Originally Posted by xiaoyao View Post
    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.

  16. #16
    PowerPoster
    Join Date
    Nov 2017
    Posts
    3,341

    Re: [RESOLVED] Passing a ParamArray from one routine to another

    Quote Originally Posted by Elroy View Post
    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.

  17. #17
    Addicted Member
    Join Date
    Mar 2009
    Posts
    248

    Re: Passing a ParamArray from one routine to another

    Offtopic:
    Quote Originally Posted by Ordinary Guy View Post
    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
    Quote Originally Posted by Ordinary Guy View Post
    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
  •  



Click Here to Expand Forum to Full Width