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

【VBA】複数条件に一致する列を抽出する方法|AND・ORで見出しを判定

Excel VBAで列を抽出するとき、「1つの条件だけでは必要な列を絞り込めない」というケースがあります。

たとえば、見出しに「売上」を含み、さらに「実績」を含む列だけを抽出したい場合です。反対に、「売上」または「原価」を含む列をまとめて取り出したい場合もあります。

このような複数条件の判定では、AndとOrを使い分けることが重要です。

条件の組み方を間違えると、VBA自体は正常に動いていても、本来必要な列が除外されたり、不要な列まで抽出されたりする可能性があります。

この記事では、複数条件を使って列の見出しを判定し、条件に一致した列だけを別シートへ抽出する方法を、AND条件とOR条件の違いから実務向けのコードまで解説します。

✅ VBAで複数条件に一致する列を抽出する基本的な考え方

複数条件で列を抽出するときは、最初に「すべての条件を満たす必要があるのか」「どれか1つを満たせばよいのか」を明確にする必要があります。この違いを曖昧にしたままコードを書くと、想定していた列と実際の抽出結果が一致しなくなります。特にAndとOrはコードとしてはわずかな違いですが、判定結果は大きく変わります。

また、今回対象にするのは各行のデータではなく、列の見出しです。「複数条件」という言葉だけで行データの絞り込みと混同しないことも重要です。まずはAND条件とOR条件で何が変わるのか整理しておきましょう。

・AND条件は複数の条件をすべて満たす列を抽出する

たとえば、1行目に次の見出しがあるとします。

A列B列C列D列E列
商品名東京売上実績東京売上予測大阪売上実績大阪原価実績

ここから、

「売上」を含む AND 「実績」を含む

という条件で列を抽出します。

対象になるのは、

  • 東京売上実績
  • 大阪売上実績

です。

「東京売上予測」は「売上」を含みますが、「実績」が含まれていないため対象外です。

「大阪原価実績」も「実績」は含みますが、「売上」が含まれていないため対象外になります。

VBAでは次のように判定できます。

If InStr(1, headerText, "売上", vbTextCompare) > 0 And _
   InStr(1, headerText, "実績", vbTextCompare) > 0 Then

    '2つの条件を満たした列を処理する

End If

AND条件では、左側と右側の両方がTrueになった場合だけ処理されるのがポイントです。

条件を追加するほど対象列は絞り込まれていきます。

そのため、「似た見出しが多い中から、目的に合う列だけを限定したい」という処理に向いています。

・OR条件はどれか1つの条件を満たす列を抽出する

今度は、

「売上」を含む OR 「原価」を含む

という条件を考えます。

先ほどの表なら、

  • 東京売上実績
  • 東京売上予測
  • 大阪売上実績
  • 大阪原価実績

が対象になります。

VBAでは次のように書けます。

If InStr(1, headerText, "売上", vbTextCompare) > 0 Or _
   InStr(1, headerText, "原価", vbTextCompare) > 0 Then

    'どちらかの条件を満たした列を処理する

End If

OR条件では、どちらか一方でも条件を満たせば処理対象になります。

したがって、

AND → 対象を絞り込む

OR → 対象を広げる

と考えると理解しやすくなります。

ただし、「ANDなら厳密、ORなら曖昧」という意味ではありません。

たとえば帳票作成で「売上関連と原価関連の列をまとめて取り出したい」という仕様なら、OR条件を使用することが正しい設計です。

重要なのは、抽出したい列のルールを先に整理してからAnd・Orを選択することです。

複数条件を組み合わせる前に、1つの見出しを基準として対象列を判定する基本処理を確認したい場合は、「条件に一致する列だけを別シートへ抽出する方法」で、見出しの判定から別シートへの転記までを詳しく解説しています。


✅ VBAでAND条件に一致する列だけを別シートへ抽出する

AND条件を使用すると、似た見出しが多数存在するデータから対象を細かく絞り込めます。ただし、条件を増やせば安全になるわけではありません。見出しの表記が少し変わっただけで、必要な列が条件から外れることもあります。また、部分一致を組み合わせる場合は、それぞれの検索文字が本当に見出しを識別できるか確認する必要があります。コード上で条件式が正しくても、検索文字の選び方が不適切なら正しい抽出結果にはなりません。

実務では「条件式」と「元データの命名ルール」をセットで考えることが大切です。ここでは、「売上」と「実績」の両方を含む列を抽出するコードを確認します。

