Does anyone know how to sort a collection in VBA?
- 
                    4First of all you should define what is in the collection and how you expect it to be sorted. Otherwise it is all just speculations. – Daniel Dušek Feb 07 '17 at 12:34
12 Answers
Late to the game... here's an implementation of the MergeSort algorithm in VBA for both Arrays and Collections. I tested the performance of this implementation against the BubbleSort implementation in the accepted answer using randomly generated strings. The chart below summarizes the results, i.e. that you should not use BubbleSort to sort a VBA collection.
You can download the source code from my GitHub Repository or just copy/paste the source code below into the appropriate modules.
For a collection col, just call Collections.sort col. 
Collections module
'Sorts the given collection using the Arrays.MergeSort algorithm.
' O(n log(n)) time
' O(n) space
Public Sub sort(col As collection, Optional ByRef c As IVariantComparator)
    Dim a() As Variant
    Dim b() As Variant
    a = Collections.ToArray(col)
    Arrays.sort a(), c
    Set col = Collections.FromArray(a())
End Sub
'Returns an array which exactly matches this collection.
' Note: This function is not safe for concurrent modification.
Public Function ToArray(col As collection) As Variant
    Dim a() As Variant
    ReDim a(0 To col.count)
    Dim i As Long
    For i = 0 To col.count - 1
        a(i) = col(i + 1)
    Next i
    ToArray = a()
End Function
'Returns a Collection which exactly matches the given Array
' Note: This function is not safe for concurrent modification.
Public Function FromArray(a() As Variant) As collection
    Dim col As collection
    Set col = New collection
    Dim element As Variant
    For Each element In a
        col.Add element
    Next element
    Set FromArray = col
End Function
Arrays module
    Option Compare Text
Option Explicit
Option Base 0
Private Const INSERTIONSORT_THRESHOLD As Long = 7
'Sorts the array using the MergeSort algorithm (follows the Java legacyMergesort algorithm
'O(n*log(n)) time; O(n) space
Public Sub sort(ByRef a() As Variant, Optional ByRef c As IVariantComparator)
    If c Is Nothing Then
        MergeSort copyOf(a), a, 0, length(a), 0, Factory.newNumericComparator
    Else
        MergeSort copyOf(a), a, 0, length(a), 0, c
    End If
End Sub
Private Sub MergeSort(ByRef src() As Variant, ByRef dest() As Variant, low As Long, high As Long, off As Long, ByRef c As IVariantComparator)
    Dim length As Long
    Dim destLow As Long
    Dim destHigh As Long
    Dim mid As Long
    Dim i As Long
    Dim p As Long
    Dim q As Long
    length = high - low
    ' insertion sort on small arrays
    If length < INSERTIONSORT_THRESHOLD Then
        i = low
        Dim j As Long
        Do While i < high
            j = i
            Do While True
                If (j <= low) Then
                    Exit Do
                End If
                If (c.compare(dest(j - 1), dest(j)) <= 0) Then
                    Exit Do
                End If
                swap dest, j, j - 1
                j = j - 1 'decrement j
            Loop
            i = i + 1 'increment i
        Loop
        Exit Sub
    End If
    'recursively sort halves of dest into src
    destLow = low
    destHigh = high
    low = low + off
    high = high + off
    mid = (low + high) / 2
    MergeSort dest, src, low, mid, -off, c
    MergeSort dest, src, mid, high, -off, c
    'if list is already sorted, we're done
    If c.compare(src(mid - 1), src(mid)) <= 0 Then
        copy src, low, dest, destLow, length - 1
        Exit Sub
    End If
    'merge sorted halves into dest
    i = destLow
    p = low
    q = mid
    Do While i < destHigh
        If (q >= high) Then
           dest(i) = src(p)
           p = p + 1
        Else
            'Otherwise, check if p<mid AND src(p) preceeds scr(q)
            'See description of following idom at: https://stackoverflow.com/a/3245183/3795219
            Select Case True
               Case p >= mid, c.compare(src(p), src(q)) > 0
                   dest(i) = src(q)
                   q = q + 1
               Case Else
                   dest(i) = src(p)
                   p = p + 1
            End Select
        End If
        i = i + 1
    Loop
