VBAで自動化 VBA一覧 抽出・検索処理 条件一致・行列処理

【VBA】特定の文字を含む行を抽出する方法|InStrで部分一致検索

Excelで大量のデータを扱っていると、「商品名に特定の文字が入っている行だけを探したい」「備考欄に『要確認』と書かれているデータだけを抽出したい」といった作業が発生します。

完全に同じ値を探すのであれば比較演算子による判定でも対応できますが、セル内の一部分に検索文字が含まれているかを調べたい場合は、完全一致とは異なる考え方が必要です。

VBAでは、InStr関数を利用することで文字列の部分一致を判定できます。

たとえば「東京営業所」「東京支店」「東京都内」のように表記が異なるデータでも、「東京」という文字が含まれている行をまとめて見つけることが可能です。

この記事では、特定の文字を含む行をVBAで抽出する方法について、単純に動作するコードだけではなく、検索条件の考え方や実務で変更しやすいコードの組み方まで解説します。

✅ VBAで特定の文字を含む行を抽出する仕組み

特定の文字を含む行を抽出するときに最初に理解しておきたいのが、「完全一致」と「部分一致」は別の判定であるという点です。実務では、この違いを意識せずコードを作成すると、対象になるはずのデータが抽出されないことがあります。

反対に、部分一致の範囲を広げすぎると、本来必要ではない行まで対象になる可能性があります。また、「行を抽出する」といっても、検索するセルと取得する行全体は分けて考える必要があります。検索対象となる列を明確にしておかなければ、データ量が増えたときに処理の意図も分かりにくくなります。まずは部分一致による行抽出がどのような仕組みなのかを整理しておきましょう。

・完全一致ではなくセル内の一部を検索する

たとえば、A列に次のようなデータが入力されているとします。

A列:商品名
東京限定セット
大阪限定セット
東京ギフトセット
名古屋セット
東京キャンペーン商品

ここから「東京」を含む行を探したい場合、

If Cells(rowIndex, 1).Value = "東京" Then

という判定では目的のデータを取得できません。

このコードはセルの値が「東京」と完全に一致しているかを判定しているためです。

「東京限定セット」は「東京」と同じ値ではないため、条件から外れてしまいます。

そこで利用できるのがInStr関数です。

If InStr(Cells(rowIndex, 1).Value, "東京") > 0 Then

InStrは、指定した文字列の中から検索文字を探し、その文字が見つかった位置を返します。

「東京限定セット」で「東京」を検索すると文字列が見つかるため、0より大きな値が返ります。

一方、「大阪限定セット」のように「東京」が存在しない場合は0になります。

そのため、

InStr(検索対象, 検索文字) > 0

という条件を利用することで、「指定した文字が含まれているか」を判定できます。

・検索する列と抽出する行を分けて考える

行抽出を作成するときは、どこを検索するのかとどこまでを取得するのかを分けて考えることが大切です。

たとえば次のような表があるとします。

A列:商品名B列:担当者C列:数量
東京限定セット佐藤10
大阪限定セット鈴木20
東京ギフトセット高橋15

「東京」を検索する対象はA列ですが、必要になるデータは商品名だけとは限りません。

対象になった行の、

  • 商品名
  • 担当者
  • 数量

をひとまとまりのデータとして扱いたいケースも多くあります。

つまり処理の流れは、

  1. A列を上から順番に確認する
  2. セル内に「東京」が含まれているか判定する
  3. 条件に一致した行を抽出対象として扱う

という形になります。

この考え方を最初に整理しておくと、「検索する列を変更したい」「取得する列を増やしたい」といった仕様変更にも対応しやすくなります。


✅ VBAのInStrで特定の文字を含む行を検索する方法

InStrを使えば部分一致検索は比較的簡単に実装できますが、検索文字や対象列をコードの各所へ直接書き込んでしまうと、後から条件を変更するときに修正箇所が増えてしまいます。小さなマクロでは問題にならなくても、実務では検索条件が変更されることは珍しくありません。

