|
Got an array of information you want to sort? Sort by one (BubbleSort) or two dimensions. Pass the array and it will be changed. This example uses a string array. (If I recall correctly, there was an issue using a variant array and all strings worked). For numbers in a 2D string array, perhaps make 2 columns to store them; one to show with formatting for display to users and the other padded with zeros for sorting.
Since this is pure VBA code and not application specific, it will work with Access as well as other applications like Excel, Word, PowerPoint, and Visio.
For performance, there's a counter for number of swaps so that VBA will stop the loop for comparing if there's nothing else to sort.
Sort Ascending or Descending
The Main procedure is to sort an array with 2-dimensions. It also works with one dimension (but is more complex than the simple BubbleSort example).
Pass an array to changed by sorting. Optionally, send a column number to sort by. Optionally send a boolean to sort descending instead of ascending (default).
The code checks the column number sent to ensure it's valid and if not, makes a logical choice.
There are additional procedures, for testing
Download zipped BAS file that you can import with a function to sort one or two dimensional array. Also contains simple Bubble Sort for one dimension and test procedures. bas_Array_Sort_s4p.zip
If you have trouble with the downloads, you may need to unblock the ZIP file, aka remove Mark of the Web, before extracting the file. Here are steps to do that: https://msaccessgurus.com/MOTW_Unblock.htm
watch on YouTube: How does Bubble Sort work? (5:50)
INITAL ARRAY: Dim asArray(1 To 5, 1 To 3) As String ------------------------- 1 Butch; Dog; 07 2 Midnight; Cat; 15 3 Tweety; Bird; 85 4 Fred; Fish; 02 5 Sylvester; Cat; 79 ------------------------- Sort2DStringArray(asArray), 1st column Ascending ------------------------- 1 Butch; Dog; 07 2 Fred; Fish; 02 3 Midnight; Cat; 15 4 Sylvester; Cat; 79 5 Tweety; Bird; 85 ------------------------- Sort2DStringArray(asArray, 2), 2nd column ascending tie in sort column is then by the last sort ------------------------- 1 Tweety; Bird; 85 2 Midnight; Cat; 15 3 Sylvester; Cat; 79 4 Butch; Dog; 07 5 Fred; Fish; 02 ------------------------- Sort2DStringArray(asArray, 2, True), 2nd column descending tie in sort column is broken by same initial Name sort ------------------------- 1 Fred; Fish; 02 2 Butch; Dog; 07 3 Midnight; Cat; 15 4 Sylvester; Cat; 79 5 Tweety; Bird; 85 ------------------------- Sort2DStringArray(asArray, 1, True), 1st column Descending ------------------------- 1 Tweety; Bird; 85 2 Sylvester; Cat; 79 3 Midnight; Cat; 15 4 Fred; Fish; 02 5 Butch; Dog; 07 ------------------------- Sort2DStringArray(asArray, 3, True), 3rd column descending ------------------------- 1 Tweety; Bird; 85 2 Sylvester; Cat; 79 3 Midnight; Cat; 15 4 Butch; Dog; 07 5 Fred; Fish; 02 -------------------------
INITAL ARRAY ------------------------- 0 Title 1 Subject 2 Author 3 Keywords 4 Comments 5 Last author 6 Revision number 7 Application name 8 Manager 9 Company ------------------------- SORTED ARRAY, Ascending ------------------------- 0 Application name 1 Author 2 Comments 3 Company 4 Keywords 5 Last author 6 Manager 7 Revision number 8 Subject 9 Title ------------------------- SORTED ARRAY, Descending ------------------------- 0 Title 1 Subject 2 Revision number 3 Manager 4 Last author 5 Keywords 6 Company 7 Comments 8 Author 9 Application name -------------------------
Option Compare Text 'Ignore Case Option Explicit 'variables must be declared '*************** Code Start *************************************************** ' module: bas_Array_Sort_s4p ' ' Purpose : Pass a string array you want to sort ' -- it will be changed. ' 1- or 2-dimensional string array ' Optionally, designate a column index to sort by ' default column=0 and will be adjusted to lowest if not sent ' Optionally, indicate descending order ' Author : crystal (strive4peace) ' this code: https://msaccessgurus.com/VBA/Array_Sort2D.htm ' LICENSE : ' You may freely use and share this code, but not sell it. ' Keep attribution. Mark your changes. Use at your own risk. '------------------------ ' PROCEDURES ' Sort2DStringArray ' BubbleSort '------------------------ ' testBubbleSort ' test2DSort ' WriteBubbleArray2Debug ' Write2DArray2Debug '-------------------------------------------------------------------------------- '------------------------------------------------------------------------------- ' Sort2DStringArray '------------------------------------------------------------------------------- Public Sub Sort2DStringArray(ByRef psArray() As String _ ,Optional ByVal piSortColumnIndex As Integer = 0 _ ,Optional ByVal pbDescending As Boolean = False _ ) ' Sort a 2-dimensional string array by specified column ' based on bubble-sort code by Brent Spaulding ' 260906 UPDATED to specify descending sort pbDescending, bSwap, ' 240520 strive4peace,... 240714 stop if done,260820 'PARAMETERs ' psArray -- string array you want to sort ' 1 or 2 dimensions will be considered ' piSortColumnIndex is the column index (2nd dimension) ' in the array to sort by ' if not specified or lower, will be by the first column ' if higher than last, will be by the last column ' pbDescending is True for descending sort. Default=False On Error GoTo Proc_Err Dim asCurrentValue() As String ' pbDescending calculated True=Descending, False=Ascending (default) Dim iColumn As Integer _ ,iColumn1 As Integer _ ,iColumn2 As Integer _ ,iRow As Integer _ ,iRow1 As Integer _ ,iRow2 As Integer _ ,iRows As Integer _ ,iLastRow As Integer _ ,iCountSwap As Integer _ ,sValue1 As String _ ,sValue2 As String _ ,bSwap As Boolean iRow1 = LBound(psArray,1) 'first row iRow2 = UBound(psArray,1) 'last row iRows = iRow2 - iRow1 + 1 'calculate number of rows iColumn1 = LBound(psArray,2) 'first column iColumn2 = UBound(psArray,2) 'last column iCountSwap = 0 'haven't swapped anything yet If piSortColumnIndex < iColumn1 Then 'sort by first column if lower number specified 'default is 0 piSortColumnIndex = iColumn1 End If If piSortColumnIndex > iColumn2 Then 'sort by last column if higher number specified piSortColumnIndex = iColumn2 End If 'array with current values -- works with 1D arrays too ReDim asCurrentValue(iColumn1 To iColumn2) 'Bubble sort the array if more than 1 row If iRows > 1 Then 'set the last row to compare iLastRow = iRow2 Do Until iLastRow = iRow1 iCountSwap = 0 'no swaps yet for this pass 'loop from first row to next to last row For iRow = iRow1 To iLastRow - 1 'store current value and next value, in Sort Column sValue1 = psArray(iRow,piSortColumnIndex) sValue2 = psArray(iRow + 1,piSortColumnIndex) bSwap = False 'is comparison ascending or descending? If pbDescending <> False Then 'True - descending If sValue1 < sValue2 Then 'sort descending bSwap = True End If Else 'ascending If sValue1 > sValue2 Then bSwap = True End If End If 'swap values If bSwap <> False Then 'save current value for each column in array For iColumn = iColumn1 To iColumn2 asCurrentValue(iColumn) = psArray(iRow,iColumn) Next iColumn 'swap value in each column For iColumn = iColumn1 To iColumn2 'assign current values to next row values psArray(iRow,iColumn) = psArray(iRow + 1,iColumn) 'assign next row values to saved values psArray(iRow + 1,iColumn) = asCurrentValue(iColumn) Next iColumn 'count how many swaps made for this pass iCountSwap = iCountSwap + 1 End If 'values swapped Next iRow 'stop the loop if no swaps were made If Not iCountSwap > 0 Then 'all done! Exit Do End If iLastRow = iLastRow - 1 'decrement last row iCountSwap = 0 'reset swap counter Loop ' Until iLastRow = iRow1 End If Proc_Exit: Exit Sub Proc_Err: MsgBox Err.Description _ ,, "ERROR " & Err.Number _ & " Sort2DStringArray" Resume Proc_Exit Resume End Sub '------------------------------------------------------------------------------- ' BubbleSort -- simple example '------------------------------------------------------------------------------- Public Sub BubbleSort(ByRef psArray() As String _ ,Optional ByVal pbDescending As Boolean = False _ ) ' 240714 strive4peace ' 260904 descending sort: pbDescending=True, bSwap ' Sort a single dimension string array ' based on bubble-sort code originally written by Brent Spaulding ' PARAMETERS ' psArray -- string array to sort ' pbDescending = True to sort descending. Default=False=sort ascending On Error GoTo Proc_Err Dim iRow As Integer _ ,iRow1 As Integer _ ,iRow2 As Integer _ ,iRows As Integer _ ,iLastRow As Integer _ ,iCountSwap As Integer _ ,sValue1 As String _ ,sValue2 As String _ ,bSwap As Boolean iRow1 = LBound(psArray,1) 'first row iRow2 = UBound(psArray,1) 'last row iRows = iRow2 - iRow1 + 1 'calculate number of rows iCountSwap = 0 'haven't swapped anything yet 'Bubble sort the array if more than 1 row If iRows > 1 Then 'set the last row to compare iLastRow = iRow2 'loop until last row is the first row Do Until iLastRow = iRow1 'loop from first row to next to last row For iRow = iRow1 To iLastRow - 1 'store current value and next value sValue1 = psArray(iRow) sValue2 = psArray(iRow + 1) bSwap = False 'is comparison Ascending or Descending? If pbDescending <> False Then 'sort descending 'if current is less than next, then swap If sValue1 < sValue2 Then bSwap = True End If Else 'sort ascending 'if current is greater than next, then swap If sValue1 > sValue2 Then bSwap = True End If End If 'swap values If bSwap <> False Then 'save current value for each column in array 'set current row value = next value psArray(iRow) = sValue2 'set next value = saved current value psArray(iRow + 1) = sValue1 'count how many swaps made for this pass iCountSwap = iCountSwap + 1 End If Next iRow 'stop the loop if no swaps were made If Not iCountSwap > 0 Then 'all done! Exit Do End If iLastRow = iLastRow - 1 'decrement last row iCountSwap = 0 'reset swap counter Loop ' Until iLastRow = iRow1 End If Proc_Exit: On Error GoTo 0 'reset Exit Sub Proc_Err: MsgBox Err.Description _ ,, "ERROR " & Err.Number _ & " BubbleSort" Resume Proc_Exit Resume End Sub '------------------------------------------------------------------------------- ' testBubbleSort '------------------------------------------------------------------------------- Sub testBubbleSort() '270414 s4p, for testing, 260904 descending 'make an array with string values ' write the original values to the Debug (Immediate) window, Ctrl-G ' show how the array changes ' for Ascending and Descending sorting 'CALLs ' BubbleSort ' WriteBubbleArray2Debug Dim asArray() As String 'define test array by splitting a string at each comma asArray = Split( _ "Title" _ & ",Subject" _ & ",Author" _ & ",Keywords" _ & ",Comments" _ & ",Last author" _ & ",Revision number" _ & ",Application name" _ & ",Manager" _ & ",Company" _ , ",") Debug.Print "INITAL ARRAY" Call WriteBubbleArray2Debug(asArray) 'sort the array Call BubbleSort(asArray) Debug.Print "SORTED ARRAY, Ascending" Call WriteBubbleArray2Debug(asArray) 'sort the array in descending order Call BubbleSort(asArray,True) Debug.Print "SORTED ARRAY, Descending" Call WriteBubbleArray2Debug(asArray) End Sub '------------------------------------------------------------------------------- ' test2DSort '------------------------------------------------------------------------------- Sub test2DSort() '260904 s4p, for testing 'make a 2-dimensional array with string values ' write the original values to the Debug (Immediate) window, Ctrl-G ' and show how the array changes ' depending on how it is sorted 'CALLs ' Sort2DStringArray ' Write2DArray2Debug Dim asArray(1 To 5,1 To 3) As String 'define test array 'Name, species, age 'Tweety and Sylvester first appeared together in 1947 asArray(1,1) = "Butch": asArray(1,2) = "Dog": asArray(1,3) = "07" asArray(2,1) = "Midnight": asArray(2,2) = "Cat": asArray(2,3) = "15" asArray(3,1) = "Tweety": asArray(3,2) = "Bird": asArray(3,3) = "85" asArray(4,1) = "Fred": asArray(4,2) = "Fish": asArray(4,3) = "02" asArray(5,1) = "Sylvester": asArray(5,2) = "Cat": asArray(5,3) = "79" Debug.Print "INITAL ARRAY: Dim asArray(1 To 5, 1 To 3) As String" Call Write2DArray2Debug(asArray) 'sort the array by first column Call Sort2DStringArray(asArray) Debug.Print "Sort2DStringArray(asArray), 1st column Ascending" Call Write2DArray2Debug(asArray) 'sort the array by 2nd column Call Sort2DStringArray(asArray,2) Debug.Print "Sort2DStringArray(asArray, 2), 2nd column ascending" Debug.Print "tie in sort column is then by the last sort" Call Write2DArray2Debug(asArray) 'sort the array by 2nd column, descending Call Sort2DStringArray(asArray,2,True) Debug.Print "Sort2DStringArray(asArray, 2, True), 2nd column descending" Debug.Print "tie in sort column is broken by same initial Name sort" Call Write2DArray2Debug(asArray) 'sort the array by first column, descending Call Sort2DStringArray(asArray,1,True) Debug.Print "Sort2DStringArray(asArray, 1, True), 1st column Descending" Call Write2DArray2Debug(asArray) 'sort the array by 3rd column in descending order Call Sort2DStringArray(asArray,3,True) Debug.Print "Sort2DStringArray(asArray, 3, True), 3rd column descending" Call Write2DArray2Debug(asArray) End Sub '------------------------------------------------------------------------------- ' WriteBubbleArray2Debug -- for testing '------------------------------------------------------------------------------- Public Sub WriteBubbleArray2Debug( _ ByRef psArray() As String _ ,Optional pbShowIndex As Boolean = True) '270414 s4p, for testing,260905 ' iterate the passed single dimension string array ' Write the array index and its values ' to the debug (Immediate) window ' PARAMETERs ' psArray -- single dimension string array ' pbShowIndex = true to show element index Dim i As Integer Debug.Print String(25, "-") For i = LBound(psArray) To UBound(psArray) If pbShowIndex Then Debug.Print i; Tab(7); End If Debug.Print psArray(i) Next i Debug.Print String(25, "-") End Sub '------------------------------------------------------------------------------- ' Write2DArray2Debug -- for testing '------------------------------------------------------------------------------- Public Sub Write2DArray2Debug( _ ByRef psArray() As String _ ,Optional pbShowIndex As Boolean = True) '270414 s4p, for testing,260905 ' iterate the passed 2-dimensional string array ' Write the array index and values for each column ' to the debug (Immediate) window ' PARAMETERs ' psArray -- 2D string array (also work with 1D?) ' pbShowIndex = true to show element index in output Dim iRow As Integer _ ,iCol As Integer _ ,vString As Variant Debug.Print String(25, "-") For iRow = LBound(psArray) To UBound(psArray) vString = Null If pbShowIndex Then Debug.Print iRow; Tab(7); End If For iCol = LBound(psArray,2) To UBound(psArray,2) vString = (vString + "; ") & psArray(iRow,iCol) Next iCol Debug.Print vString Next iRow Debug.Print String(25, "-") End Sub '*************** Code End *******************************************************' Code was generated with colors using the free Color Code add-in for Access
Help: LBound function
Help: UBound function
Help: Exit statement
Help: String function
Help: ByRef, ByVal
Maybe instead of saving values to a table, you're using an array that only exists in memory?
BubbleSort is a fairly simple version of sorting a string array. It was based on code originally written by Brent Spaulding. It sorts by one dimension. How it works is explained in:
YouTube video: How does Bubble Sort work? (5:50)
Until I wrote intermediate arrays to Debug, for Bubble Sort video visuals, it didn't occur to me to stop comparing ... hence a new thing to keep track of — iCountSwap — number of swaps so looping and comparing will stop if there's nothing more to do.
Sort2DStringArray works with 2 dimensions like an Excel spreadsheet. Whenever data is swapped, so are corresponding values in related columns.
If no particular column is specified, array will be sorted by the first column. This could be expanded for more than 2 dimensions.