・2つの検索文字を変数として管理する

条件式へ直接、

"売上"
"実績"

と書いても動作します。

しかし、後から条件を変更する可能性を考えると、それぞれを変数として管理しておくと分かりやすくなります。

Dim firstCondition As String
Dim secondCondition As String

firstCondition = "売上"
secondCondition = "実績"

そして判定部分を、

If InStr(1, headerText, firstCondition, vbTextCompare) > 0 And _
   InStr(1, headerText, secondCondition, vbTextCompare) > 0 Then

とします。

たとえば後から、

「売上」AND「予測」

へ変更する場合は、

firstCondition = "売上"
secondCondition = "予測"

と変更できます。

condition1やstr1のような名前でも動作しますが、後からコードを確認する人にとっては何を表す変数なのか判断しにくくなります。

実務では、多少長くても変数の役割が推測できる名前を使用することが保守性につながります。

・AND条件で列を抽出する実務コード

次のコードでは、「元データ」シートの見出しから「売上」と「実績」の両方を含む列を探し、「抽出結果」シートへ左から順番に転記します。

Sub ExtractColumnsByAndCondition()

    Dim sourceSheet As Worksheet
    Dim destinationSheet As Worksheet
    Dim firstCondition As String
    Dim secondCondition As String
    Dim headerText As String
    Dim lastColumn As Long
    Dim lastRow As Long
    Dim currentColumn As Long
    Dim destinationColumn As Long

    '処理対象となるシートを設定する
    Set sourceSheet = ThisWorkbook.Worksheets("元データ")
    Set destinationSheet = ThisWorkbook.Worksheets("抽出結果")

    'AND条件として使用する検索文字
    firstCondition = "売上"
    secondCondition = "実績"

    '1行目の最終列を取得する
    lastColumn = sourceSheet.Cells(1, sourceSheet.Columns.Count) _
                            .End(xlToLeft).Column

    '抽出先はA列から開始する
    destinationColumn = 1

    For currentColumn = 1 To lastColumn

        '現在の列の見出しを取得する
        headerText = CStr(sourceSheet.Cells(1, currentColumn).Value)

        '2つの文字を両方含む見出しか判定する
        If InStr(1, headerText, firstCondition, vbTextCompare) > 0 And _
           InStr(1, headerText, secondCondition, vbTextCompare) > 0 Then

            '対象列の最終行を取得する
            lastRow = sourceSheet.Cells( _
                sourceSheet.Rows.Count, currentColumn _
            ).End(xlUp).Row

            '見出しから最終行までを抽出する
            sourceSheet.Range( _
                sourceSheet.Cells(1, currentColumn), _
                sourceSheet.Cells(lastRow, currentColumn) _
            ).Copy Destination:=destinationSheet.Cells(1, destinationColumn)

            '次の抽出結果は右隣へ配置する
            destinationColumn = destinationColumn + 1

        End If

    Next currentColumn

End Sub

このコードでは、headerTextへ現在調べている列の見出しを一度格納してから判定しています。

同じセルを条件式の中で何度も直接参照することもできますが、

headerText = CStr(sourceSheet.Cells(1, currentColumn).Value)

としておくことで、「現在の見出しに対して複数の条件を判定している」という処理意図が読み取りやすくなります。

また、条件に一致した後もループを終了していません。

AND条件を満たす列が複数存在する可能性があるため、最終列まで検索を続け、それぞれを抽出先のA列、B列、C列……と順番に配置します。

「1列見つけたら終了する」のか、「一致するすべての列を抽出する」のかは、同じ検索処理でも設計が異なります。

今回の目的は複数条件を満たすすべての列を抽出することなので、最後まで検索する構成にしています。

AND・ORを組み合わせるのではなく、「売上」のような1つの文字を含む列をまとめて抽出したい場合は、「特定の文字を含む列を抽出する方法」で、InStrによる部分一致検索と複数列の転記方法を解説しています。


✅ VBAでOR条件に一致する複数列を抽出する考え方

OR条件はAND条件より対象範囲が広がるため、意図していない列まで抽出してしまう点に注意が必要です。特に短い検索文字を複数指定すると、多くの見出しがいずれかの条件へ一致する可能性があります。

