Lastname Firstname
ADAMS GARY A
Adams Gary
ANDREWS, JR. CLAYTON D.
Andrews Clayton
By default, the LIKE function does case-sensitive pattern matching. So, my lastname and firstname column comparisons using the LIKE operator failed under the default (case-sensitive) conditions.
rngRow.Cells(1, 8) Like (rngRow.Offset(lngFrom).Cells(1, 8) & "*")
rngRow.Cells(1, 9) Like (rngRow.Offset(lngFrom).Cells(1, 9) & "*")
InStr(1, rngRow.Cells(1, 8), rngRow.Offset(lngFrom).Cells(1, 8), vbTextCompare) = 1
InStr(1, rngRow.Cells(1, 9), rngRow.Offset(lngFrom).Cells(1, 9), vbTextCompare) = 1
Note: I could have used one of the VB case-shifting functions to make both strings upper case or lower case. For a few small strings, this might be an acceptable solution. However, both large strings and lots of UCase()/LCase() invocations have performance detractors.
OPTION COMPARE TEXT
in the General Declarations section. But that meant that ALL comparisons in that module would be case-insensitive. This led me to my latest recommendation...Create Two Modules -- one case-sensitive and the other not.
Attribute VB_Name = "mod_CS"
Option Explicit
Option Compare Binary
Public Function IsLike_CS(parmText As String, parmPattern As String) As Boolean
IsLike_CS = parmText Like parmPattern
End Function
Public Function IsEqual_CS(parmA As String, parmB As String) As Boolean
IsEqual_CS = (parmA = parmB)
End Function
Public Function InStr_CS(parmText As String, parmFind As String) As Long
InStr_CS = InStr(parmText, parmFind)
End Function
Attribute VB_Name = "mod_CI"
Option Explicit
Option Compare Text
Public Function IsEqual_CI(parmA As String, parmB As String) As Boolean
IsEqual_CI = (parmA = parmB)
End Function
Public Function IsLike_CI(parmText As String, parmPattern As String) As Boolean
IsLike_CI = parmText Like parmPattern
End Function
Public Function InStr_CI(parmText As String, parmFind As String) As Long
InStr_CI = InStr(parmText, parmFind)
End Function
IsLike_CI(rngRow.Cells(1, 8), rngRow.Offset(lngFrom).Cells(1, 8) & "*")
IsLike_CI(rngRow.Cells(1, 9), rngRow.Offset(lngFrom).Cells(1, 9) & "*")
?IsLike_CI("Now is the time","[n]*THE*")
True
?IsLike_CS("Now is the time","[nN]*the*")
True
Notice that the first letter part of the case-insensitive pattern, [n], is simplified.
?InStr(1, "Now is the time", "IS", vbTextCompare)
5
?InStr_CI("Now is the time","IS")
5
?IsEqual_CI("abba","ABBA")
True
?IsEqual_CS("abba","ABBA")
False
'class: clsCICS
Option Explicit
Public Function IsEqual_CI(ByVal parmA As String, ByVal parmB As String) As Boolean
IsEqual_CI = mod_CI.IsEqual_CI(parmA, parmB)
End Function
Public Function IsEqual_CS(ByVal parmA As String, ByVal parmB As String) As Boolean
IsEqual_CS = mod_CS.IsEqual_CS(parmA, parmB)
End Function
Public Function InStr_CI(ByVal parmText As String, ByVal parmFind As String) As Long
InStr_CI = mod_CI.InStr_CI(parmText, parmFind)
End Function
Public Function InStr_CS(ByVal parmText As String, ByVal parmFind As String) As Long
InStr_CS = mod_CS.InStr_CS(parmText, parmFind)
End Function
Public Function IsLike_CS(ByVal parmText As String, ByVal parmPattern As String) As Boolean
IsLike_CS = mod_CS.IsLike_CS(parmText, parmPattern)
End Function
Public Function IsLike_CI(ByVal parmText As String, ByVal parmPattern As String) As Boolean
IsLike_CI = mod_CI.IsLike_CI(parmText, parmPattern)
End Function
Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.
Comments (10)
Commented:
Using the like method, 100m iterations took 24395 milliseconds; using the instr method, 100m iterations took 20228 milliseconds.
I again ran another test, but this time, rather than using lcase, I used the option vbTextCompare. This took 16338 milliseconds.
Whilst one like statement can be really simple to use, replacing it with many instr statements, would be ~33% faster.
DanRollins, if you could please enlighten us as to how to implement what you say.
Commented:
Author
Commented:>>I made a test where each method had to find "f*n*" in "Find" (case insensitive).
You created a test where two InStr() functions could match the pattern. My earlier comment and point to using the LIKE operator is that you can do a match that can NOT be done with InStr() functions without a great deal of teeth gnashing and hair pulling.
>>Using the like method, 100m iterations ...
Performance measurement it isn't just about iterations, you have to evaluate different scenarios, such as long strings, mixed case strings, placement of near-miss patterns in the string, and different placement of exact match substrings.
>>Whilst one like statement can be really simple to use, replacing it with many instr statements, would be ~33% faster.
I'm not sure if you are showing performance times for TWO InStr() functions, which is required to match the pattern you are testing. If not, then two InStr() functions (32k ms) are more than a single LIKE operator (24k ms).
Even if your InStr() times are for a pair of InStr() functions, "many instr statements" is an erroneous conclusion. It fails the reader (performance evaluator) in deciding how many InStr() functions one might use in place of a single LIKE operator.
=================
For case insensitive searching, even the native InStr() function can be beat. Consider this VBSpeed article:
http://www.xbeat.net/vbspeed/c_InStr.htm
Despite my proclivity towards highly optimized operations and code, I will use a less optimal strategy to accomplish other development goals, such as rapid prototyping and flexibility.
Commented:
I agree, it was just a simple test. Further investigation may turn up a different result, but until then, I will assume that my results stand.
The 33% reduction was for both statements against the like.
Without thinking much into it, I would suggest one instr per continuous, non wildcard pattern. (i.e. "*123*5*78*" would require 3.)
===============
I tried that, it took ages, I eventually broke it and it was only a quarter of the way through. When I restarted it, it died, taking my project with it.
Author
Commented:Thank you for the idea, but I'll pass. It isn't really worth the effort, since an InStr() isn't good for pattern matching for something equivalent to
strThing Like "*[e-m]?[PTS]*WTF*[1-9][3-
Patterns can be sufficiently sophisticated that I would need to use a RegEx parser instead of the LIKE operator.
All of this InStr() versus LIKE performance discussion isn't important to this article, which has to do with having two flavors (case sensitive/insensitive) of string comparison functions.
View More