【VBA】複数条件でデータを抽出して別シートにまとめる方法(コピペOK)

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

この記事でできること

  • VBAで指定条件のデータを自動抽出できる
  • 抽出結果を別シートにコピーしてまとめられる
  • 複数条件(AND/OR)+日付範囲の絞り込みもできる(実務版)

対象: Excel 2016以降 / Microsoft 365、Windows 10/11


完成イメージ(Before / After)

Before(手動フィルター):

  1. 手動でフィルターのプルダウンを開く
  2. 条件を1つずつ設定
  3. 抽出結果をコピー
  4. 別シートに貼り付け
  5. フィルターを解除 → 次の条件で繰り返し

After(VBAで自動抽出):

  1. マクロを実行(またはボタンをクリック)
  2. 指定した条件で自動フィルターが実行される
  3. 抽出結果が別シートにコピーされる
  4. 完了メッセージで抽出件数を確認

自分も毎月、品質データから不良品カテゴリ別に抽出して報告書を作っていた。手動フィルターで3条件設定→コピー→別シートに貼り付け、を5カテゴリ分繰り返すのが地味にストレスだった。VBAでAutoFilterを自動化してからは、5カテゴリ分の抽出が1クリックで完了。条件設定ミスもゼロ。同じフィルター操作を繰り返している人に、この記事で自動化を体験してほしい。

手動フィルターは「毎回同じ条件で繰り返す」のが最大の無駄。VBAに条件を覚えさせれば、1クリックで正確に抽出できる。

なお、特定の文字を「検索してハイライトする」のは 特定の文字を含むセルを検索してハイライト を参照。この記事では「条件で行を抽出して別シートにまとめる」に特化する。


実行前の準備

シート構成を確認する

このコードは以下の2シート構成を前提としている:

「データ」シート(元データ):

A列 B列 C列 D列
日付 カテゴリ 品名 金額
2026/03/01 原材料 鋼材A 50000
2026/03/05 外注費 加工B 30000
  • 1行目はヘッダー
  • 2行目以降がデータ

「抽出結果」シート:

  • 抽出結果の貼り付け先。マクロ実行時にクリアしてから貼り付ける

バックアップを取る

抽出先シートの既存データは上書きされる。元データは変更されないが、念のためファイルのコピーを保存しておく。

Excelをマクロ有効ブック(.xlsm)で保存する

  1. 「ファイル」→「名前を付けて保存」
  2. ファイルの種類を「Excelマクロ有効ブック (*.xlsm)」に変更
  3. 保存

手順(コピペ → 実行まで約5分)

VBE(コードを書く画面)を開く

  1. Excelで Alt + F11 を押す
  2. VBE(Visual Basic Editor)が開く

標準モジュールを挿入する

  1. VBEのメニュー →「挿入」→「標準モジュール」
  2. 白い画面(コードウィンドウ)が表示される

コードを貼り付けて実行する

  1. コードウィンドウに、下のコードをそのままコピペする
  2. Alt + F8 → マクロ名を選んで「実行」

ボタンに割り当てれば毎回Alt+F8を押さなくて済む。方法は マクロをボタン1つで実行する方法 を参照。


コード(最小版)– 1条件でフィルター+別シートにコピー


'============================================================
' ■ AutoFilterで条件抽出 → 別シートにコピー(最小版)
'   → 指定列の条件に一致するデータを抽出し、別シートに貼り付け
'============================================================
Sub FilterAndCopyMinimal()

    '--- ★書き換えポイント ---
    Dim srcSheet As String
    srcSheet = "データ"           '← 元データのシート名

    Dim destSheet As String
    destSheet = "抽出結果"        '← 抽出結果の貼り付け先シート名

    Dim filterCol As Long
    filterCol = 2                 '← フィルターする列番号(2=B列)

    Dim filterValue As String
    filterValue = "原材料"        '← 抽出条件(完全一致)
    '--- ★ここまで ---

    Dim wsSrc As Worksheet
    Set wsSrc = ThisWorkbook.Worksheets(srcSheet)

    Dim wsDest As Worksheet
    Set wsDest = ThisWorkbook.Worksheets(destSheet)

    '--- 抽出先シートをクリア
    wsDest.Cells.Clear

    '--- 既存のAutoFilterを解除
    If wsSrc.AutoFilterMode Then wsSrc.AutoFilterMode = False

    '--- AutoFilter実行
    Dim lastRow As Long
    lastRow = wsSrc.Cells(wsSrc.Rows.Count, 1).End(xlUp).Row

    Dim dataRange As Range
    Set dataRange = wsSrc.Range("A1:D" & lastRow)

    dataRange.AutoFilter Field:=filterCol, Criteria1:=filterValue

    '--- 抽出結果を別シートにコピー
    Dim visibleCount As Long
    On Error Resume Next
    visibleCount = dataRange.Columns(1).SpecialCells(xlCellTypeVisible).Count - 1
    On Error GoTo 0

    If visibleCount > 0 Then
        dataRange.SpecialCells(xlCellTypeVisible).Copy
        wsDest.Range("A1").PasteSpecial xlPasteValues
        Application.CutCopyMode = False
    End If

    '--- フィルター解除
    wsSrc.AutoFilterMode = False

    '--- 完了メッセージ
    If visibleCount > 0 Then
        MsgBox visibleCount & " 件のデータを抽出しました。" & vbCrLf & _
               "結果: " & destSheet & "シート", vbInformation
    Else
        MsgBox "条件に一致するデータがありませんでした。", vbExclamation
    End If

