【VBA】InStr関数で文字列を検索する方法|文字位置・有無判定・大文字小文字(コピペOK)

スポンサーリンク
スポンサーリンク

この記事でできること

セルや変数の文字列に「特定の文字が含まれているか」を一発で判定したい。あるいは「@マークの位置」を取って、その前後を切り出したい。VBAではInStr関数を使えば、わずか1行でこの2つを実現できる。本記事ではコピペでそのまま動くサンプルを使い、業務でつまずきやすい「戻り値0の判定ミス」「右から検索したいときのInStrRev」「Like・Replaceとの使い分け」までを実用本位で解説する。

これからVBAを学び始める方はVBA入門ロードマップもあわせてどうぞ。

3秒で分かる結論

InStrは「対象文字列の中に検索文字が見つかった位置」を返す。見つからなければ0。判定するときは> 0を必ず付けるのが安全。

If InStr(対象文字列, 検索文字) > 0 Then
    ' 含まれていたときの処理
End If

業務サンプル①:メールアドレスから「@より前」を抽出する

顧客名簿のA列に並んだメールアドレスから、ローカル部(@より前)だけB列に取り出したいケース。たとえば「tanaka@example.com」→「tanaka」を抜き出す。

Sub ExtractLocalPart()
    Dim i As Long
    Dim lastRow As Long
    Dim atPos As Long
    Dim addr As String

    lastRow = Cells(Rows.Count, 1).End(xlUp).Row
    For i = 2 To lastRow
        addr = Cells(i, 1).Value
        atPos = InStr(addr, "@")
        If atPos > 0 Then
            Cells(i, 2).Value = Left(addr, atPos - 1)
        Else
            Cells(i, 2).Value = "(無効)"
        End If
    Next i
End Sub

ポイントはatPos > 0の判定。@がない不正な行を弾けるので、この後の処理が落ちなくなる。応用として「@より前を宛先キーにしてOutlookへ自動送信」も可能。詳細はExcelからOutlookメールを自動作成する方法を参照。

業務サンプル②:ファイルパスから拡張子と親フォルダを取り出す

「C:\Users\name\report.xlsx」のような絶対パスから、拡張子・ファイル名・親フォルダの3要素を取り出す。「右から検索したい」シーンなのでここではInStrRevを使う。

