Given that a custom sort is required because that offered by the ListBox is unsuitable, here are some relative timings for some different approaches/ methods;
In my tests the data is obtained from a Source array of about 11,500 records with about 6700 unique entries, each entry can be up to 30 characters long, trailing spaces trimmed.
To ensure unique entries in the final list a Collection is used as follows; (this has been found quicker than using a binary search of existing entries or SendMessage(.hWnd, LB_FINDSTRINGEXACT, -1, ByVal a$)
Code:
For i = 1 To UBound(SourceArray)
a$ = SourceArray(i)
On Error Resume Next
col.Add vbNullChar, UCase$(a$)
If Err.Number = 0 Then (typically) List1.AddItem a$ 'this line varies depending on the sort method being used
On Error GoTo 0
Next
Method 0 the reference - Use a Sorted ListBox as in the code above - 0.34s (the sort is flawed as previosly discussed)
An unsorted ListBox is used and a custom sort of some kind is applied in all the following
Method 1 - Add all items and then sort them in situ in the ListBox - 17s
Method 2 - Insert items into the Collection in order via a binary search to determine the insertion point, then add/ loop them into the ListBox in order - 3.94s
Method 3 - Insert items into the ListBox in order via a binary search to determine the insertion point - 0.53s
Method 4 - Add all items into a String array, sort them using a QuickSort routine, then add/ loop them into the ListBox in order - 0.38s
Results are very similar on XP single core 2.26GHz (IDE and exe) and on a Win7 i7 Quad core 1.73GHz in the IDE, timings for exes on the Win7 machine however are significantly slower for me.
Any feedback after comparing speed of the following (just straight forward .AddItem with no sorting) in IDE vs exe in W7 would be appreciated;
Code:
Option Explicit
Private Declare Function QueryPerformanceFrequency Lib "kernel32" (lpFrequency As Currency) As Long
Private Declare Function QueryPerformanceCounter Lib "kernel32" (lpPerformanceCount As Currency) As Long
Private Sub Command7_Click()
Dim i&, j&, QPTicks As Currency, QPTicks2 As Currency, QPfreq As Currency
'List1 is set unsorted at design time
QueryPerformanceFrequency QPfreq
List1.Visible = False
QueryPerformanceCounter QPTicks
For j = 1 To 100
List1.Clear
For i = 1 To 1000
List1.AddItem CStr(i)
Next
Next
QueryPerformanceCounter QPTicks2
List1.Visible = True
MsgBox j - 1 & "*" & List1.ListCount & " Items in " & (QPTicks2 - QPTicks) / QPfreq & " seconds"
End Sub