End Sub

書き換えポイント

変数 説明 初期値
srcSheet 元データのシート名 "データ"
destSheet 抽出結果の貼り付け先 "抽出結果"
filterCol フィルターする列番号 2(B列)
filterValue 抽出条件 "原材料"

コードの流れ

  1. 抽出先シートをクリア(前回の結果を消す)
  2. 既存のAutoFilterを解除(二重設定防止)
  3. データ範囲に AutoFilter を実行
  4. SpecialCells(xlCellTypeVisible) でフィルター結果(可視セル)を取得
  5. 抽出結果を別シートにコピー(値のみ)
  6. フィルターを解除して元に戻す

重要: フィルター結果が0件の場合、SpecialCells がエラーになる。On Error Resume Next で回避し、0件チェックを行っている。転記の技術は セルの転記を自動化する方法 と同じ仕組み。


コード(実務版)– 複数条件+日付範囲+件数表示

実務では「カテゴリがAまたはB」かつ「日付が今月分」のように複数条件を組み合わせる。日付範囲のフィルターと、OR条件の指定方法を追加した版。

日付範囲の絞り込みを追加してからは、月次報告書の抽出が正確になった。先月分と今月分を間違えて報告する事故がなくなった。


'============================================================
' ■ 複数条件AutoFilter+日付範囲+別シートコピー(実務版)
'   → カテゴリOR条件 + 日付範囲AND条件
'============================================================
Sub FilterAndCopyAdvanced()

    '--- ★書き換えポイント ---
    Dim srcSheet As String
    srcSheet = "データ"

    Dim destSheet As String
    destSheet = "抽出結果"

    '--- フィルター条件1: カテゴリ(B列)のOR条件
    Dim categoryCol As Long
    categoryCol = 2                '← カテゴリ列(B列)

    Dim categories As Variant
    categories = Array("原材料", "外注費")  '← 抽出するカテゴリ(複数可)

    '--- フィルター条件2: 日付範囲(A列)
    Dim dateCol As Long
    dateCol = 1                    '← 日付列(A列)

    Dim startDate As Date
    startDate = DateSerial(Year(Date), Month(Date), 1)  '← 今月1日

    Dim endDate As Date
    endDate = DateSerial(Year(Date), Month(Date) + 1, 0)  '← 今月末日
    '--- ★ここまで ---

    Dim wsSrc As Worksheet
    Set wsSrc = ThisWorkbook.Worksheets(srcSheet)

    Dim wsDest As Worksheet
    Set wsDest = ThisWorkbook.Worksheets(destSheet)

    '--- 抽出先シートをクリア
    wsDest.Cells.Clear

    '--- 既存のAutoFilterを解除
    If wsSrc.AutoFilterMode Then wsSrc.AutoFilterMode = False

    '--- データ範囲を設定
    Dim lastRow As Long
    lastRow = wsSrc.Cells(wsSrc.Rows.Count, 1).End(xlUp).Row

    Dim lastCol As Long
    lastCol = wsSrc.Cells(1, wsSrc.Columns.Count).End(xlToLeft).Column

    Dim dataRange As Range
    Set dataRange = wsSrc.Range(wsSrc.Cells(1, 1), wsSrc.Cells(lastRow, lastCol))

    '--- AutoFilter: カテゴリ(OR条件)
    dataRange.AutoFilter Field:=categoryCol, _
        Criteria1:=categories, _
        Operator:=xlFilterValues

    '--- AutoFilter: 日付範囲(AND条件)
    dataRange.AutoFilter Field:=dateCol, _
        Criteria1:=">=" & Format(startDate, "yyyy/MM/dd"), _
        Operator:=xlAnd, _
        Criteria2:="<=" & Format(endDate, "yyyy/MM/dd")

    '--- 抽出結果を別シートにコピー
    Dim visibleCount As Long
    On Error Resume Next
    visibleCount = dataRange.Columns(1).SpecialCells(xlCellTypeVisible).Count - 1
    On Error GoTo 0

    If visibleCount > 0 Then
        dataRange.SpecialCells(xlCellTypeVisible).Copy
        wsDest.Range("A1").PasteSpecial xlPasteValues
        Application.CutCopyMode = False
    End If

    '--- フィルター解除
    wsSrc.AutoFilterMode = False

    '--- 完了メッセージ
    Dim msg As String
    If visibleCount > 0 Then
        msg = visibleCount & " 件のデータを抽出しました。" & vbCrLf & _
              "条件: " & Join(categories, ", ") & vbCrLf & _
              "期間: " & Format(startDate, "yyyy/MM/dd") & " 〜 " & _
              Format(endDate, "yyyy/MM/dd") & vbCrLf & _
              "結果: " & destSheet & "シート"
        MsgBox msg, vbInformation
    Else
        MsgBox "条件に一致するデータがありませんでした。" & vbCrLf & _
               "条件: " & Join(categories, ", ") & vbCrLf & _
               "期間: " & Format(startDate, "yyyy/MM/dd") & " 〜 " & _
               Format(endDate, "yyyy/MM/dd"), vbExclamation
    End If