End Sub
IVariantComparator class
Option Explicit
'The IVariantComparator provides a method, compare, that imposes a total ordering over a collection _
of variants. A class that implements IVariantComparator, called a Comparator, can be passed to the _
Arrays.sort and Collections.sort methods to precisely control the sort order of the elements.
'Compares two variants for their sort order. Returns -1 if v1 should be sorted ahead of v2; +1 if _
v2 should be sorted ahead of v1; and 0 if the two objects are of equal precedence. This function _
should exhibit several necessary behaviors: _
  1.) compare(x,y)=-(compare(y,x) for all x,y _
  2.) compare(x,y)>= 0 for all x,y _
  3.) compare(x,y)>=0 and compare(y,z)>=0 implies compare(x,z)>0 for all x,y,z
Public Function compare(ByRef v1 As Variant, ByRef v2 As Variant) As Long
End Function
If no IVariantComparator is provided to the sort methods, then the natural ordering is assumed. However, if you need to define a different sort order (e.g. reverse) or if you want to sort custom objects, you can implement the IVariantComparator interface. For example, to sort in reverse order, just create a class called CReverseComparator with the following code:
CReverseComparator class
Option Explicit
Implements IVariantComparator
Public Function IVariantComparator_compare(v1 As Variant, v2 As Variant) As Long
    IVariantComparator_compare = v2-v1
End Function
Then call the sort function as follows: Collections.sort col, New CReverseComparator
Bonus Material: For a visual comparison of the performance of different sorting algorithms check out https://www.toptal.com/developers/sorting-algorithms/
- 
                    1This was hard for me in VBA, like it took a herculean effort to make work since I'm not really a programmer. I finally used cpearson's array sort because making a Factory would be easier with bricks and the Collections.ToArray function adds an annoying extra item because it redim a(0 to count) instead of redim a(0 to count-1) since my arrays start at 0 based and my collections start at 1. – Henrietta Martingale May 25 '18 at 14:15
- 
                    3Seems like great information and code. It is not real clear where it needs to be placed for someone unfamiliar with VBA. "Just copy/paste the source code below into the appropriate modules." Where are these modules? – Joe McGrath Aug 08 '18 at 13:16
- 
                    9There are a lot of functions in here that are not defined in the modules and are not standard VBA functions, e.g. `copyOf()`,`length()`,`swap()`. It isn't testable in its current form; was there meant to be another module included with the answer? – sigil Jan 08 '19 at 23:51
- 
                    3I can't even find these functions in the GitHub Repository. E.g. Arrays.copyOf is stated in the Readme file but not included in Arrays.bas. The code in VBA-Utilities.xlam doesn't compile either because of missing methods. – Jörg Brenninkmeyer Aug 27 '19 at 10:01
The code below from this post uses a bubble sort
Sub SortCollection()
    Dim cFruit As Collection
    Dim vItm As Variant
    Dim i As Long, j As Long
    Dim vTemp As Variant
    Set cFruit = New Collection
    'fill the collection
    cFruit.Add "Mango", "Mango"
    cFruit.Add "Apple", "Apple"
    cFruit.Add "Peach", "Peach"
    cFruit.Add "Kiwi", "Kiwi"
    cFruit.Add "Lime", "Lime"
    'Two loops to bubble sort
    For i = 1 To cFruit.Count - 1
        For j = i + 1 To cFruit.Count
            If cFruit(i) > cFruit(j) Then
                'store the lesser item
                vTemp = cFruit(j)
                'remove the lesser item
                cFruit.Remove j
                're-add the lesser item before the
                'greater Item
                cFruit.Add vTemp, vTemp, i
            End If
        Next j
    Next i
    'Test it
    For Each vItm In cFruit
        Debug.Print vItm
    Next vItm