また、「売上または原価」のような単純なOR条件と、AND・ORを同時に組み合わせた条件では判定の考え方も変わります。複雑な条件をいきなり1つのIf文へ詰め込むと、後から見たときにどの列が対象になるのか判断しにくくなります。まずは2つの条件のどちらかを満たす基本的なOR判定から理解することが重要です。AND条件との抽出結果の違いを意識しながら確認しましょう。

・「売上」または「原価」を含む見出しを判定する

OR条件の基本形は次のようになります。

If InStr(1, headerText, firstCondition, vbTextCompare) > 0 Or _
   InStr(1, headerText, secondCondition, vbTextCompare) > 0 Then

    'どちらかの条件に一致した列を抽出する

End If

たとえば、

firstCondition = "売上"
secondCondition = "原価"

とすれば、「売上」または「原価」のどちらかを含む見出しが対象です。

AND条件のコードと大部分は共通していますが、Andを単純にOrへ変更すればよいという考え方だけでは不十分です。

ANDからORへ変更すると対象列が増えるため、実際にどの見出しが条件へ一致するのかを確認してから使用することが重要になります。

特に業務ファイルでは、似た名前の列が後から追加されることがあります。

コードを作成した時点では正しくても、半年後に「売上予測」などの列が追加されれば、それもOR条件の対象になる可能性があります。

そのため、複数条件による列抽出では、条件式だけでなく元データ側の見出しルールが変わった場合の影響まで考えておくことが大切です。

・OR条件で一致した列を抽出する実務コード

次のコードでは、見出しに「売上」または「原価」のどちらかを含む列を抽出します。

Sub ExtractColumnsByOrCondition()

    Dim sourceSheet As Worksheet
    Dim destinationSheet As Worksheet
    Dim firstCondition As String
    Dim secondCondition As String
    Dim headerText As String
    Dim lastColumn As Long
    Dim lastRow As Long
    Dim currentColumn As Long
    Dim destinationColumn As Long

    '処理対象となるシートを設定する
    Set sourceSheet = ThisWorkbook.Worksheets("元データ")
    Set destinationSheet = ThisWorkbook.Worksheets("抽出結果")

    'OR条件として使用する検索文字
    firstCondition = "売上"
    secondCondition = "原価"

    '1行目の最終列を取得する
    lastColumn = sourceSheet.Cells(1, sourceSheet.Columns.Count) _
                            .End(xlToLeft).Column

    '抽出先はA列から開始する
    destinationColumn = 1

    For currentColumn = 1 To lastColumn

        '現在の列の見出しを取得する
        headerText = CStr(sourceSheet.Cells(1, currentColumn).Value)

        'どちらかの文字を含む見出しか判定する
        If InStr(1, headerText, firstCondition, vbTextCompare) > 0 Or _
           InStr(1, headerText, secondCondition, vbTextCompare) > 0 Then

            '対象列の最終行を取得する
            lastRow = sourceSheet.Cells( _
                sourceSheet.Rows.Count, currentColumn _
            ).End(xlUp).Row

            '見出しから最終行までを転記する
            sourceSheet.Range( _
                sourceSheet.Cells(1, currentColumn), _
                sourceSheet.Cells(lastRow, currentColumn) _
            ).Copy Destination:=destinationSheet.Cells(1, destinationColumn)

            '次の転記位置を右へ移動する
            destinationColumn = destinationColumn + 1

        End If

    Next currentColumn

End Sub

AND条件のコードと基本構造は同じですが、判定部分の意味は異なります。

条件1 And 条件2

なら両方を満たす必要がありますが、

条件1 Or 条件2

なら、どちらか一方を満たせば対象になります。

そのため、コードを修正するときはAndとOrだけを機械的に変更するのではなく、変更後にどの見出しが抽出対象になるのかを確認することが重要です。


✅ VBAでAND・OR条件を組み合わせるときの注意点

実務では「売上または原価を含み、さらに実績を含む列」のように、ANDとORを組み合わせたいケースもあります。ここで条件を思いついた順番に並べてしまうと、コードを見ただけでは判定範囲が分かりにくくなります。

また、演算子には評価される順序があるため、書いた本人の意図と実際の判定結果がずれる可能性もあります。マクロがエラーになれば気付きやすいですが、条件式の問題は「正常に動作しながら間違った列を抽出する」ことがあるため注意が必要です。複雑な条件では、どこまでを1つの条件グループとして扱うのか明示することが重要です。ANDとORを組み合わせる場合は、可読性も含めて条件式を設計しましょう。