End Sub

書き換えポイント

変数 説明 初期値
srcSheet / destSheet 元データ / 抽出先シート名 "データ" / "抽出結果"
categoryCol カテゴリ列の番号 2(B列)
categories 抽出するカテゴリ(複数指定可) Array("原材料", "外注費")
dateCol 日付列の番号 1(A列)
startDate / endDate 日付範囲 今月1日〜今月末日

コードの流れ

  1. 抽出先クリア: 前回の結果を消す
  2. AutoFilter解除: 二重設定を防止
  3. カテゴリOR条件: Operator:=xlFilterValues + Array() で複数値を指定
  4. 日付AND条件: >=開始日 AND <=終了日 で範囲指定
  5. 可視セルコピー: SpecialCells(xlCellTypeVisible) で抽出結果を取得
  6. フィルター解除: 元データを元の状態に戻す
  7. 件数表示: 抽出件数・条件・期間をまとめて表示

抽出マクロをボタン(マクロをボタン1つで実行する方法)に割り当てれば、毎月の報告書作成がボタン1つで完了する。


よくある落とし穴5選

1. フィルター結果が0件で「SpecialCells」エラー

自分もこれで止まった。条件に一致するデータが0件のときに SpecialCells(xlCellTypeVisible) がエラーを出す。「データがないだけなのに止まるの?」と最初は戸惑った。

対策: On Error Resume Next で一旦エラーを無視し、可視セル数をカウントして0件チェックを行う。コード内で対策済み。

2. AutoFilterが二重にかかってエラー

原因: 既にAutoFilterがかかっている状態で AutoFilter を実行すると、意図しない動作になる。

対策: If wsSrc.AutoFilterMode Then wsSrc.AutoFilterMode = False で事前に解除。コード内で対策済み。

3. 日付のフィルターが効かない

原因: セルの書式が「文字列」になっていると、日付として認識されない。

対策: 日付列のセル書式を「日付」に変更する。Format(startDate, "yyyy/MM/dd") の形式がシートの日付形式と一致しているか確認する。

4. 抽出先シートの既存データが残っている

原因: 前回の抽出結果が残ったままで、新しい結果と混在する。

対策: コード冒頭で wsDest.Cells.Clear を実行して全クリアしている。

5. ワイルドカードの意図しないマッチ

原因: Criteria1:="材*" のように * を使うと、「材料」「材質」「材木」すべてにマッチする。

対策: 完全一致で抽出したい場合は * を使わない。部分一致なら "*材*" のように両側に付ける。


FAQ

Q1: 3列以上に条件を設定したい

AutoFilter を列ごとに複数回実行する。条件は上書きではなくANDで積み重なる:


dataRange.AutoFilter Field:=1, Criteria1:=">=2026/03/01"   '← A列
dataRange.AutoFilter Field:=2, Criteria1:="原材料"          '← B列
dataRange.AutoFilter Field:=4, Criteria1:=">=10000"         '← D列

Q2: フィルターだけかけて、コピーはしない

別シートコピーの処理を削除し、フィルターだけ残す。手動で確認してからコピーしたい場合に便利。

Q3: 書式もコピーしたい

xlPasteValuesxlPasteAll に変更する:


wsDest.Range("A1").PasteSpecial xlPasteAll

Q4: 抽出結果をPDFで保存したい

抽出結果シートをPDFに変換できる。ExcelファイルをPDFに一括変換 を参照。

Q5: 抽出結果をCSVで出力したい

抽出結果シートをCSVに書き出せる。ExcelデータをCSVファイルに書き出す を参照。


まとめ

  • AutoFilter で条件指定してデータを抽出できる(最小版)
  • xlFilterValues + Array() で複数条件のOR抽出ができる(実務版)
  • 日付範囲は >= / <= のAND条件で指定する
  • 0件チェック(SpecialCells のエラー回避)を忘れずに入れる

関連記事


次にやりたくなること


もっとカスタマイズしたい場合

「抽出条件が5つ以上ある」「抽出結果をそのまま帳票テンプレートに流し込みたい」「AdvancedFilterを使いたい」など、業務に合わせたカスタマイズが必要な場合は、ココナラで相談できる。

相談時に伝えると話が早い情報:

  • Excel のバージョン / OS
  • 元データの列構成と行数の目安
  • 抽出条件の内容(列名・条件値・AND/OR)
  • 抽出結果の使い道(報告書/CSV/メール/PDF)

あわせて読みたい

コメント

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