End Sub
 
    
    - 15,168
- 7
- 48
- 72
 
    
    - 32,673
- 4
- 52
- 73
- 
                    Thanks -- just needed to change vTemp to be of type Object to sort a collection of objects. – Ron Rosenfeld Oct 01 '14 at 19:56
- 
                    13
- 
                    1You can skip the 'key' parameter, and just put in an extra comma I found out. – bmende Aug 23 '15 at 10:38
- 
                    Also, if you try to shorten and put in cFruit.Remove cFruit(j) you get a run-time error – bmende Aug 23 '15 at 10:53
- 
                    1
- 
                    First: I hate(!!!) VBA Second: I get a runtime error (438) on `vTemp = cFruit(j)` and cant figure out why. – Jan Dec 06 '17 at 09:32
- 
                    `Set vTemp = cFruit(j)` helped me out, now I got stuck on `cFruit.Add vTemp, vTemp, i` with runtime error (13). .... VBA ..... >:( – Jan Dec 06 '17 at 09:37
- 
                    Solution: `cFruit.Add vTemp, , i` @bmende I HAD to skip the key parameter, such a pain... – Jan Dec 06 '17 at 09:40
- 
                    When you add an object (as opposed to a scalar value) you have to use the `Set` keyword as you discovered. The key to a collection has to be a string. When I'm adding strings, I can use the same thing for key and item. But when the item is an object, you have to use something different. Like if you were adding command buttons, you might use `vTemp.Name` as the key (or some other string property of the object). Certainly nothing wrong with using the index as you did, though. – Dick Kusleika Dec 06 '17 at 13:29
- 
                    +1 for Bubble Sort, if your data is nearly ordered then bubble sort is the way to go. Check out this comparison: https://www.toptal.com/developers/sorting-algorithms – SlowLearner Jul 12 '18 at 00:11
You could use a ListView.  Although it is a UI object, you can use its functionality. It supports sorting. You can store data in Listview.ListItems and then sort like this:
Dim lv As ListView
Set lv = New ListView
lv.ListItems.Add Text:="B"
lv.ListItems.Add Text:="A"
lv.SortKey = 0            ' sort based on each item's Text
lv.SortOrder = lvwAscending
lv.Sorted = True
MsgBox lv.ListItems(1)    ' returns "A"
MsgBox lv.ListItems(2)    ' returns "B"
 
    
    - 16,685
- 2
- 45
- 81
 
    
    - 339
- 3
- 2
- 
                    5This is sheer genius! I just tried it and it works very nicely. You can also sort on a particular subitem if you want to keep multiple sort orders in the same table. Don't forget to add the reference to `mscomctl.ocx`. – cxw Feb 06 '17 at 17:47
- 
                    2C:\Windows\SysWOW64\mscomctl.ocx Microsoft Common Controls . This is fab, surprised it can run without a form. – S Meaden Feb 07 '17 at 12:57
- 
                    1another workaround: copy collection to the range on the spreadsheet, sort the range and copy it back – ilya Dec 07 '20 at 06:07
- 
                    1This might work but is advised against. When working with a VBA collection and temporarily clone/copy it to a listview, make use of its sorting capabilities and then put the sorted items back into a collection (array) is cumbersome programming. Better use a generic sorting algorithm a mentionde in the answer of @Austin. Although this also involves a copy back-and-forth operatioin – Youp Bernoulli May 26 '22 at 17:17
Collection is a rather wrong object for sorting.
The very point of a collection is to provide very fast access to a certain element identified by a key. How the items are stored internally should be irrelevant.
You might want to consider using arrays instead of collections if you actually need sorting.
Other than that, yes, you can sort items in a collection.
You need to take any sorting algorithm available on the Internet (you can google inplementations in basically any language) and make a minor change where a swap occurs (other changes are unnecessary as vba collections, like arrays, can be accessed with indices). To swap two items in a collection, you need to remove them both from the collection and insert them back at the right positions (using the third or the forth parameter of the Add method).
 
    
    - 76,472
- 17
- 159
- 346
- 
                    1Using an array doesn't have the `.add` in vba for dynamic additions to the Array. – James Mertz Jun 29 '12 at 20:27
- 
                    
- 
                    1I understand, but you suggested using arrays instead of collections, which don't allow for dynamically adding to the array very easily. – James Mertz Jun 29 '12 at 20:42
- 
                    @KronoS The first part of the answer, separated with a line, is rather not connected to the second part. For arrays, you don't need to add any items when sorting. – GSerg Jun 29 '12 at 20:49
- 
                    There are some other problems with arrays in Excel, such as that you can use them as return values in functions. – Dynamicbyte Dec 17 '12 at 13:52
- 
                    @Dynamicbyte Don't get that. You can return an array from a function, and you can return a collection. – GSerg Dec 17 '12 at 14:03
- 
                    @GSerg: Sorry, I made a mistake it should be ".. you cannot use them as return values" – Dynamicbyte Jan 09 '13 at 12:22
- 
                    @GSerg: You cannot return an array from a function directly. That is only possible by using a Variant as the return type. – Dynamicbyte Jan 30 '13 at 15:59
- 
                    1@Dynamicbyte Yes you can. `Function foo() As Long()` returns an array of `Long`s. You're probably thinking about VB5. – GSerg Jan 30 '13 at 17:38
- 
                    
- 
                    I found that simply using an ArrayList instead of a collection was the best solution in my case. Even if you have to use a collection to start with for some reason, converting to an ArrayList and using .sort is probably still simpler than anything else. – SendETHToThisAddress Apr 15 '20 at 09:27
- 
                    @technoman23 There is no ArrayList in VBA, and I don't think bringing the one from .Net is worth the overhead. – GSerg Apr 15 '20 at 09:56
There is no native sort for the Collection in VBA, but since you can access items in the collection via index, you can implement a sorting algorithm to go through the collection and sort into a new collection.
Here's a HeapSort algorithm implementation for VBA/VB 6.
Here's what appears to be a BubbleSort algorithm implementation for VBA/VB6.
 
    
    - 124,184
- 33
- 204
- 266
If your collection doesn't contain objects and you only need to sort ascending, you might find this easier to understand:
Sub Sort(ByVal C As Collection)
Dim I As Long, J As Long
For I = 1 To C.Count - 1
    For J = I + 1 To C.Count
        If C(I) > C(J) Then Swap C, I, J
    Next
Next
End Sub
'Take good care that J > I
Sub Swap(ByVal C As Collection, ByVal I As Long, ByVal J As Long)
C.Add C(J), , , I
C.Add C(I), , , J + 1
C.Remove I
C.Remove J
End Sub
I hacked this up in minutes, so this may not be the best bubble sort, but it should be easy to understand, and hence easy to modify for your own purposes.
 
    
    - 51
- 1
- 1
This is my implementation of BubbleSort:
Public Function BubbleSort(ByRef colInput As Collection, _
                                    Optional asc = True) As Collection
    Dim temp                    As Variant
    Dim counterA                As Long
    Dim counterB                As Long
    For counterA = 1 To colInput.Count - 1
        For counterB = counterA + 1 To colInput.Count
            Select Case asc
            Case True:
                If colInput(counterA) > colInput(counterB) Then
                    temp = colInput(counterB)
                    colInput.Remove counterB
                    colInput.Add temp, temp, counterA
                End If
            Case False:
                If colInput(counterA) < colInput(counterB) Then
                    temp = colInput(counterB)
                    colInput.Remove counterB
                    colInput.Add temp, temp, counterA
                End If
            End Select
        Next counterB
    Next counterA
    Set BubbleSort = colInput
End Function
Public Sub TestMe()
    Dim myCollection    As New Collection
    Dim element         As Variant
    myCollection.Add "2342"
    myCollection.Add "vityata"
    myCollection.Add "na"
    myCollection.Add "baba"
    myCollection.Add "ti"
    myCollection.Add "hvarchiloto"
    myCollection.Add "stackoveflow"
    myCollection.Add "beta"
    myCollection.Add "zuzana"
    myCollection.Add "zuzan"
    myCollection.Add "2z"
    myCollection.Add "alpha"
    Set myCollection = BubbleSort(myCollection)
    For Each element In myCollection
        Debug.Print element
    Next element
    Debug.Print "--------------------"
    Set myCollection = BubbleSort(myCollection, False)
    For Each element In myCollection
        Debug.Print element
    Next element
End Sub
It takes the collection by reference, thus it can easily return it as a function and it has an optional parameter for Ascending and Descending sorting. The sorting returns this in the immediate window:
2342
2z
alpha
baba
beta
hvarchiloto
na
stackoveflow
ti
vityata
zuzan
zuzana
--------------------
zuzana
zuzan
vityata
ti
stackoveflow
na
hvarchiloto
beta
baba
alpha
2z
2342
 
    
    - 42,633
- 8
- 55
- 100
This code snippet works well, but it is in java.
To translate it you could do it like this:
 Function CollectionSort(ByRef oCollection As Collection) As Long
Dim smTempItem1 As SeriesManager, smTempItem2 As SeriesManager
Dim i As Integer, j As Integer
i = 1
j = 1
On Error GoTo ErrFailed
Dim swapped As Boolean
swapped = True
Do While (swapped)
    swapped = False
    j = j + 1
    For i = 1 To oCollection.Count - 1 - j
        Set smTempItem1 = oCollection.Item(i)
        Set smTempItem2 = oCollection.Item(i + 1)
        If smTempItem1.Diff > smTempItem2.Diff Then
            oCollection.Add smTempItem2, , i
            oCollection.Add smTempItem1, , i + 1
            oCollection.Remove i + 1
            oCollection.Remove i + 2
            swapped = True
        End If
    Next
Loop
Exit Function
ErrFailed:
     Debug.Print "Error with CollectionSort: " & Err.Description
     CollectionSort = Err.Number
     On Error GoTo 0
End Function
SeriesManager is just a class that stores the difference between two values. It can really be any number value you want to sort on. This by default sorts in ascending order.
I had difficulty sorting a collection in vba without making a custom class.
 
    
    - 19,874
- 8
- 24
- 34
 
    
    - 61
- 2
This is a VBA implementation of the QuickSort algorithm, which is often a better alternative to MergeSort:
Public Sub QuickSortSortableObjects(colSortable As collection, Optional bSortAscending As Boolean = True, Optional iLow1, Optional iHigh1)
    Dim obj1 As Object
    Dim obj2 As Object
    Dim clsSortable As ISortableObject, clsSortable2 As ISortableObject
    Dim iLow2 As Long, iHigh2 As Long
    Dim vKey As Variant
    On Error GoTo PtrExit
    'If not provided, sort the entire collection
    If IsMissing(iLow1) Then iLow1 = 1
    If IsMissing(iHigh1) Then iHigh1 = colSortable.Count
    'Set new extremes to old extremes
    iLow2 = iLow1
    iHigh2 = iHigh1
    'Get the item in middle of new extremes
    Set clsSortable = colSortable.Item((iLow1 + iHigh1) \ 2)
    vKey = clsSortable.vSortKey
    'Loop for all the items in the collection between the extremes
    Do While iLow2 < iHigh2
        If bSortAscending Then
            'Find the first item that is greater than the mid-Contract item
            Set clsSortable = colSortable.Item(iLow2)
            Do While clsSortable.vSortKey < vKey And iLow2 < iHigh1
                iLow2 = iLow2 + 1
                Set clsSortable = colSortable.Item(iLow2)
            Loop
            'Find the last item that is less than the mid-Contract item
            Set clsSortable2 = colSortable.Item(iHigh2)
            Do While clsSortable2.vSortKey > vKey And iHigh2 > iLow1
                iHigh2 = iHigh2 - 1
                Set clsSortable2 = colSortable.Item(iHigh2)
            Loop
        Else
            'Find the first item that is less than the mid-Contract item
            Set clsSortable = colSortable.Item(iLow2)
            Do While clsSortable.vSortKey > vKey And iLow2 < iHigh1
                iLow2 = iLow2 + 1
                Set clsSortable = colSortable.Item(iLow2)
            Loop
            'Find the last item that is greater than the mid-Contract item
            Set clsSortable2 = colSortable.Item(iHigh2)
            Do While clsSortable2.vSortKey < vKey And iHigh2 > iLow1
                iHigh2 = iHigh2 - 1
                Set clsSortable2 = colSortable.Item(iHigh2)
            Loop
        End If
        'If the two items are in the wrong order, swap the rows
        If iLow2 < iHigh2 And clsSortable.vSortKey <> clsSortable2.vSortKey Then
            Set obj1 = colSortable.Item(iLow2)
            Set obj2 = colSortable.Item(iHigh2)
            colSortable.Remove iHigh2
            If iHigh2 <= colSortable.Count Then _
                colSortable.Add obj1, Before:=iHigh2 Else colSortable.Add obj1
            colSortable.Remove iLow2
            If iLow2 <= colSortable.Count Then _
                colSortable.Add obj2, Before:=iLow2 Else colSortable.Add obj2
        End If
        'If the Contracters are not together, advance to the next item
        If iLow2 <= iHigh2 Then
            iLow2 = iLow2 + 1
            iHigh2 = iHigh2 - 1
        End If
    Loop
    'Recurse to sort the lower half of the extremes
    If iHigh2 > iLow1 Then QuickSortSortableObjects colSortable, bSortAscending, iLow1, iHigh2
    'Recurse to sort the upper half of the extremes
    If iLow2 < iHigh1 Then QuickSortSortableObjects colSortable, bSortAscending, iLow2, iHigh1
PtrExit:
End Sub
The objects stored in the collection must implement the ISortableObject interface, which must be defined in your VBA project. To do that, add a class module called ISortableObject with the following code:
Public Property Get vSortKey() As Variant
End Property
 
    
    - 441
- 2
- 4
I want to go a little bit further with igorsp7 QuickSort
If you dont wan't to use special Interface, just for the sake of sorting you can use CallByName function:
Public Sub QuickSortCollection(colSortable As Object, nameOfSortingProperty As String, Optional bSortAscending As Boolean = True, Optional iLow1, Optional iHigh1)
Dim obj1 As Object
Dim obj2 As Object
Dim clsSortable As Object
Dim clsSortable2 As Object
Dim iLow2 As Long, iHigh2 As Long
Dim vKey As Variant
On Error GoTo PtrExit
'If not provided, sort the entire collection
If IsMissing(iLow1) Then iLow1 = 1
If IsMissing(iHigh1) Then iHigh1 = colSortable.Count
'Set new extremes to old extremes
iLow2 = iLow1
iHigh2 = iHigh1
'Get the item in middle of new extremes
Set clsSortable = colSortable.Item((iLow1 + iHigh1) \ 2)
vKey = CallByName(clsSortable, nameOfSortingProperty, VbGet)
'Loop for all the items in the collection between the extremes
Do While iLow2 < iHigh2
    If bSortAscending Then
        'Find the first item that is greater than the mid-Contract item
        Set clsSortable = colSortable.Item(iLow2)
        Do While CallByName(clsSortable, nameOfSortingProperty, VbGet) < vKey And iLow2 < iHigh1
            iLow2 = iLow2 + 1
            Set clsSortable = colSortable.Item(iLow2)
        Loop
        'Find the last item that is less than the mid-Contract item
        Set clsSortable2 = colSortable.Item(iHigh2)
        Do While CallByName(clsSortable2, nameOfSortingProperty, VbGet) > vKey And iHigh2 > iLow1
            iHigh2 = iHigh2 - 1
            Set clsSortable2 = colSortable.Item(iHigh2)
        Loop
    Else
        'Find the first item that is less than the mid-Contract item
        Set clsSortable = colSortable.Item(iLow2)
        Do While CallByName(clsSortable, nameOfSortingProperty, VbGet) > vKey And iLow2 < iHigh1
            iLow2 = iLow2 + 1
            Set clsSortable = colSortable.Item(iLow2)
        Loop
        'Find the last item that is greater than the mid-Contract item
        Set clsSortable2 = colSortable.Item(iHigh2)
        Do While CallByName(clsSortable2, nameOfSortingProperty, VbGet) < vKey And iHigh2 > iLow1
            iHigh2 = iHigh2 - 1
            Set clsSortable2 = colSortable.Item(iHigh2)
        Loop
    End If
    'If the two items are in the wrong order, swap the rows
    If iLow2 < iHigh2 And CallByName(clsSortable, nameOfSortingProperty, VbGet) <> CallByName(clsSortable2, nameOfSortingProperty, VbGet) Then
        Set obj1 = colSortable.Item(iLow2)
        Set obj2 = colSortable.Item(iHigh2)
        colSortable.Remove iHigh2
        If iHigh2 <= colSortable.Count Then _
            colSortable.Add obj1, before:=iHigh2 Else colSortable.Add obj1
        colSortable.Remove iLow2
        If iLow2 <= colSortable.Count Then _
            colSortable.Add obj2, before:=iLow2 Else colSortable.Add obj2
    End If
    'If the Contracters are not together, advance to the next item
    If iLow2 <= iHigh2 Then
        iLow2 = iLow2 + 1
        iHigh2 = iHigh2 - 1
    End If
Loop
'Recurse to sort the lower half of the extremes
If iHigh2 > iLow1 Then Call QuickSortCollection(colSortable, nameOfSortingProperty, bSortAscending, iLow1, iHigh2)
'Recurse to sort the upper half of the extremes
If iLow2 < iHigh1 Then Call QuickSortCollection(colSortable, nameOfSortingProperty, bSortAscending, iLow2, iHigh1)
PtrExit:
End Sub
Also i've changed colSortable to be Object, as I'm using a lot of custom typed collections.
 
    
    - 11
- 1
As mentioned, Collections do not have a built in sort feature. I came up with a simpler implementation using VBA Collection's built in After property.
This method loops through each existing item in the Collection, and once the new item (NewItem) comes later than the current loop value (Col.Item(i)) by ASCII comparison, it exits the loop and adds NewItem into that spot.
Private Sub InsertCollectionValueAlphabetically(Col As Collection, NewItem As String)
    Dim i As Long
    
    If Col.Count = 0 Then
        Col.Add NewItem, NewItem  'First value gets added without trying to loop through
        Exit Sub
    End If
    
    For i = 1 To Col.Count
        'Convert to lower case to get predictable behavior after ASCII text comparison
        If (LCase(NewItem) < LCase(Col.Item(i))) Then Exit For
    Next i
    
    If i = 1 Then
        Col.Add NewItem, NewItem, 1
    Else
        Col.Add NewItem, NewItem, , i - 1
    End If
End Sub
 
    
    - 2,816
- 5
- 30
- 52
Added missing features( copyOf(), length(), swap() ) to the answer above(@Austin).
Public Function copyOf(a As Variant) As Variant()
    Dim el As Variant
    Dim ar() As Variant
    Dim i As Integer
    ReDim ar(UBound(a))
    i = 0
    For Each el In a
        If IsEmpty(el) Then
            Exit For
        End If
        Set ar(i) = el
        i = i + 1
    Next
    copyOf = ar
End Function
    
Public Function length(a As Variant) As Long
    length = UBound(a)
End Function
Public Sub swap(arr() As Variant, a As Integer, b As Integer)
    Dim x As Variant
    Set x = arr(a)
    Set arr(a) = arr(b)
    Set arr(b) = x
End Sub
 
    
    - 11
- 2
 
     
    
 
    