また、最終行を固定値にすると、データ件数が増減した際に検索漏れや不要なループが発生します。処理そのものが短いからこそ、「何を変更すれば検索条件を変えられるのか」が分かる構成にしておくことが重要です。ここでは検索文字や対象列を変数として分離し、後から流用しやすい形で部分一致検索を組み立てます。

InStrは行抽出だけでなく、セル内のどの位置に検索文字が存在するかを調べる場合にも利用できます。InStrの戻り値や文字位置の取得方法を詳しく確認したい場合は、「【VBA】(セル内)特定の文字の最初の位置を検索(InStr関数の使用方法)」もあわせて確認してみてください。

・InStrで部分一致した行を判定するコード

次の例では、A列の商品名から「東京」を含む行を検索します。

Sub FindRowsContainingText()

    Dim targetSheet As Worksheet
    Dim searchText As String
    Dim searchColumn As Long
    Dim lastRow As Long
    Dim rowIndex As Long

    Set targetSheet = ThisWorkbook.Worksheets("商品一覧")

    '検索条件をまとめて管理する
    searchText = "東京"
    searchColumn = 1

    '検索対象列の最終行を取得する
    lastRow = targetSheet.Cells(targetSheet.Rows.Count, searchColumn).End(xlUp).Row

    'データ部分を上から順番に確認する
    For rowIndex = 2 To lastRow

        If InStr(1, _
                 CStr(targetSheet.Cells(rowIndex, searchColumn).Value), _
                 searchText, _
                 vbTextCompare) > 0 Then

            Debug.Print "該当行:" & rowIndex

        End If

    Next rowIndex

End Sub

ここでは、検索文字をsearchText、検索対象列をsearchColumnとして分離しています。

たとえば検索対象を「大阪」に変更する場合は、

searchText = "大阪"

と変更するだけです。

また、検索対象をA列からC列へ変更する場合も、

searchColumn = 3

と変更できます。

検索条件を処理本体から切り離しておくことで、「どこを変更すればよいのか」が明確になります。

・最終行を取得して必要なデータだけを検索する

先ほどのコードでは、次の処理で検索対象列の最終行を取得しています。

lastRow = targetSheet.Cells(targetSheet.Rows.Count, searchColumn).End(xlUp).Row

たとえば商品データが500行目まで存在する場合は、2行目から500行目までを検索します。

次のように固定値でループさせることもできます。

For rowIndex = 2 To 10000

しかし、実際のデータが500行しかなければ、残りの9500行も確認することになります。

反対に、データが10000行を超えれば検索漏れが発生します。

データ件数が変化する業務ファイルでは、最終行を取得して処理範囲を決める方が管理しやすくなります。

なお、検索対象列の途中に空白セルが存在していても、End(xlUp)で取得するのは基本的に下側から見つかった最後のデータ位置です。そのため、途中に空白があるだけでループが終了するわけではありません。

・検索結果をすぐ転記せず行番号で確認する理由

この段階では、条件に一致したデータをいきなり別シートへコピーせず、

Debug.Print "該当行:" & rowIndex

として該当する行番号を確認しています。

これは、部分一致の判定と、その後に行う処理を分けて考えるためです。

検索した瞬間に、

Rows(rowIndex).Copy

のような処理を組み込むこともできます。

しかし、検索とコピーを一体化すると、「部分一致の条件が正しいのか」「コピー処理側に問題があるのか」が分かりにくくなる場合があります。

特に業務で使用するマクロでは、最初に検索条件だけを確認し、

  1. 正しい行が見つかっているか
  2. 想定外の行が含まれていないか
  3. 検索対象から漏れているデータがないか

を確認してから、抽出先への書き込み処理を追加した方が安全です。

また、検索処理と後続処理を分けて考えられる構成にしておけば、後から「抽出ではなく色を付けたい」「該当行だけ集計したい」と仕様が変わった場合にも流用しやすくなります。

