ParamArray Sorting question

neonangel

Board Regular
Joined
Jul 5, 2004
Messages
99
Hi All,

Apologies in advance for the code dropping I'm about to do, but it should make testing easier. In VBA I have the following procedure to test sorting procedures:

Code:
Sub TestSort()
Dim Names(1 To 10) As String
Dim Order(1 To 10) As Integer
Dim RndNos(1 To 10) As Single
Dim i As Integer

    Randomize
    For i = 1 To 10
        Order(i) = i
        RndNos(i) = Rnd()
    Next i
    Names(1) = "Alice": Names(2) = "Bob": Names(3) = "Cathy"
    Names(4) = "Doofus": Names(5) = "Ed": Names(6) = "Fergy"
    Names(7) = "Grant": Names(8) = "Helena": Names(9) = "Ira": Names(10) = "Jacquie"
    Call BubbleSortWrapper(True, RndNos, Names, Order)
    Debug.Print vbCrLf & "Random Numbers Sorted"
    For i = 1 To 10
        Debug.Print RndNos(i)
    Next i
    Call BubbleSortWrapper(True, Order, Names, RndNos)
    Debug.Print vbCrLf & "Names Sorted"
    For i = 1 To 10
        Debug.Print Names(i)
    Next i
End Sub

I am using this to call the following procedure, which in turn calls a bubble sort procedure:

Code:
Sub BubbleSortWrapper(Ascending As Boolean, ParamArray Arr() As Variant)
Dim tmpArr As Variant

    tmpArr = Arr
    Call BubbleSort(Ascending, tmpArr)
    Arr = tmpArr
End Sub

Code:
Sub BubbleSort(Ascending As Boolean, Arr As Variant)
' Sorts arrays Arr based on Arr1 in Asc order using the bubble sort algorithm
Dim tmpArr() As Variant
Dim i As Integer, j As Integer, k As Integer

    On Error Resume Next ' Handle optional arrays
    ReDim tmpArr(0 To UBound(Arr)) ' One temporary storage element for each array
    For i = LBound(Arr(0)) To UBound(Arr(0))
        For j = 1 To UBound(Arr(0)) - i
            If IIf(Ascending, Arr(0)(j + 1) < Arr(0)(j), Arr(0)(j + 1) > Arr(0)(j)) Then
                For k = LBound(Arr) To UBound(Arr)
                    tmpArr(k) = Arr(k)(j + 1)
                    Arr(k)(j + 1) = Arr(k)(j)
                    Arr(k)(j) = tmpArr(k)
                Next k
            End If
        Next j
    Next i
End Sub

The above chain of events does not give the correct output, however using the BubbleSort procedure as:
Code:
Sub BubbleSort(Ascending As Boolean, ParamArray Arr() As Variant)
does. Which means I am enquiring as to how one passes a ParamArray for modification of the arrays.

I found a post online saying I could redefine my BubbleSort procedure with the variant, as above, and it also suggested I could simply use Call BubbleSort(Ascending, Arr) although this gave me an error: "Invalid ParamArray use" which on investigating the help file indicates I should "Assign the ParamArray parameter to a Variant, and then pass the variant" which I how I obtained the above code.

? statements in the Intermediate window indicate that the sorting procedure works and that, right before exiting the BubbleSortWrapper procedure, the ParamArray Arr has the correct values sorted, however immediately after exiting the sorting procedure the values are unchanged, leading me to believe this is some issue with ByRef ByVal.

Solution?
 

Excel Facts

Which Excel functions can ignore hidden rows?
The SUBTOTAL and AGGREGATE functions ignore hidden rows. AGGREGATE can also exclude error cells and more.
neonangel said:
*snip*

? statements in the Intermediate window indicate that the sorting procedure works and that, right before exiting the BubbleSortWrapper procedure, the ParamArray Arr has the correct values sorted, however immediately after exiting the sorting procedure the values are unchanged, leading me to believe this is some issue with ByRef ByVal.

Solution?

Have you tried passing the array ByRef? I've always passed arrays by reference (though that was in other programming languages). Unless you have gobs and gobs of memory available, and you don't care about memory usage or speed, I was taught to always always pass arrays by reference.
 
Upvote 0
From the help file:

ParamArray Optional. Used only as the last argument in arglist to indicate that the final argument is an Optional array of Variant elements. The ParamArray keyword allows you to provide an arbitrary number of arguments. ParamArray can't be used with ByVal, ByRef, or Optional.
 
Upvote 0
"You use ParamArray (only as the last argument to a procedure) to indicate that the procedure may take an unspecified number of arguments"

lol, I should probably have made myself clear at the outset..

Objective: A sorting procedure that
* can accept a variable number of one dimensional arrays
* sorts them all based on the first array
* uses bubblesort for < 25 elements and quicksort for > 25 elements

I have the individual sorting procedures working, but I'm looking to write the cover function that will:
a) redirect to the appropriate sort type based on the number of elements
b) prevent me from having to specify the Lower and Upper for the first call of the quicksort, which should be LBound(Arr(1)) and UBound(Arr(1)) by default.

