文字列内の文字をカウントする


たとえば、ある文字列の中に、任意の文字が存在するかどうかは、InStr関数で判定できます。下のコードは、"ABC,DEF"の中に","が存在するかどうかを判定します。

Sub Sample1()
    Dim buf As String
    buf = "ABC,DEF"
    If InStr(buf, ",") > 0 Then
        MsgBox "存在します"
    Else
        MsgBox "存在しません"
    End If
End Sub

InStr関数は、検索する文字列(ここでは",")が何文字目に存在するかを返しますので、InStr関数の結果が0より大きいときは、存在するということです。もし、検索する文字列が複数存在した場合、InStr関数は最初に見つかった位置を数値で返します。

Sub Sample2()
    Dim buf As String, n As Long
    buf = "ABC,DEF,GHI"
    n = InStr(buf, ",")
    If n > 0 Then
        MsgBox n & "文字目に存在します"
    Else
        MsgBox "存在しません"
    End If
End Sub

では、上のようなケースで「","がいくつ存在するか」を調べるにはどうしたらいいでしょう。

これには、いくつかの方法があります。まずは、一番ベタな方法でやってみましょう。左端の1文字目から、1文字ずつチェックする考え方です。

Sub Sample3()
    Dim buf As String, i As Long, cnt As Long
    buf = "ABC,DEF,GHI"
    For i = 1 To Len(buf)
        If Mid(buf, i, 1) = "," Then cnt = cnt + 1
    Next i
    MsgBox cnt & "個あります"
End Sub

次に、InStr関数を使って調べてみましょう。InStr関数の書式は次の通りです。

InStr([start, ]string1, string2[, compare])

引数startは、検索を開始する文字位置を指定します。
検索対象の文字列がstring1で、検索する文字がstring2です。
引数compareには比較モードを指定します。

一般的には、引数string1と引数string2だけを指定して、引数startと引数compareは省略されることが多いです。引数startを省略するということは、検索対象の先頭(1文字目)から探して最初に見つかった位置を返す、ということですから、もし検索対象内に検索する文字が複数存在する場合は、この引数startを動的に変化させることですべての検索文字を調べることができます。

Sub Sample3()
    Dim buf As String, n As Long, cnt As Long
    buf = "ABC,DEF,GHI"
    Do
        n = InStr(n + 1, buf, ",")
        If n = 0 Then
            Exit Do
        Else
            cnt = cnt + 1
        End If
    Loop
    MsgBox cnt & "個あります"
End Sub

こうした判定を何度も繰り返す場合は、Functionプロシージャとして作成しておくと便利ですね。次のコードは、指定した文字列(ここでは"田中 亨")の中に存在する半角スペースの数を数えて、スペースが1つのときだけ処理をします。

Sub Sample4()
    Dim buf As String
    buf = "田中 亨"
    Select Case StrCount(buf, " ")
    Case 0
        MsgBox "半角スペースがありません"
    Case 1
        Debug.Print Split(buf, " ")(0)
    Case Else
        MsgBox "半角スペースが2つ以上あります"
    End Select
End Sub

Function StrCount(Source As String, Target As String) As Long
    Dim n As Long, cnt As Long
    Do
        n = InStr(n + 1, Source, Target)
        If n = 0 Then
            Exit Do
        Else
            cnt = cnt + 1
        End If
    Loop
    StrCount = cnt
End Function

ほかにも方法があります。

"ABC,DEF,GHI"の中に","が、いくつあるかを調べるということは、次のように考えられます。

"ABC,DEF,GHI"は、全部で11文字です。ここから","をすべて消し去った"ABCDEFGHI"は9文字です。","の個数は、11 - 9で2個と分かります。つまり、元の文字数から、数えたい文字を消した文字数を引いた結果が答えだということです。

Sub Sample4()
    Dim buf As String, cnt As Long
    buf = "ABC,DEF,GHI"
    cnt = Len(buf) - Len(Replace(buf, ",", ""))
    MsgBox cnt & "個あります"
End Sub

最後は、配列を使う方法です。たとえば"ABC,DEF,GHI"を","で区切ると

ABC
DEF
GHI

という3つの要素に分割できます。","で区切ったら、要素が3つになったのですから、","の数は「要素数 - 1」ですね。

こうした処理をしてくれるのがSplit関数です。検索対象の文字列を、検索文字で分割した結果、いくつの要素に分割されたかを調べれば、結果的に、検索文字がいくつ存在したかがわかります。Split関数は結果を配列で返します。配列にいくつの要素があるかは、UBound関数で分かります。

Split関数が返す配列は、最初の要素が「0」です。

0:ABC
1:DEF
2:GHI

UBound関数は、指定した配列の最も大きい要素番号を返します。上記でしたら「2」ですね。本来であれば「要素の数 - 1」を計算するのですが、VBAで配列の要素数を調べるのはUBound関数で、UBound関数が最も大きい要素番号を返し、配列の要素番号が0から始まっているのですから、検索文字の個数は、UBound関数の結果と同じになります。

Sub Sample5()
    Dim buf As String
    buf = "ABC,DEF,GHI"
    MsgBox UBound(Split(buf, ",")) & "個あります"
End Sub