部分一致検索にはInStr以外にも、Findやループ処理を利用する方法があります。検索対象や後続処理によって適した方法が変わるため、検索方法を比較したい場合は「【VBA】文字列検索を部分一致で行う方法|Find・InStr・ループを使った実務サンプル」も参考になります。


✅ VBAで部分一致検索するときに知っておきたいInStrの判定

InStrは短いコードで部分一致を判定できる便利な関数ですが、単に「0より大きいか」だけを覚えてしまうと、実際のデータで想定外の結果になることがあります。特に注意したいのが、英字を検索するときの大文字・小文字の扱いです。

また、セルには数値やエラー値など、文字列以外のデータが入る可能性もあります。検索条件を増やしていく前に、まず1つの条件をどのルールで比較するのか決めておくことが重要です。ここが曖昧なまま複数条件へ発展させると、どの条件によって抽出されたのか分かりにくくなります。部分一致検索を安定して利用するために、InStrの比較方法を確認しておきましょう。

・大文字と小文字を区別しない部分一致検索

今回のコードでは、InStrを次のように記述しています。

InStr(1, _
      CStr(targetSheet.Cells(rowIndex, searchColumn).Value), _
      searchText, _
      vbTextCompare)

最後のvbTextCompareは、文字列として比較することを指定しています。

たとえば検索文字が、

excel

の場合でも、

Excel
EXCEL
excel

などを大文字・小文字を区別せず検索できます。

商品コードなどで大文字・小文字を厳密に区別する必要がある場合は、vbBinaryCompareを利用する方法もあります。

InStr(1, _
      CStr(targetSheet.Cells(rowIndex, searchColumn).Value), _
      searchText, _
      vbBinaryCompare)

どちらが正しいというわけではなく、扱っているデータによって使い分けます。

一般的な名称や説明文を検索するのであれば、大文字・小文字の表記揺れによる検索漏れを抑えられるvbTextCompareが扱いやすいケースがあります。

一方、コードや識別子など文字の違い自体に意味があるデータでは、比較方法を安易に変更しないことが大切です。

今回のような「特定の文字を含む行」の抽出では、どの文字を含んでいるかだけでなく、どの比較ルールで「含む」と判断するのかまで決めておくことで、後からデータが増えたときにも検索結果を管理しやすくなります。


✅ VBAで特定の文字を含む行を実際に抽出する方法

ここまでの処理で特定の文字を含む行を判定できますが、実務では該当行を見つけるだけではなく、そのデータを一覧として取り出したいケースもあります。ただし、「見つかったらその場で行全体をコピーする」という作り方だけを覚えてしまうと、抽出する列が変わったときやデータ量が増えたときに修正しにくくなります。

また、元シートと抽出先シートを明示していないコードは、別のシートを操作している状態で実行した際に意図しない場所へ書き込む原因になります。部分一致の判定が正しくても、抽出先の管理が曖昧では安全な処理とはいえません。検索処理と書き込み処理の役割を整理しながら、どのデータをどこへ抽出するのかを明確にすることが大切です。

ここでは、前半で使用したInStrの判定を利用して、特定の文字を含む行を抽出する基本形を確認します。

・部分一致した行だけを抽出するコード

次の例では、「商品一覧」シートのA列を検索し、「東京」を含むデータを「抽出結果」シートへ書き出します。