・ANDとORを組み合わせる場合は括弧で意図を明確にする

たとえば、

「売上」または「原価」を含み、さらに「実績」を含む

という条件なら、考え方は次のようになります。

(売上 OR 原価)AND 実績

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

If (InStr(1, headerText, "売上", vbTextCompare) > 0 Or _
    InStr(1, headerText, "原価", vbTextCompare) > 0) And _
    InStr(1, headerText, "実績", vbTextCompare) > 0 Then

    '条件に一致した列を処理する

End If

たとえば、

  • 東京売上実績
  • 大阪原価実績
  • 東京売上予測
  • 大阪原価予測

という見出しがあれば、最初の2列が対象になります。

ここで重要なのが括弧です。

複数のAndとOrを組み合わせるときは、演算子の評価順序だけに頼るのではなく、

(条件A Or 条件B) And 条件C

のようにグループを明示した方が、後からコードを確認したときにも意図を読み取りやすくなります。

条件がさらに増える場合は、1つの長いIf文へ無理にまとめるより、判定結果をBoolean型の変数へ分ける方法もあります。

Dim isSalesOrCost As Boolean
Dim isActual As Boolean

isSalesOrCost = _
    InStr(1, headerText, "売上", vbTextCompare) > 0 Or _
    InStr(1, headerText, "原価", vbTextCompare) > 0

isActual = _
    InStr(1, headerText, "実績", vbTextCompare) > 0

If isSalesOrCost And isActual Then
    '条件に一致した列を処理する
End If

コードの行数は増えますが、

何を判定しているのか

が変数名から分かるため、条件変更が多い処理ではこちらの方が保守しやすい場合があります。

短く書くことよりも、数か月後にコードを見た人が条件を正しく理解できることを優先しましょう。

見出しではなく、各行のデータをAND・OR条件で判定して必要なレコードだけを取り出したい場合は、「複数条件に一致する行を抽出する方法」で、行方向の複数条件による抽出を詳しく解説しています。


 

✅ 複数条件に一致する列がない場合もVBAで判定する

複数条件を使用すると、単一条件よりも「対象が1件もない」という状況が起こりやすくなります。特にAND条件では条件を追加するほど対象が絞られるため、元データの見出しが少し変わっただけで一致件数が0になることがあります。その状態でマクロが何も表示せず終了すると、利用者は正常終了したのか、条件に一致しなかったのか判断できません。

また、前回の抽出結果が転記先に残っていれば、それを今回の結果と誤認する危険もあります。検索・抽出処理では、一致した場合だけでなく「一致しなかった場合」を処理の一部として考えることが大切です。簡単なカウンターを用意するだけでも結果を確認しやすくなります。

・抽出した列数をカウントして0件を検出する

一致した列数を記録する変数を用意します。

Dim matchedColumnCount As Long

matchedColumnCount = 0

条件に一致したときに、

matchedColumnCount = matchedColumnCount + 1

と加算します。

すべての列を確認した後に、

If matchedColumnCount = 0 Then
    MsgBox "条件に一致する列が見つかりませんでした。", vbExclamation
Else
    MsgBox matchedColumnCount & "列を抽出しました。", vbInformation
End If

とすれば、抽出結果を利用者へ知らせられます。

特に定期実行するマクロでは、「エラーが出なかった」ことと「必要なデータを抽出できた」ことは同じではありません。

見出し名の変更や入力ミスなどによって条件不一致になった場合も検出できるようにしておくと、抽出漏れに気付きやすくなります。

条件に一致した列を別シートへ抽出するのではなく、元データ上で一時的に隠したい場合は、「条件に一致する列を非表示にする方法」で、見出しや値を判定して列を自動で非表示にする方法を解説しています。


✅ 複数条件で抽出した列の値だけを転記する方法

複数条件の判定が正しくても、転記方法が目的に合っていなければ抽出結果を扱いにくくなることがあります。Copyを使えば数式や書式なども含めて転記できますが、集計用データとして利用する場合は値だけで十分なケースもあります。

また、元データに数式が設定されている場合、転記先でも数式を維持したいのか、計算済みの結果だけを残したいのかによって適した方法が変わります。抽出条件と転記方法は別の問題として考えることが重要です。条件判定が複雑になったからといって、転記処理まで複雑にする必要はありません。用途に合わせてCopyと値の直接代入を使い分けましょう。

・値だけ必要ならRangeへまとめて代入する

