instr function with wildcard

R

richardconers

I'd like to find a three digit number within a string. It would be
much (much) better if it's possible to do this using INSTR rather than
Find.
ex: mystring = "abcdef789gh"
anumber = instr(1, mystring , whatever)
What should whatever equal to find digits in mystring ?
Thank you!
 
J

Jonathan West

I'd like to find a three digit number within a string. It would be
much (much) better if it's possible to do this using INSTR rather than
Find.
ex: mystring = "abcdef789gh"
anumber = instr(1, mystring , whatever)
What should whatever equal to find digits in mystring ?
Thank you!

Instr can't do this.

You can use the Like operator to find out whether there is a 3-digit number
embedded in the string, but not where it is
 
H

Helmut Weber

Hi Richard,
IMHO I think the first step is showing,
that a solution is possible. The next step,
which is up to you, would be, to find the best solution.
Sub Findfirst3Digits()
Dim s As String
Dim i As Integer
s = "abcdef444gh1"
Dim f As Boolean ' found
f = False
For i = 1 To Len(s) - 2
If IsNumeric(Mid(s, i, 1)) And _
IsNumeric(Mid(s, i, 2)) And _
IsNumeric(Mid(s, i, 3)) Then
f = True
Exit For
End If
Next
If f Then
MsgBox "3 digits found at position " & i
Else
MsgBox "no 3 digits found"
End If
End Sub
---
Greetings from Bavaria, Germany
Helmut Weber, MVP
"red.sys" & chr(64) & "t-online.de"
Word XP, Win 98
http://word.mvps.org/
 
A

Andi Mayer

For i = 1 To Len(s) - 2
If IsNumeric(Mid(s, i, 1)) And _
IsNumeric(Mid(s, i, 2)) And _
IsNumeric(Mid(s, i, 3)) Then
f = True
Exit For
End If
Next

Hmmmm,
the IsNumeric(Mid(s, i, 3)) is enaugh

or do I miss something?

If you expect an answer to a personal mail, add the word "manfred" to the first 10 lines in the message
MW
 
J

Jonathan West

Helmut Weber said:
Hi Richard,
IMHO I think the first step is showing,
that a solution is possible. The next step,
which is up to you, would be, to find the best solution.
Sub Findfirst3Digits()
Dim s As String
Dim i As Integer
s = "abcdef444gh1"
Dim f As Boolean ' found
f = False
For i = 1 To Len(s) - 2
If IsNumeric(Mid(s, i, 1)) And _
IsNumeric(Mid(s, i, 2)) And _
IsNumeric(Mid(s, i, 3)) Then
f = True
Exit For
End If
Next
If f Then
MsgBox "3 digits found at position " & i
Else
MsgBox "no 3 digits found"
End If
End Sub

This offers the opportunity for an interesting little exercise in
optimisation :)

If you are looking for 3 consecutive digits, then you only need initially to
check every 3rd character, because if that character is not numeric, it
can't be part of a 3-digit number, and so a 3-digit number cannot be
starting either at that point or the two previous characters.

Therefore, the algorithm could be significantly speeded up as follows.

Sub Findfirst3Digits()
Dim s As String
Dim i As Integer
Dim j As Integer

s = "abcdgfef444gh1"
j = 0
For i = 3 To Len(s) Step 3
If IsNumeric(Mid$(s, i, 1)) Then
' found a digit

If IsNumeric(Mid$(s, i - 1, 1)) Then
' char before is also a digit

If IsNumeric(Mid$(s, i - 2, 1)) Then
' 2 chars before also a digit

j = i - 2
Exit For
' found 3 digit number starting at i-2

ElseIf IsNumeric(Mid$(s, i - 1, 3)) Then
j = i - 1
Exit For
' found 3 digit number starting at i-1

End If
ElseIf IsNumeric(Mid$(s, i, 3)) Then
j = i
Exit For
' found 3 digit number starting at i

End If
End If
Next i
If j > 0 Then
MsgBox "3 digits found at position " & j
Else
MsgBox "no 3 digits found"
End If
End Sub
 
H

Helmut Weber