Sub ExtractRowsContainingText()

    Dim sourceSheet As Worksheet
    Dim outputSheet As Worksheet
    Dim searchText As String
    Dim searchColumn As Long
    Dim lastRow As Long
    Dim lastColumn As Long
    Dim outputRow As Long
    Dim rowIndex As Long
    Dim cellValue As Variant

    Set sourceSheet = ThisWorkbook.Worksheets("商品一覧")
    Set outputSheet = ThisWorkbook.Worksheets("抽出結果")

    '検索条件
    searchText = "東京"
    searchColumn = 1

    '検索対象となる最終行と、転記する最終列を取得
    lastRow = sourceSheet.Cells( _
        sourceSheet.Rows.Count, searchColumn).End(xlUp).Row

    lastColumn = sourceSheet.Cells(1, _
        sourceSheet.Columns.Count).End(xlToLeft).Column

    '抽出結果を書き込む開始行
    outputRow = 2

    For rowIndex = 2 To lastRow

        cellValue = sourceSheet.Cells(rowIndex, searchColumn).Value

        'エラー値は検索対象から除外
        If Not IsError(cellValue) Then

            If InStr(1, CStr(cellValue), _
                     searchText, vbTextCompare) > 0 Then

                outputSheet.Cells(outputRow, 1) _
                    .Resize(1, lastColumn).Value = _
                    sourceSheet.Cells(rowIndex, 1) _
                    .Resize(1, lastColumn).Value

                outputRow = outputRow + 1

            End If

        End If

    Next rowIndex

End Sub

このコードでは、条件に一致した行をCopyメソッドでコピーするのではなく、Valueを使って必要な範囲の値を書き出しています。

検索対象のA列に「東京限定セット」が存在すれば、その行にある商品名・担当者・数量などをまとめて「抽出結果」シートへ転記できます。

・CopyではなくValueで抽出している理由

行を抽出するだけであれば、次のように書く方法もあります。

sourceSheet.Rows(rowIndex).Copy _
    Destination:=outputSheet.Rows(outputRow)

短く書けるため便利ですが、行全体をコピーすると、値だけでなく書式なども転記対象になります。

さらに、Excelのワークシートは非常に多くの列を持っているため、必要なデータがA~C列しかないにもかかわらず、Rows(rowIndex)で行全体を対象にする必要はありません。

今回のコードでは、

sourceSheet.Cells(rowIndex, 1) _
    .Resize(1, lastColumn).Value

として、実際に使用している列までを対象にしています。

また、値の抽出だけが目的なら、クリップボードを経由する必要もありません。

実務では「何を抽出したいのか」を明確にし、値だけでよい場合は必要な範囲だけを書き出す方が、後から処理内容を把握しやすくなります。

ただし、セルの色や罫線などの書式まで含めて抽出する必要がある場合は、Copyを使用する方が適しているケースもあります。

目的によって使い分けることが重要です。

今回は「特定の文字を含む」という部分一致を基準に行を抽出しました。文字列の部分一致に限らず、指定した条件を判定して必要なデータだけを別シートへ取り出したい場合は、「【VBA】条件に一致する行だけを別シートへ抽出する方法|データ転記を自動化」も参考になります。


 

✅ VBAで部分一致した行を抽出するときのエラーや空白対策

実際のExcelファイルでは、検索対象列のすべてに正常な文字列が入っているとは限りません。空白セルが混在していることもあれば、数式の結果としてエラー値が表示されている場合もあります。テスト用のきれいなデータだけでコードを作成すると、本番データへ適用した瞬間に処理が停止することがあります。

特にCStrで文字列へ変換すればどの値でも安全に検索できる、と考えてしまうのは注意が必要です。エラー値については通常の文字列や数値とは別に扱う必要があります。

また、空白を検索対象としてどう扱うのかも業務上のルールによって変わります。部分一致検索を実務で使用するなら、正常なデータ以外が存在することも想定しておきましょう。

・エラー値を除外してからInStrで判定する

前述のコードでは、検索対象の値を一度変数へ格納しています。

cellValue = sourceSheet.Cells(rowIndex, searchColumn).Value

その後、

If Not IsError(cellValue) Then

でエラー値ではないことを確認してからInStrを実行しています。

これは、セルに#N/Aや#VALUE!などのエラー値が存在するケースを想定しているためです。

たとえば、

CStr(cellValue)

であらゆるデータを文字列へ変換しようとしても、エラー値まで通常の文字列と同じように扱えるわけではありません。

