PDA

View Full Version : Indexing characters in a string



Hawkin
11-02-2011, 01:03 PM
Hello there!

From other programming languages I am used to index characters in strings, because they are accessible like arrays.

I want to check a string for characters on specific positions (is the 4th letter an "A", etc).

I can only think of
string2 = Mid(string1, 4, 5)
result = InStr(string2, "A", vbBinaryCompare)
Isn't there an easier method???

TIA,
Hawk

JimmyTheHand
11-02-2011, 01:53 PM
Not much simpler, but maybe:
Dim result As Boolean
result = (Mid(string1, 4, 5) = "A") Jimmy

GTO
11-02-2011, 04:14 PM
...I want to check a string for characters on specific positions (is the 4th letter an "A", etc)...

Hi there,

Apologies if not reading correctly, but if just returning TRUE/FALSE, wouldn't it be:

Sub test()
Dim string1 As String, result As Boolean

string1 = "Coca Cola is good"
result = InStr(1, string1, "a", vbBinaryCompare) = 4
End Sub

Paul_Hossler
11-02-2011, 04:27 PM
Strings can be tricky because you have to deal with Unicode (aka Wide) strings that are 2 bytes, plus probably some other complications, like Upper/Lower Case, etc.

I'd vote for less effecient, but more maintainable code unless it's in a very critical and frequently used part of the program

Was this an acedemic interest question, or are you trying to enhance run time?

You do a function to make it easier to use


Option Explicit
Sub test()
Const s1 As String = "asdfghjkl"

MsgBox IsThisTheLetter(s1, "s", 2)
MsgBox IsThisTheLetter(s1, "a", 2)
MsgBox IsThisTheLetter(s1, "s", 2, True)
MsgBox IsThisTheLetter(s1, "S", 2, True)

End Sub
Function IsThisTheLetter(sSearch As String, sLetter, iPosition As Long, Optional bMatchCase As Boolean = False) As Boolean
If bMatchCase Then
IsThisTheLetter = (Mid(sSearch, iPosition, 1) = Left(sLetter, 1))
Else
IsThisTheLetter = (Mid(UCase(sSearch), iPosition, 1) = Left(UCase(sLetter), 1))
End If
End Function






What you have will work

Paul

Kenneth Hobs
11-02-2011, 08:12 PM
InStr() and InStrRev() are fairly handly. I don't use InStrB().

Regular Expressions are fairly common among the various languages. Here are some test examples. For what it is worth, because code seems long or complicated does not mean that it is less efficient than shorter code. For stack overhead consideration, you are probably better off using built-in VBA functions.

These kinds of things are fun to think about though.

Option Explicit

Sub Test_RegExpTest()
MsgBox RegExpTest("is.", "IS1 is2 IS3 is4"), vbInformation, _
"Case Sensitive Match Position for ""is"" in: IS1 is2 IS3 is4"
MsgBox RegExpTest("R", "Kenneth Ray Hobson"), vbInformation, _
"Case Sensitive Match Position for ""R"" in: Kenneth Ray Hobson"
MsgBox RegExpTest("O", "Kenneth Ray Hobson", False), vbInformation, _
"Case Sensitive Match Position for ""O"" in: Kenneth Ray Hobson"
MsgBox RegExpTest("o", "Kenneth Ray Hobson", False), vbInformation, _
"Case Insensitive Match Position for "":o"" in: Kenneth Ray Hobson"
End Sub

Sub Test_RegExpTestPos1()
MsgBox RegExpTestPos1("is.", "IS1 is2 IS3 is4"), vbInformation, _
"Case Sensitive Match Position for ""is"" in: IS1 is2 IS3 is4"
MsgBox RegExpTestPos1("R", "Kenneth Ray Hobson"), vbInformation, _
"Case Sensitive Match Position for ""R"" in: Kenneth Ray Hobson"
MsgBox RegExpTestPos1("O", "Kenneth Ray Hobson", False), vbInformation, _
"Case Sensitive Match Position for ""O"" in: Kenneth Ray Hobson"
MsgBox RegExpTestPos1("o", "Kenneth Ray Hobson", False), vbInformation, _
"Case Insensitive Match Position for ""o"" in: Kenneth Ray Hobson"
End Sub

Sub Make_VBS_Ref()
On Error Resume Next
'in case ref exists
ActiveWorkbook.VBProject.References.AddFromGuid "{3F4DACA7-160D-11D2-A8E9-00104B365C9F}", 5, 5
End Sub

' Similar to: http://msdn.microsoft.com/en-us/library/yab2dx62%28v=VS.85%29.aspx
' Add by reference by VBE menu: Tools > References... > Microsoft VBScript Regular Expressions 5.5 or run Make_VBS_Ref
Function RegExpTest(patrn As String, strng As String, Optional bCase As Boolean = True) As String
Make_VBS_Ref 'Adds the RegExp reference if needed.
Dim regEx, Match, Matches ' Create variable.
Dim RetStr As String
Set regEx = New RegExp ' Create a regular expression.
regEx.pattern = patrn ' Set pattern.
regEx.IgnoreCase = bCase ' Set case insensitivity.
regEx.Global = True ' Set global applicability.
Set Matches = regEx.Execute(strng) ' Execute search.
For Each Match In Matches ' Iterate Matches collection.
RetStr = RetStr & "Match found at position "
RetStr = RetStr & Match.FirstIndex & ". Match Value is '"
RetStr = RetStr & Match.Value & "'." & vbCrLf
Next Match
RegExpTest = RetStr
End Function

Function RegExpTestPos1(patrn As String, strng As String, Optional bCase As Boolean = True) As Long
Make_VBS_Ref 'Adds the RegExp reference if needed.
Dim regEx, Match, Matches ' Create variable.
Dim RetStr As String
Set regEx = New RegExp ' Create a regular expression.
regEx.pattern = patrn ' Set pattern.
regEx.IgnoreCase = bCase ' Set case insensitivity.
regEx.Global = True ' Set global applicability.
Set Matches = regEx.Execute(strng) ' Execute search.
If Matches.Count > 0 Then
RegExpTestPos1 = Matches(0).FirstIndex
Else: RegExpTestPos1 = -1
End If
End Function

Hawkin
11-03-2011, 05:35 AM
I wanted to split a string into substrings delimited by specific characters using the method I wrote. Today I found out that there exists the function Split(), so the function I wanted to write is already coded :dot:

Thank you for your help!

Aflatoon
11-03-2011, 07:26 AM
Just for information, you can assign a string to a Byte array directly. Note, as Paul said, that characters are double byte (for typical English chars the second byte is 0).

Paul_Hossler
11-03-2011, 09:21 AM
I want to check a string for characters on specific positions (is the 4th letter an "A", etc).


and



I wanted to split a string into substrings delimited by specific characters

seems pretty far apart, but I'm glad you got an answer

Paul