This UDF returns an array of the values of the inputRange sorted by the keyColumn
Putting the array formula {=QSortedRange(B2:H6,3,TRUE)} in P2:V6 will show the range B2:H6,
sorted descending by column3 (relative to B2, that is column D).
It can also be called from a VB routine and not shown on the sheet.
Option Explicit
Public imageArray As Variant
Public keyCol As Long
Function QSortedRange(inputRange As Range, Optional keyColumn As Long, Optional descending As Boolean) As Variant
Dim RowArray As Variant
Dim outRRay As Variant
Dim i As Long, j As Long
If keyColumn = 0 Then keyColumn = 1
If inputRange.Columns.Count < keyColumn Then
QSortedRange = CVErr(xlErrRef)
Else
keyCol = keyColumn
imageArray = inputRange.Value
ReDim RowArray(1 To inputRange.Rows.Count)
For i = 1 To UBound(RowArray)
RowArray(i) = i
Next i
Call sortQuickly(RowArray, descending)
outRRay = imageArray
For i = 1 To UBound(outRRay, 1)
For j = 1 To UBound(outRRay, 2)
outRRay(i, j) = imageArray(RowArray(i), j)
Next j
Next i
QSortedRange = outRRay
End If
End Function
Sub sortQuickly(ByRef inRRay As Variant, Optional ByVal descending As Boolean, Optional ByVal low As Long, Optional ByVal high As Long)
Dim pivot As Variant
Dim i As Long, pointer As Long
If low = 0 Then low = LBound(inRRay)
If high = 0 Then high = UBound(inRRay)
pointer = low
Call Swap(inRRay, (low + high) / 2, high)
pivot = inRRay(high)
For i = low To high - 1
If LT(inRRay(i), pivot) Xor descending Then
Call Swap(inRRay, i, pointer)
pointer = pointer + 1
End If
Next i
Call Swap(inRRay, pointer, high)
If low < pointer - 1 Then
Call sortQuickly(inRRay, descending, low, pointer - 1)
End If
If pointer + 1 <= high Then
Call sortQuickly(inRRay, descending, pointer + 1, high)
End If
End Sub
Function LT(aRow As Variant, bRow As Variant) As Boolean
On Error GoTo excelComparison
LT = (imageArray(aRow, keyCol) < imageArray(bRow, keyCol))
On Error GoTo 0
Exit Function
excelComparison:
LT = aRow < bRow
On Error GoTo 0
End Function
Sub Swap(ByRef inRRay, a As Long, b As Long)
Dim temp As Variant
temp = inRRay(a)
inRRay(a) = inRRay(b)
inRRay(b) = temp
End Sub
(Array formulas are confirmed with Ctrl-Shift-Enter (Cmd+Return for Mac))