そのため、

  1. セルの値を取得する
  2. エラー値か確認する
  3. 問題がなければ文字列として検索する
  4. 部分一致した場合だけ抽出する

という順番にしています。

業務データでは、数式や外部データの取得結果によって一時的にエラー値が発生することもあります。

1件のエラー値によって抽出処理全体が停止しないよう、検索前にデータの状態を確認しておくと安全です。

・空白セルは基本的に部分一致しない

検索対象が空白の場合、

InStr(1, "", "東京", vbTextCompare)

の結果は0となるため、「東京」を含む行として抽出されることはありません。

そのため、今回のように特定の文字列を探すだけであれば、空白セルについて必ず個別処理を追加しなければならないわけではありません。

ただし、

「商品名が空白の行は異常データとして記録する」

「検索対象が空白なら別の処理を行う」

といった要件がある場合は、部分一致検索とは別の条件として扱った方が分かりやすくなります。

検索・空白判定・エラー判定を1つの複雑な条件式へ詰め込みすぎると、後から修正するときに判定ルールが把握しにくくなるためです。


✅ VBAのInStrとLikeは部分一致検索でどう使い分けるか

VBAで「文字を含むか」を調べる方法はInStrだけではありません。Like演算子でも部分一致を判定できるため、どちらを使うべきか迷うことがあります。単純な文字列検索であれば、どちらでも同じような結果を得られる場合がありますが、得意とする条件は少し異なります。この違いを理解せずに使い分けると、単純な検索なのに条件式が必要以上に複雑になることがあります。

反対に、パターンを利用したい場面ですべてInStrだけで対応しようとすると、複数の判定を組み合わせる必要が出てきます。実務では「どちらが上位か」ではなく、検索条件を読みやすく表現できる方法を選ぶことが大切です。今回の「特定の文字を含む行」という目的を基準に違いを確認してみましょう。

・単純に文字を含むか調べるならInStrが分かりやすい

InStrでは、次のように記述できます。

If InStr(1, cellValue, searchText, vbTextCompare) > 0 Then

このコードからは、

「cellValueの中にsearchTextが存在するか」

という意図を比較的そのまま読み取れます。

一方、Likeを使うと次のような書き方ができます。

If CStr(cellValue) Like "*東京*" Then

*は任意の文字列を表すため、「東京」の前後に別の文字が存在していても一致します。

したがって、これも部分一致検索として利用できます。

・Likeは文字列パターンを指定したい場合に便利

Likeの特徴は、単純な部分一致だけではなくパターンを指定できることです。

たとえば、

If CStr(cellValue) Like "東京*" Then

とすれば、「東京」から始まる文字列を判定できます。

一方、今回のように、

「セルのどこかに指定した文字が存在するか」

を調べることが目的なら、検索位置を取得でき、比較方法も指定できるInStrは扱いやすい選択肢です。

実務では無理に1つの方法へ統一する必要はありません。

  • 特定文字が含まれるかを検索する → InStr
  • 文字列のパターンで判定する → Like

というように目的を分けると、後からコードを読む人にも処理の意図が伝わりやすくなります。

LikeとInStrはどちらも部分一致の判定に利用できますが、条件分岐として組み込む場合は検索条件の作り方も重要になります。IF文と組み合わせた設計や使い分けについては、「【VBA】文字列の部分一致(IF文)|LikeとInStrで壊れない条件分岐を設計する」で詳しく解説しています。


✅ VBAで特定の文字を含む行を抽出する実務上のポイント

部分一致検索は便利ですが、対象データが増えるほど「検索できるコード」だけでは十分ではなくなります。実務では検索文字の変更、検索列の変更、抽出先の変更など、作成後に仕様が変わる可能性があります。そのたびにループ内部を書き換える設計では、修正漏れや条件の食い違いが起こりやすくなります。