Hi Andi,
"1.0", eg. would return true. Also "1,0"
with my german version, may be with an english version, too.
Which is not desired her, as I understood Richard.
I think, Richard is looking for a 3 digit string.
---
Greetings from Bavaria, Germany
Helmut Weber, MVP
"red.sys" & chr(64) & "t-online.de"
Word XP, Win 98
http://word.mvps.org/
 
H

Helmut Weber

Hi Jonathan,
I wonder, as I am not too familiar with "like",
whether one coudn't utilize "like", like ;-)
Dim s As String
s = "aret274scg"
If Mid(s, 5, 3) Like "###" Then
MsgBox "found"
End If
---
Greetings from Bavaria, Germany
Helmut Weber, MVP
"red.sys" & chr(64) & "t-online.de"
Word XP, Win 98
http://word.mvps.org/
 
A

Andi Mayer

Hi Andi,
"1.0", eg. would return true. Also "1,0"
with my german version, may be with an english version, too.

you are right, forgot that [+],[-],[.],[,] and E and H is numeric

If you expect an answer to a personal mail, add the word "manfred" to the first 10 lines in the message
MW
 
J

Jonathan West

Helmut Weber said:
Hi Jonathan,
I wonder, as I am not too familiar with "like",
whether one coudn't utilize "like", like ;-)
Dim s As String
s = "aret274scg"
If Mid(s, 5, 3) Like "###" Then
MsgBox "found"
End If

Using Like in this manner is better than using IsNumeric, because as you
pointed out, IsNumeric would return True for a string such as "1.0"

This can be combined with the idea of checking every 3rd character. We can
also make a function out of it, which returns the character position of the
3-digit number, or zero if no number is found. Finally, it can be extended
to include an optional starting position parameter. The function would then
look like this

Function FindFirst3Digits(strIn As String, _
Optional ByVal iStart As Long = 1) As Long

Dim i As Long
Dim j As Long

If iStart < 1 Then
iStart = 1
End If

j = 0
For i = iStart + 2 To Len(strIn) Step 3
If Mid$(strIn, i, 1) Like "#" Then
' found a digit

If Mid$(strIn, i - 1, 1) Like "#" Then
' char before is also a digit

If Mid$(strIn, i - 2, 1) Like "#" Then
' 2 chars before also a digit

j = i - 2
Exit For
' found 3 digit number starting at i-2

ElseIf Mid$(strIn, i - 1, 3) Like "###" Then
j = i - 1
Exit For
' found 3 digit number starting at i-1

End If
ElseIf Mid$(strIn, i, 3) Like "###" Then
j = i
Exit For
' found 3 digit number starting at i

End If
End If
Next i
FindFirst3Digits = j
End Function

If you simply check each character position in turn for the presence of a
3-digit string, you get code that is simpler, but much slower

Function FindFirst3DigitsAlt(strIn As String, _
Optional ByVal iStart As Long = 1) As Long
Dim i As Long
If iStart < 1 Then
iStart = 1
End If

For i = iStart To Len(strIn) - 3
If Mid$(strIn, i, 3) Like "###" Then
Exit For
' found 3 digit number starting at i

End If
Next i
FindFirst3DigitsAlt = i
End Function


You can easily check the relative timings of these two versions of the
function with the following code, which should be placed in a separate
module

Public Declare Function GetTickCount Lib "kernel32" () As Long

Sub TimeFunctions()
Dim tStart As Long
Dim tEnd As Long
Dim strIn As String
Dim iCount As Long

strIn = Space$(5000000) & "123"

tStart = GetTickCount
iCount = FindFirst3Digits(strIn)
tEnd = GetTickCount - tStart
Debug.Print "FindFirst3Digits", iCount, tEnd

tStart = GetTickCount
iCount = FindFirst3DigitsAlt(strIn)
tEnd = GetTickCount - tStart
Debug.Print "FindFirst3DigitsAlt", iCount, tEnd

End Sub

This code creates a 5000000 character string and appends "123" to the end.
It then applies both versions of the function to the string and prints the
result in the immediate window. The call to GetTickCount retrieves the value
of a timer that is incremented every millisecond, so the time that is
displayed is the elapsed time in milliseconds. On my test runs,
FindFirst3Digits is almost exactly 3 times faster than FindFirst3DigitsAlt.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top