値だけを抽出する場合は、対象範囲と同じ大きさの転記先を用意します。

Dim sourceRange As Range
Dim destinationRange As Range

Set sourceRange = sourceSheet.Range( _
    sourceSheet.Cells(1, currentColumn), _
    sourceSheet.Cells(lastRow, currentColumn) _
)

Set destinationRange = destinationSheet.Cells(1, destinationColumn) _
    .Resize(sourceRange.Rows.Count, 1)

destinationRange.Value = sourceRange.Value

この方法では、クリップボードを使用せずに値をまとめて転記できます。

元セルに数式が入っている場合は、基本的に計算結果が転記されるため、抽出結果を固定データとして利用したい場合にも使いやすい方法です。

一方、書式や数式もそのまま必要なら、

sourceRange.Copy Destination:=destinationSheet.Cells(1, destinationColumn)

を使用します。

どちらを使用するかは、

「何を条件に抽出するか」ではなく、「抽出したデータを何に使うか」

で判断するのがポイントです。

抽出結果をA列から作り直すのではなく、転記先の既存データを残したまま右端へ追加したい場合は、「条件に一致する列を別シートの最終列へ追加する方法」で、最終列を取得して追記する処理を解説しています。


✅ VBAの複数条件を増やしすぎないことも実務では重要

AND・OR条件を使えば、かなり複雑な見出し判定も1つのマクロへ組み込めます。しかし、条件を追加できることと、追加した方がよいことは別です。条件が5個、10個と増えると、どの組み合わせで列が抽出されるのかコードだけでは判断しにくくなります。さらに、仕様変更のたびに長い条件式を書き換える設計では、括弧の位置や演算子を変更した際に別の条件へ影響する可能性があります。

実務では、処理を高度にすることよりも、後から安全に変更できることが重要になる場面があります。条件が複雑になってきたら、判定部分の分割や条件の管理方法そのものを見直しましょう。

・判定条件の役割が分かる構成にする

たとえば、

isSalesOrCost
isActual

のように判定結果を分けておけば、

If isSalesOrCost And isActual Then

という最終的な条件の意味を把握しやすくなります。

条件がさらに増える場合は、判定処理を別のFunctionへ分離する設計も選択肢です。

ただし、2条件程度の簡単な処理まで無理に分割すると、かえってコードを追いにくくなることがあります。

実務では、

  • 条件が少なく変更も少ない → If文で直接判定
  • AND・ORが混在する → Boolean型の変数で意味を分ける
  • 条件が多く複数処理から利用する → 判定処理の共通化を検討する

といったように、処理規模に合わせて設計すると管理しやすくなります。

複雑なコードを書くことが目的ではありません。

仕様変更があったときに、どこを修正すればよいか判断できる構成にしておくことが、実務用VBAでは重要です。

条件に一致する列について、検索・削除・別シートへのコピーなど関連する処理をまとめて確認したい場合は、「特定の文字を含む列の処理:検索・削除・別シートにコピー」もあわせて参考にしてください。


 

✅ まとめ:VBAのAND・OR条件で必要な列だけを抽出しよう

VBAでは、AndとOrを使い分けることで、複数の条件に一致する列だけを別シートへ抽出できます。

今回のポイントをまとめると、次のとおりです。

  • AND条件は複数の条件をすべて満たす列を対象にする
  • OR条件はいずれかの条件を満たす列を対象にする
  • InStrと組み合わせれば見出しを部分一致で判定できる
  • ANDとORを組み合わせる場合は括弧で条件のまとまりを明確にする
  • 複雑な条件はBoolean型の変数へ分けると意図を読み取りやすい
  • 一致した列数をカウントすれば0件の場合も検出できる
  • 複数列を抽出するときは転記先の列位置も管理する
  • 書式や数式も必要ならCopy、値だけなら.Valueによる転記を使い分ける
  • 条件を増やしすぎず、後から変更しやすい構成を意識する

単純な列抽出では1つの条件だけで十分でも、実際の業務データでは似た名前の見出しが増え、複数条件による絞り込みが必要になることがあります。

そのような場合も、最初から長い条件式を作るのではなく、「すべて必要なのか」「どれか1つでよいのか」を整理してからAND・ORを選択することが大切です。

条件の意味をコード上でも明確にしておけば、元データの項目追加や仕様変更が発生した場合にも、抽出条件を見直しやすいVBA処理にできます。

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