n番目の位置を調べる


タイトルが分かりにくいですかね。つまり、こういうことです。

こうなっていたとき、じゃ「n番目の"-"は何文字目」にあるのか調べようってことです。文字列の中で、任意の文字の位置を調べるにはInStr関数が便利です。InStr関数は、一般的に次のように使われます。

でも実は、ほかにも引数があって、先頭には次のような引数を指定できます。

引数「開始位置」を指定すると「どこ(何文字目)から探すか」を指定できます。引数「開始位置」は省略できます。普通は省略しますよね。省略すると「1」を指定したと見なされます。一般的に探すときは文字列の先頭(1文字目)から探すことが多いので、省略することが多いわけで。でも上図のような状態で、3文字目から探せば、2つめの"-"の位置が分かるわけです。

まとめてみましょう。

  • 1つめを見つけるとき → 先頭から探す
  • 2つめを見つけるとき → 1つめの位置 + 1文字目から探す
  • 3つめを見つけるとき → 2つめの位置 + 1文字目から探す
  • 4つめを見つけるとき → 3つめの位置 + 1文字目から探す

ちなみに、最初の「先頭から探す」ときは「InStr("…", "・")」のように引数「開始位置」を省略してもいいですし、「InStr(1, "…", "・")」でもいいです。

なので、次のようにしてn番目の位置を調べることができます。

Sub Sample1()
    Dim i As Long, P As Long
    For i = 1 To 3  '' ← 3番目の位置
        P = InStr(P + 1, "A-B-C-D-E", "-")
    Next i
    MsgBox P & "文字目"
End Sub

変数名のPは「Position」のつもりです。関係ないですけど、最近はできるだけ短い変数名を使うのがマイブームですw どうでもいい変数にはどうでもいい名前をつけた方が、逆に重要な変数名が際立ちます。何でもかんでも長いしっかりした名前をつければいいってのも、どうかと思います。個人的な感覚ですけど。

これ、もちろん次のようなケースでも対応できます。

Sub Sample3()
    Dim i As Long, P As Long
    For i = 1 To 4  ''←4番目の位置
        P = InStr(P + 1, "西野-佐々木-桜井-東-松本", "-")
    Next i
    MsgBox P & "文字目"
End Sub

せっかくですから、Functionにしちゃいましょうか。

Sub Sample4()
    Dim buf As String, N As Long
    buf = "西野-佐々木-桜井-東-松本"
    N = InStr2(buf, "-", 3)
    MsgBox Left(buf, N - 1) & vbCrLf & Mid(buf, N + 1)
End Sub

Function InStr2(str1 As String, str2 As String, pos As Long)
    Dim i As Long, P As Long
    For i = 1 To pos
        P = InStr(P + 1, str1, str2)
    Next i
    InStr2 = P
End Function

なお、今回の"西野-佐々木-桜井-東-松本"に"-"は4つしかありません。このときあり得ない5番目のように指定すると、For Nextの最後で見つかりませんから、最後のInStr関数は0を返します。なので、次のようにできます。

まぁ、Functionの方で確認してもいいですけど。

Function InStr2(str1 As String, str2 As String, pos As Long)
    Dim i As Long, P As Long
    If pos > UBound(Split(str1, str2)) Then
        InStr2 = -1
        Exit Function
    End If
    For i = 1 To pos
        P = InStr(P + 1, str1, str2)
    Next i
    InStr2 = P
End Function

でも、本来であれば呼び出し元のマクロ側で、ちゃんと確認すべきでしょうね。