また、数万行規模のデータを扱う場合には、セルを1つずつ読み書きする処理方法自体を見直した方がよいケースもあります。最初から必要以上に複雑なコードへする必要はありませんが、データ量と利用期間に応じて設計を変える視点は重要です。部分一致検索を別の業務へ流用できるよう、最後に実務で意識したいポイントを整理します。

・検索条件はループ処理から分離して管理する

今回のコードでは、

searchText = "東京"
searchColumn = 1

のように検索条件を変数へ格納しています。

これはコードを長くするためではなく、変更する可能性が高い値を見つけやすくするためです。

たとえば後から、

  • 「東京」ではなく「大阪」を検索する
  • A列ではなくD列を検索する
  • 検索結果の出力先を変更する

といった仕様変更が発生しても、変更箇所が明確になります。

さらに検索条件をセルから取得するようにすれば、VBAコードを直接修正せず検索文字を変更する仕組みに発展させることもできます。

・大量データでは配列処理も選択肢になる

今回紹介した方法は、ワークシートを1行ずつ確認するため、処理の流れが理解しやすく、小~中規模のデータでは扱いやすい構成です。

一方、数万行など大量のデータを繰り返し処理する業務では、

  1. 元データを配列へまとめて読み込む
  2. VBA内部でInStrによる判定を行う
  3. 条件に一致したデータを抽出用の配列へ格納する
  4. 最後に結果をワークシートへ一括出力する

という方法もあります。

セルへの読み書きを何度も繰り返さず、VBA内部でデータを処理できるため、大量データでは処理時間を改善できる場合があります。

ただし、データ件数が少ない処理まで配列化するとコードが複雑になり、保守性を下げることもあります。

まずは処理の目的とデータ量を確認し、必要になった段階で配列処理へ変更するのが現実的です。

実務では「東京を含み、なおかつ数量が一定以上」のように、複数の条件を組み合わせて抽出したいケースもあります。1つの検索条件からAND・ORによる判定へ発展させたい場合は、「【VBA】複数条件に一致する行を抽出する方法|AND・OR条件でデータを判定」もあわせて確認してみてください。


 

✅ まとめ:VBAで特定の文字を含む行を部分一致で抽出しよう

VBAで特定の文字を含む行を抽出するときは、単純に行をコピーする処理から考えるのではなく、どの列から、どの文字を、どの比較方法で検索するのかを最初に整理することが重要です。特に完全一致と部分一致を混同すると、本来対象になるデータを取得できない原因になります。InStrを利用すれば、セル内の任意の位置に検索文字が存在するかを判定できます。

一方で、実際の業務データには空白やエラー値が含まれる可能性があるため、正常な文字列だけを前提にしないことも大切です。また、検索条件と抽出処理を分けて設計しておけば、検索文字や対象列が変わった場合にも修正しやすくなります。まずは基本的な部分一致検索を正しく作り、データ量や業務要件に応じて抽出方法を発展させていきましょう。

  • InStrを使うと、セル内に特定の文字が含まれているかを判定できる
  • 完全一致と部分一致では検索結果が異なるため、目的に合わせて使い分ける
  • 検索対象列と抽出する行の範囲は分けて考える
  • vbTextCompareを指定すると、大文字・小文字を区別しない検索ができる
  • エラー値が含まれる可能性がある場合は、IsErrorで確認してから検索する
  • 値だけを抽出する場合は、行全体のCopyではなく必要範囲をValueで転記する方法もある
  • 単純な部分一致にはInStr、パターン判定にはLikeという使い分けができる
  • 大量データを扱う場合は、配列へ読み込んでVBA内部で検索・抽出する方法も検討する

部分一致検索の仕組みを独立して理解しておけば、抽出だけでなく、該当行の削除・色付け・集計・別処理への振り分けなどにも応用できます。検索処理を再利用できる形で組んでおくことで、似た条件を扱うVBAを作成するときにも効率よく展開できるようになります。

    -VBAで自動化, VBA一覧, 抽出・検索処理, 条件一致・行列処理