Sub SplitFilePath()
    Dim path As String
    Dim dotPos As Long
    Dim slashPos As Long

    path = "C:\Users\name\Documents\report.xlsx"

    ' 最後のドット位置 (拡張子の境目)
    dotPos = InStrRev(path, ".")
    ' 最後のバックスラッシュ位置 (フォルダの境目)
    slashPos = InStrRev(path, "\")

    Debug.Print "親フォルダ: " & Left(path, slashPos - 1)
    Debug.Print "ファイル名: " & Mid(path, slashPos + 1, dotPos - slashPos - 1)
    Debug.Print "拡張子   : " & Mid(path, dotPos + 1)
End Sub

結果は「親フォルダ: C:\Users\name\Documents」「ファイル名: report」「拡張子: xlsx」となる。サブフォルダ再帰検索でファイル一覧を取得する方法と組み合わせれば、フォルダ構造から特定の拡張子だけを抽出する処理が短時間で書ける。

引数の早見表

InStrの引数は最大4つ。省略可能な部分が多いので混乱しやすい。下表でまとめて把握してほしい。

引数 意味 省略時の値
start 検索を開始する位置(先頭=1) 1(先頭から)
string1 検索される側の文字列 必須
string2 検索する文字列 必須
compare 比較モード(vbBinaryCompare / vbTextCompare) vbBinaryCompare(大小区別あり)

注意:startを指定するときはcompareも指定する必要がある。逆に、compareだけを指定したいときはstartに1を入れてInStr(1, s, t, vbTextCompare)と書く。

ハマりやすい罠:戻り値0を「> 0」で判定すること

InStrの戻り値は「見つかったら位置(1以上)、見つからなければ0」。VBAでは0はFalseと評価されるので、技術的にはIf InStr(s, t) Thenでも動いてしまう。だがこれは避けたい

悪い例(意図が読み取りにくい)

If InStr(addr, "@") Then
    ' "見つかったら処理する"つもりだが、
    ' 「数値の真偽判定なのか、位置を使いたいのか」が読み手に伝わらない
End If

良い例(意図が一目で分かる)

If InStr(addr, "@") > 0 Then
    ' "@が見つかった場合"だと一目瞭然
End If

後でコードを見返したとき、自分自身も他人も「あ、ここは含むかどうか判定してるんだな」とすぐ分かる。習慣として常に> 0を付けておくのが、メンテナンスしやすいコードへの第一歩だ。

InStrRev:右から検索したいとき

InStrは左から検索する。逆に「最後に出てくる位置」を取りたいときはInStrRev関数を使う。引数の順序が少し異なる点に注意。

Dim s As String
s = "C:\Users\Documents\report.xlsx"

Debug.Print InStr(s, "\")      ' → 3(最初の \ の位置)
Debug.Print InStrRev(s, "\")   ' → 19(最後の \ の位置)

パス処理・URL解析・拡張子抽出など「区切り文字の最後の位置」が知りたいシーンで頻出する。

大文字と小文字を区別したくないとき

InStrはデフォルトで大小を区別する(vbBinaryCompare)。「Abc」と「abc」は別物として扱われる。区別したくないときは第4引数にvbTextCompareを指定する(このとき第1引数startに1を入れる必要がある)。

Debug.Print InStr("Hello", "hello")                      ' → 0(区別あり)
Debug.Print InStr(1, "Hello", "hello", vbTextCompare)    ' → 1(区別なし)

顧客名やキーワード検索など、大小を意識しなくていいケースで重宝する。

InStr vs Like vs Replace 使い分け早見表

「文字列を扱う関数」は複数あって混乱しがち。やりたいことで早見表を用意した。

やりたいこと 使う関数 備考
含まれているか判定したい InStr (> 0) 位置も同時に分かる
パターンで判定したい(例: 数字3桁+任意の文字) Like演算子 ワイルドカード可。位置は取れない
含まれている文字を別の文字に置き換えたい Replace関数 判定不要、変換だけする
位置を使って一部を切り出したい InStr + Left/Mid/Right 本記事の業務サンプル①②
区切り文字で分割したい Split関数 結果は配列で返る

置換だけで足りるならセルの文字列を一括置換する方法が、区切り文字で分けたいなら文字列を区切り文字で分割して取り出す方法が効率的。

同じ文字が複数回出てくるときの全位置取得

InStrは「最初に見つかった位置」しか返さない。「すべての出現位置」を取りたいときは、Do Loopで前回の位置を引き継ぎながら繰り返す。

Sub FindAllPositions()
    Dim s As String
    Dim t As String
    Dim startPos As Long
    Dim foundPos As Long

    s = "apple,orange,banana,grape"
    t = ","
    startPos = 1

    Do
        foundPos = InStr(startPos, s, t)
        If foundPos = 0 Then Exit Do
        Debug.Print foundPos
        startPos = foundPos + 1
    Loop
End Sub

結果は6・13・20の3つの位置が出力される。なお区切り文字での分割ならSplit関数のほうが圧倒的にシンプルなので、用途に応じて選ぶといい。

FAQ

セルの値が数値のとき、InStrは使える?

InStrは文字列専用なので、セルの値が数値の場合はCStrで明示的に文字列に変換しておくと安全。詳しくは文字列⇔数値の型変換で計算エラーを防ぐ方法を参照。

空文字列を検索するとどうなる?

InStrの第3引数(検索文字)に空文字列””を渡すと、startで指定した位置(省略時は1)が返る。意図しない挙動になりやすいので、検索文字が空でないかは事前にチェックすると安全。

If Len(searchText) = 0 Then Exit Sub
foundPos = InStr(targetText, searchText)

含むセルをハイライトしたい

「特定の文字を含むセルを見つけて色付けする」業務直結サンプルは特定の文字を含むセルを検索してハイライトする方法に詳細がある。

ワイルドカードで判定したい

「先頭が”VB”で末尾が”A”」のようなパターン判定はLike演算子の出番。If addr Like "VB*A" Thenのように書ける。InStrよりも柔軟だが、位置は返さない。

まとめ

  • 含む判定はIf InStr(s, t) > 0 Thenが定石。> 0を省略しないのが鉄則
  • 右から検索したいときはInStrRev。パス解析・拡張子抽出に必須
  • 大小を無視したいときはInStr(1, s, t, vbTextCompare)
  • パターン判定はLike、置換はReplace、分割はSplitと使い分ける

関連記事

コメント

タイトルとURLをコピーしました