【この記事について】本記事に載せた VBA のコードは、2026年11月5日に Microsoft 365 の Excel(Windows デスクトップ版)ですべて実際に実行し、結果を確かめたものです。構文の説明は Microsoft Learn の公式リファレンス(記事末尾に出典)に沿っています。マクロは元に戻せない変更をすることがあります。会社のファイルで試す前に、必ずコピーを取ってから実行してください。マクロの利用が会社のルールで制限されている場合は、そちらに従ってください。本記事の内容の利用は、ご自身の判断と責任でお願いします。
対象環境:Windows 11 / Microsoft 365 の Excel(デスクトップ版・バージョン 16.0 ビルド 20527)。2026年11月5日に全コードの動作を確認。難易度:VBA 入門(マクロを1回でも貼り付けて動かしたことがある人向け)。
VBA で文字列を検索するなら、まずは InStr 関数です。InStr(調べる文字列, 探す文字) が0より大きければ「含む」、0なら「含まない」。後ろから探すなら InStrRev、「〇〇で始まる」「数字3桁」のような形で判定するなら Like 演算子、シートの中から探すセルを見つけるなら Range.Find を使います。この記事では、4つの使い分けを、実機の Excel で動かして確かめたコードで整理します。

この記事は「VBA のコードで探す」話です。Excel の画面で Ctrl+F を押しても見つからない、というときは、こちらで原因別に直し方をまとめています。

