この記事でできること
セルや変数の文字列に「特定の文字が含まれているか」を一発で判定したい。あるいは「@マークの位置」を取って、その前後を切り出したい。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と使い分ける

コメント