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
| |