You can't have optional parameters when using a ParamArray to allow a variable number of arrays, so I was using the cover function to add this information into the quicksort call.

Regards,

Alex
 
Upvote 0
Hello Alex,

Pass the array as a Variant. And you need to restack the array or create a new, sorted array from the function return, yes-no? E.g.,

<font face=Courier New><SPAN style="color:darkblue">Function</SPAN> arrSort(<SPAN style="color:darkblue">ByVal</SPAN> myArr <SPAN style="color:darkblue">As</SPAN> <SPAN style="color:darkblue">Variant</SPAN>, _
    <SPAN style="color:darkblue">Optional</SPAN> <SPAN style="color:darkblue">ByVal</SPAN> Descend <SPAN style="color:darkblue">As</SPAN> <SPAN style="color:darkblue">Boolean</SPAN>) <SPAN style="color:darkblue">As</SPAN> <SPAN style="color:darkblue">Variant</SPAN>
<SPAN style="color:darkblue">Dim</SPAN> i <SPAN style="color:darkblue">As</SPAN> <SPAN style="color:darkblue">Long</SPAN>, j <SPAN style="color:darkblue">As</SPAN> <SPAN style="color:darkblue">Long</SPAN>, LwVl <SPAN style="color:darkblue">As</SPAN> <SPAN style="color:darkblue">Long</SPAN>
<SPAN style="color:darkblue">For</SPAN> i = <SPAN style="color:darkblue">LBound</SPAN>(myArr) <SPAN style="color:darkblue">To</SPAN> <SPAN style="color:darkblue">UBound</SPAN>(myArr)
    LwVl = myArr(i)
    <SPAN style="color:darkblue">For</SPAN> j = i + 1 <SPAN style="color:darkblue">To</SPAN> <SPAN style="color:darkblue">UBound</SPAN>(myArr)
        <SPAN style="color:darkblue">If</SPAN> Choose(-CInt(Descend) + 1, _
            myArr(j) < LwVl, myArr(j) > LwVl) <SPAN style="color:darkblue">Then</SPAN>
              LwVl = myArr(j)
              myArr(j) = myArr(i)
              myArr(i) = LwVl
        <SPAN style="color:darkblue">End</SPAN> <SPAN style="color:darkblue">If</SPAN>
    <SPAN style="color:darkblue">Next</SPAN>
<SPAN style="color:darkblue">Next</SPAN>
arrSort = myArr
<SPAN style="color:darkblue">End</SPAN> <SPAN style="color:darkblue">Function</SPAN>

<SPAN style="color:darkblue">Sub</SPAN> tester()
<SPAN style="color:darkblue">Dim</SPAN> myArr <SPAN style="color:darkblue">As</SPAN> <SPAN style="color:darkblue">Variant</SPAN>, i <SPAN style="color:darkblue">As</SPAN> <SPAN style="color:darkblue">Long</SPAN>
<SPAN style="color:darkblue">Let</SPAN> myArr = [{5,22,4,1}]
<SPAN style="color:darkblue">Let</SPAN> myArr = arrSort(myArr)
<SPAN style="color:darkblue">For</SPAN> i = <SPAN style="color:darkblue">LBound</SPAN>(myArr) <SPAN style="color:darkblue">To</SPAN> <SPAN style="color:darkblue">UBound</SPAN>(myArr)
    <SPAN style="color:darkblue">Debug</SPAN>.<SPAN style="color:darkblue">Print</SPAN> myArr(i)
<SPAN style="color:darkblue">Next</SPAN>
<SPAN style="color:darkblue">End</SPAN> <SPAN style="color:darkblue">Sub</SPAN></FONT>
 
Upvote 0
"Pass the array as a Variant. And you need to restack the array or create a new, sorted array from the function return, yes-no?"

Are you saying I would need to use something like:
Code:
Function BubbleSortWrapper(Ascending As Boolean, ParamArray Arr() As Variant) As Variant
    BubbleSortWrapper = Arr
    Call BubbleSort(Ascending, BubbleSortWrapper)
End Function
and then in my test code:
Code:
Dim Temp as Variant

Temp = BubbleSortWrapper(True, Order, Names, RndNos)
Order = Temp(0)
Names = Temp(1)
RndNos = Temp(2)

??

As I say, when I use:
Code:
Sub BubbleSort(Ascending As Boolean, ParamArray Arr() As Variant)
and call BubbleSort with
Code:
Call BubbleSort(True, Order, Names, RndNos)
this thing works perfectly. It is only when I intermediate the process with a function to redirect my ParamArray to another function that I encounter problems?
 
Upvote 0
Nope, do it the way I did it. Not:

ParamArray Arr() As Variant

Try:

byVal Arr As Variant

The following:

Dim Temp as Variant
Temp = BubbleSortWrapper(True, Order, Names, RndNos)

Is affirmative. ;)
 
Upvote 0

Forum statistics

Threads
1,216,999
Messages
6,133,948
Members
449,849
Latest member
nnnyyy

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