🔎 あわせて確認されている記事
まず結論|VBA の文字列検索4つの早見表
| やりたいこと | 使うもの | 返ってくるもの |
|---|---|---|
| 文字列に「〇〇」が含まれるか・何文字目にあるか | InStr | 見つかった位置(数値)。無ければ 0 |
| 最後に出てくる位置(パスからファイル名を取り出す等) | InStrRev | 後ろから探して最初に見つかった位置(数え方は先頭から) |
| 「〇〇を含む」「英字1文字+数字3桁」のような形で判定 | Like 演算子 | True/False |
| シートの中で探す文字が入ったセルを見つける | Range.Find(続きは FindNext) | 見つかったセル。無ければ Nothing |
この記事のコードを試すための準備
- Excel で新しいブックを開き、Alt+F11 で VBE(マクロを書く画面)を開く
- メニューの[挿入]→[標準モジュール]を選ぶ
- コードを貼り付け、Ctrl+G でイミディエイト ウィンドウを表示しておく(
Debug.Printの結果がここに出ます) - カーソルを Sub の中に置いて F5 で実行する
InStr|「含む」かどうかと、その位置を調べる
InStr は、文字列の中から探す文字を見つけて、それが何文字目から始まるかを返します。見つからなければ 0 です。日本語も1文字ずつ数えます。
Sub InStrBasic()
Dim s As String
s = "東京都千代田区丸の内1-1"
Debug.Print InStr(s, "千代田") ' → 4(4文字目から見つかった)
Debug.Print InStr(s, "大阪") ' → 0(見つからない)
End Sub
実行すると、イミディエイト ウィンドウに 4 と 0 が表示されました。
「含む」の判定は「0より大きいか」で書く
実務でいちばん使うのはこの形です。位置そのものは使わず、0かどうかだけを見るのがコツです。
Sub InStrContains()
Dim s As String
s = "株式会社サンプル 御中"
If InStr(s, "御中") > 0 Then
Debug.Print "「御中」が含まれています"
Else
Debug.Print "含まれていません"
End If
End Sub
実行結果は「「御中」が含まれています」でした。逆に「含まない」を判定したいときは If InStr(s, "御中") = 0 Then と書きます。
大文字・小文字、全角・半角を区別しないで探す
InStr は、そのままだと大文字と小文字を区別します。区別したくないときは、1つ目に開始位置、4つ目に vbTextCompare を指定します。4つ目を書くときは、1つ目の開始位置を省略できません。
Sub InStrIgnoreCase()
Dim s As String
s = "Excel VBA 研修"
Debug.Print InStr(1, s, "vba") ' → 0(大文字小文字を区別)
Debug.Print InStr(1, s, "vba", vbTextCompare) ' → 7(区別しない)
End Sub
実機では、vbTextCompare を付けると、全角の「VBA研修」から半角の “vba” を探しても 1(見つかった)が返りました。付けない場合は 0 でした。社内の表に全角と半角が混ざっているときは、vbTextCompare を付けておくと取りこぼしが減ります。
2つ目以降を探す|開始位置をずらす
InStr の1つ目の引数に探し始める位置を渡せます。1つ目に見つかった位置の「次の文字」から探し直せば、2つ目が見つかります。
Sub InStrSecond()
Dim s As String, p1 As Long, p2 As Long
s = "2026-11-05"
p1 = InStr(s, "-") ' 1つ目の「-」
p2 = InStr(p1 + 1, s, "-") ' 1つ目の次の文字から探す
Debug.Print p1, p2 ' → 5 8
Debug.Print Mid(s, p1 + 1, p2 - p1 - 1) ' → 11(月)
End Sub
実行結果は 5 8 と 11 でした。日付の文字列から「月」の部分だけを取り出す、といった使い方ができます。
InStrRev|後ろから探して、ファイル名や拡張子を取り出す
InStrRev は、文字列の後ろから探します。返ってくる位置は、InStr と同じく先頭から数えた位置です。フォルダーの区切り「\」は何個あるか分かりませんが、最後の「\」の後ろがファイル名なので、InStrRev がぴったりです。
Sub InStrRevFileName()
Dim p As String
p = "C:\Users\sato\Documents\見積書_2026.xlsx"
Debug.Print InStrRev(p, "\") ' → 24(最後の「\」の位置)
Debug.Print Mid(p, InStrRev(p, "\") + 1) ' → 見積書_2026.xlsx
Debug.Print Left(p, InStrRev(p, ".") - 1) ' 拡張子を除いた部分
End Sub
実行結果は 24、見積書_2026.xlsx、C:\Users\sato\Documents\見積書_2026 でした。Mid 関数は「〇文字目から最後まで」を、Left 関数は「先頭から〇文字」を取り出します。
何回出てくるかを数える|Replace との組み合わせ
VBA には「文字が何回出てくるか」を直接数える関数がありません。探す文字を消した長さとの差を、探す文字の長さで割ると数になります。
Sub CountWord()
Dim s As String, w As String, n As Long
s = "請求書、見積書、請求書(再発行)、納品書"
w = "請求"
n = (Len(s) - Len(Replace(s, w, ""))) / Len(w)
Debug.Print n ' → 2
End Sub
実行結果は 2 でした(「請求書」と「請求書(再発行)」の2回)。
Like|「〇〇を含む」「数字3桁」のような形で判定する
Like 演算子は、ワイルドカードを使って文字列の形を判定し、True か False を返します。
| 記号 | 意味 | 例 |
|---|---|---|
* |
0文字以上の何か | "*株式会社*"=「株式会社」を含む |
? |
任意の1文字 | "第?回"=「第1回」「第A回」など |
# |
数字1文字 | "###"=数字3桁 |
[A-Z] |
括弧内の範囲の1文字 | "[A-Z]-###"=英大文字1つ+「-」+数字3桁 |
Sub LikeSample()
Debug.Print "見積書_株式会社サンプル" Like "*株式会社*" ' → True
Debug.Print "A-123" Like "[A-Z]-###" ' → True
Debug.Print "A-12X" Like "[A-Z]-###" ' → False
End Sub
実行結果は True・True・False でした。商品コードや社員番号の書式チェックに便利です。「含むかどうか」だけなら InStr でも Like でも同じことができるので、読みやすいほうを選んでかまいません。
セルを1つずつ調べて、含む行に印を付ける
InStr は、ループと組み合わせると力を発揮します。A列に「請求」を含む行があれば、B列に「対象」と書き込む例です。
Sub MarkRows()
Dim ws As Worksheet, i As Long, lastRow As Long
Set ws = ActiveSheet
lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
For i = 2 To lastRow
If InStr(ws.Cells(i, "A").Value, "請求") > 0 Then
ws.Cells(i, "B").Value = "対象"
Else
ws.Cells(i, "B").ClearContents
End If
Next i
End Sub
A2:A7 に「請求書_10月分」「見積書_株式会社サンプル」「請求書(再発行)」「納品書」「ご請求のお知らせ」「VBA研修の案内」を入れて実行すると、「請求」を含む3行(2・4・6行目)だけに「対象」が入りました。最終行の取り方とループの書き方は、こちらで詳しく扱っています。

Range.Find|シートの中から探す文字が入ったセルを見つける
行数が多い表で「どのセルにあるか」を知りたいときは、Ctrl+F と同じ働きの Range.Find が速くて確実です。見つからないと Nothing が返るので、必ず先に Nothing かどうかを確かめます。
Sub FindAllCells()
Dim ws As Worksheet, c As Range, firstAddress As String
Set ws = ActiveSheet
Set c = ws.Range("A:A").Find(What:="請求", LookIn:=xlValues, _
LookAt:=xlPart, MatchCase:=False, MatchByte:=False)
If c Is Nothing Then
MsgBox "見つかりませんでした"
Exit Sub
End If
firstAddress = c.Address
Do
Debug.Print c.Address, c.Value
Set c = ws.Range("A:A").FindNext(c)
Loop While c.Address <> firstAddress
End Sub
上と同じ表で実行すると、$A$2・$A$4・$A$6 の3つが、値と一緒に表示されました。表を空にして実行すると「見つかりませんでした」と表示されました。FindNext は最初のセルに戻ってくるまで探し続けるので、最初に見つかったアドレスを覚えておき、そこに戻ったら止めるのが決まった書き方です。
Find の引数は毎回すべて書く
Microsoft Learn によると、LookIn・LookAt・SearchOrder・MatchByte の設定は、Find を使うたびに保存され、省略すると前回の値が使われます。しかも、この設定はCtrl+F の[検索]ダイアログと共有されています。前に誰かが「完全一致」で検索していると、コードが同じでも結果が変わります。だから上の例では、引数を全部書いています。
| 引数 | 指定する値 | 意味 |
|---|---|---|
| LookIn | xlValues | 表示されている値で探す(xlFormulas だと数式で探す) |
| LookAt | xlPart / xlWhole | 一部が一致(含む)/セル全体が一致 |
| MatchCase | False | 大文字・小文字を区別しない |
| MatchByte | False | 全角・半角を区別しない(日本語版 Excel 用の引数) |
実機では、MatchByte:=False で “VBA” を探すと全角の「VBA研修の案内」($A$7)が見つかり、MatchByte:=True では見つかりませんでした。
セル全体が一致するものだけを探す
Sub FindWhole()
Dim c As Range
Set c = ActiveSheet.Range("A:A").Find(What:="納品書", LookIn:=xlValues, LookAt:=xlWhole)
If c Is Nothing Then
Debug.Print "見つかりませんでした"
Else
Debug.Print c.Address ' → $A$5
End If
End Sub
実行結果は $A$5 でした。LookAt:=xlWhole にすると、「納品書」とだけ書かれたセルを探し、「納品書(控え)」のようなセルは対象外になります。
よくあるつまずき
Find の結果をそのまま使うと「実行時エラー91」で止まる
見つからなかったときの Nothing に対して c.Address などを使うと、実行時エラー91(オブジェクト変数または With ブロック変数が設定されていません)で止まります。If c Is Nothing Then の確認を飛ばさないでください。

InStr の引数の順番を逆にしている
InStr は「調べる文字列」が先、「探す文字」が後です。逆に書いてもエラーにならず、0が返るだけなので気付きにくいミスです(実機で InStr("御中", "株式会社サンプル 御中") は 0 でした)。結果がいつも0のときは、まず順番を確かめてください。
探す文字が空のとき
探す文字が空文字("")だと、InStr は開始位置(通常は1)を返しました。セルの値を探す文字に使うときは、空のセルだと「含む」と判定されてしまうので、先に If 探す文字 <> "" Then で除いておくと安全です。
よくある質問
Q. InStr と Like は、どちらを使えばいいですか?
「含むかどうか」だけなら、どちらでも同じ結果になります。位置が必要なら InStr、「数字3桁」のような形を判定したいなら Like と覚えておけば迷いません。
Q. ワークシート関数の SEARCH や FIND は VBA で使えますか?
WorksheetFunction 経由で呼べます。ただ、実機で WorksheetFunction.Search("大阪", "東京都千代田区") を試すと、見つからないときは実行時エラー1004(WorksheetFunction クラスの Search プロパティを取得できません)で止まりました。VBA の中では、見つからないと 0 を返す InStr を使うのが素直です。
Q. 大量の行を InStr で調べると遅いです。
セルを1つずつ読む回数が多いと遅くなります。何万行もあるなら、範囲をまとめて配列に読み込んでから InStr で調べると速くなります。配列の使い方は、こちらで実測つきで説明しています。

まとめ|「含む」は InStr > 0 から始める
- 含むか・何文字目か → InStr(0なら見つからない)
- 大文字小文字・全角半角を区別しない → InStr(1, 文字列, 探す文字, vbTextCompare)
- 後ろから探す・ファイル名を取り出す → InStrRev
- 形で判定する(コードの書式チェックなど) → Like
- シートの中のセルを探す → Range.Find。Nothing の確認と、引数を全部書くことを忘れない
文字列の検索ができるようになると、「目で探して印を付ける」作業が、ボタン1つで終わる作業に変わります。まずは今日の表で、InStr の例を1つ動かしてみてください。0以外の数字が返ってきたら、それがあなたの最初の自動化です。
次に読む


参考にした一次情報(2026年11月5日 確認)
InStr 関数|Microsoft Learn
https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/instr-function
InStrRev 関数|Microsoft Learn
https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/instrrev-function
Like 演算子|Microsoft Learn
https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/like-operator
Range.Find メソッド (Excel)|Microsoft Learn
https://learn.microsoft.com/ja-jp/office/vba/api/excel.range.find
Range.FindNext メソッド (Excel)|Microsoft Learn
https://learn.microsoft.com/ja-jp/office/vba/api/excel.range.findnext


コメント