IsStringLess |
Description: | |
IsStringLess is a simple function that will compare two strings and tell you if the first is less than the second. Unlike using StrComp(), it will take into account any numbers that appear in the strings. For instance, the two strings "Track 2 - Blues" and "Track 10 - Pop" would sort using StrComp with the 10 first. IsStringLess sorts them as you might want them sorted, with the 2 first. The example shows how to sort a collection using this function and the clsSort class available elsewhere on this site. 11/23/2003: Removed the need for the comparison function to create a duplicate of each string, speeding up the comparison by about 30%. | |
Code: | |
Public Function IsStringLess( _ sString1 As String, _ sString2 As String) As Boolean Dim nPos1 As Long Dim nPos2 As Long Dim nEndPos1 As Long Dim nEndPos2 As Long Dim sChar1 As String Dim sChar2 As String Dim nResult As Long Do nPos1 = nPos1 + 1 nPos2 = nPos2 + 1 sChar1 = Mid(sString1, nPos1, 1) sChar2 = Mid(sString2, nPos2, 1) If Len(sChar1) > Len(sChar2) Then IsStringLess = False Exit Function ElseIf Len(sChar2) > Len(sChar1) Then IsStringLess = True Exit Function ElseIf Len(sChar1) = 0 Then IsStringLess = False Exit Function End If ' See if this part of both strings looks like a number If IsNum(sChar1) And IsNum(sChar2) Then 'Look for the end of the numeric part nEndPos1 = nPos1 Do nEndPos1 = nEndPos1 + 1 Loop While IsNum(Mid(sString1, nEndPos1, 1)) nEndPos2 = nPos2 Do nEndPos2 = nEndPos2 + 1 Loop While IsNum(Mid(sString2, nEndPos2, 1)) 'Compare the two numbers Do If nEndPos1 - nPos1 = nEndPos2 - nPos2 Then ' If the lengths of the numbers are ' equal, compare them nResult = StrComp(Mid(sString1, nPos1, nEndPos1 - _ nPos1), Mid(sString2, nPos2, nEndPos2 - _ nPos2)) If nResult = 0 Then nPos1 = nEndPos1 - 1 nPos2 = nEndPos2 - 1 Exit Do ElseIf nResult = -1 Then IsStringLess = True Exit Function Else IsStringLess = False Exit Function End If ElseIf nEndPos1 - nPos1 > nEndPos2 - nPos2 Then 'If the first number is longer, make sure it's not ' zero padded, otherwise it's ' bigger If Mid(sString1, nPos1, 1) = "0" Then 'If it's zero padded, just ignore the zeros nPos1 = nPos1 + 1 Else IsStringLess = False Exit Function End If Else 'If the second number is longer, make sure it's not ' zero padded, otherwise it's ' bigger If Mid(sString2, nPos2, 1) = "0" Then 'If it's zero padded, just ignore the zeros nPos2 = nPos2 + 1 Else IsStringLess = True Exit Function End If End If Loop Else 'One or both of these characters is not a number, so just ' compare them as a string nResult = StrComp(sChar1, sChar2, vbTextCompare) If nResult <> 0 Then IsStringLess = (nResult = -1) Exit Do End If End If Loop End Function Public Function IsNum(s As String) As Boolean If Len(s) = 0 Then IsNum = False Else IsNum = Asc(Mid(s, 1, 1)) >= Asc("0") And _ Asc(Mid(s, 1, 1)) <= Asc("9") End If End Function | |
Sample Usage: | |
Private WithEvents m_sort As clsSort Private Sub Example() Set m_sort = New clsSort Dim col As Collection Set col = New Collection col.Add "20 - Twenty" col.Add "1 - One" col.Add "10 - Ten (1)" col.Add "2 - Two" col.Add "15 - Fifteen" col.Add "1 - One (b)" col.Add "10 - Ten (2)" col.Add "3 - Three" col.Add "10 - Ten (100)" m_sort.Sort col, SortCustom Dim vItem As Variant For Each vItem In col Debug.Print vItem Next ' Results: '1 - One '1 - One (b) '2 - Two '3 - Three '10 - Ten (1) '10 - Ten (2) '10 - Ten (100) '15 - Fifteen '20 - Twenty End Sub Private Sub m_sort_IsLess(obj1 As Variant, obj2 As Variant, _ bResult As Boolean) bResult = IsStringLess(CStr(obj1), CStr(obj2)) End Sub |