【ExcelVBA・マクロ】AdvancedFilter完全ガイド|AutoFilterとの違い・別シート抽出・重複削除まで【コピペOK】

AdvancedFilter完全ガイド ExcelVBA

AutoFilterで2つ以上の条件が組めなくて困っていませんか?ExcelVBAの AdvancedFilter を使えば、AND/OR条件の自由な組み合わせ・別シートへの直接出力・重複の自動除去が「1メソッド」で実現できます。今回はコピペOKのサンプルコードつきで、AdvancedFilterの使い方を完全網羅します。

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

この記事で学べること

  • AdvancedFilter と AutoFilter の違い
  • 引数(Action / CriteriaRange / CopyToRange / Unique)の正しい使い方
  • 条件範囲(CriteriaRange)の作り方:AND条件・OR条件・ワイルドカード
  • 別シートへの抽出方法
  • 重複削除(ユニークリスト作成)
  • よくあるエラーと対処法

AdvancedFilter とは?AutoFilter との違い

AdvancedFilterの3大メリット

まずは、よく使われる AutoFilter との違いを比較表で確認しましょう。

比較項目AutoFilterAdvancedFilter
同時指定できる条件数1列につき最大2条件制限なし
AND/OR の組み合わせ同一列のみ複数列をまたいで自在
抽出結果の出力先元データの場所のみ別シート・別セルに直接出力可
重複除去不可Unique:=True で可能
元データへの影響あり(フィルター表示)xlFilterCopyなら変更なし

結論:AutoFilterで対応できない「複雑な条件」「別シート出力」「重複除去」はAdvancedFilterの出番です!


基本構文と引数の説明

構文

Range.AdvancedFilter(Action, CriteriaRange, CopyToRange, Unique)

引数一覧表

引数名必須/省略可説明
Action必須xlFilterInPlace(元の場所で絞込)または xlFilterCopy(別場所にコピー)
CriteriaRange省略可検索条件を書いたセル範囲。省略すると条件なし(全件対象)
CopyToRange省略可ActionがxlFilterCopyのときの出力先(xlFilterCopyの場合は実質必須)
Unique省略可True=重複除去して抽出。False(既定)=重複を含む

Action 定数の説明

定数動作
xlFilterInPlace1元のデータ範囲で非表示・表示を切り替え(AutoFilterに近い動作)
xlFilterCopy2条件に合う行を別場所にコピー。元データは変更なし ← 実務では主にこちら

条件範囲(CriteriaRange)の作り方【最重要】

基本ルール

⚠️ 重要:条件範囲の1行目(ヘッダー)は元データの列名と完全一致させる必要があります!大文字・小文字・スペースのズレでも動作しません。

AND条件の作り方

「条件を同じ行に横並びに書く → 全条件を満たす行だけ抽出(AND)」

サンプル条件範囲(シートのG1:H2に入力):

担当者売上金額
田中>100000
Sub AdvancedFilter_AND条件()
    Dim ws As Worksheet
    Set ws = ActiveSheet
    
    ' 条件範囲(AND条件):担当者が「田中」かつ売上が100000より大きい
    ' G1:H2 に以下の内容が入力済み前提
    ' G1=担当者, H1=売上金額
    ' G2=田中,  H2=>100000
    
    ' 抽出前に出力先をクリア
    ws.Range("J1:N1000").ClearContents
    
    ws.Range("A1").CurrentRegion.AdvancedFilter _
        Action:=xlFilterCopy, _
        CriteriaRange:=ws.Range("G1:H2"), _
        CopyToRange:=ws.Range("J1")
    
    MsgBox "AND条件で抽出しました!"
End Sub

OR条件の作り方

「条件を別々の行に書く → どちらかを満たす行を抽出(OR)」

サンプル条件範囲(シートのG1:G3に入力):

担当者
田中
鈴木
Sub AdvancedFilter_OR条件()
    Dim ws As Worksheet
    Set ws = ActiveSheet
    
    ' 条件範囲(OR条件):担当者が「田中」または「鈴木」
    ' G1:G3 に以下の内容が入力済み前提
    ' G1=担当者
    ' G2=田中
    ' G3=鈴木
    
    ws.Range("J1:N1000").ClearContents
    
    ws.Range("A1").CurrentRegion.AdvancedFilter _
        Action:=xlFilterCopy, _
        CriteriaRange:=ws.Range("G1:G3"), _
        CopyToRange:=ws.Range("J1")
    
    MsgBox "OR条件で抽出しました!"
End Sub

AND+ORの複合条件

「同じ行=AND、別の行=OR」の組み合わせで複雑な条件も表現できます。

例:「田中かつ売上>100000」 OR 「鈴木かつ売上>50000」

担当者売上金額
田中>100000
鈴木>50000

ワイルドカードの使い方

記号意味条件セルの書き方マッチする例
*任意の文字列(0文字以上)東京*「東京都」「東京都新宿区」など
?任意の1文字田?「田中」「田村」(2文字限定)
~エスケープ文字~*「*」という文字そのもの
Sub AdvancedFilter_ワイルドカード()
    Dim ws As Worksheet
    Set ws = ActiveSheet
    
    ' 条件範囲:商品名が「ノート」で始まる行を抽出
    ' G1=商品名, G2=ノート*  ← シートに入力済み前提
    
    ws.Range("J1:N1000").ClearContents
    
    ws.Range("A1").CurrentRegion.AdvancedFilter _
        Action:=xlFilterCopy, _
        CriteriaRange:=ws.Range("G1:G2"), _
        CopyToRange:=ws.Range("J1")
    
    MsgBox "ワイルドカード抽出しました!"
End Sub

別シートへの抽出方法【実務でよく使う!】

⚠️ 重要:別シートへ抽出するとき、AdvancedFilter を呼び出すのは「元データがあるシート側」からです。出力先を別シートに指定するだけでOKです。

Sub AdvancedFilter_別シート抽出()
    Dim srcWs As Worksheet  ' 元データのシート
    Dim destWs As Worksheet ' 出力先のシート
    
    Set srcWs = Worksheets("売上データ")
    Set destWs = Worksheets("抽出結果")
    
    ' 出力先シートをクリア(ヘッダーも含めてリセット)
    destWs.Cells.ClearContents
    
    ' 条件範囲は srcWs の I1:J2 に設定済みとする
    ' ★ 元データ側のシートから呼び出す(重要!)
    srcWs.Range("A1").CurrentRegion.AdvancedFilter _
        Action:=xlFilterCopy, _
        CriteriaRange:=srcWs.Range("I1:J2"), _
        CopyToRange:=destWs.Range("A1")
    
    Dim cnt As Long
    cnt = destWs.Range("A1").CurrentRegion.Rows.Count - 1
    MsgBox "別シートへの抽出が完了しました!" & vbCrLf & "件数:" & cnt & "件"
End Sub
  • CopyToRangeには出力先シートの先頭セル(A1)だけ指定すればOK
  • 出力前に destWs.Cells.ClearContents で前回の結果をクリアすることを忘れずに
  • CriteriaRange と元データは同じシート(srcWs)に置く

重複削除してユニークリストを作成する

売上リストから「担当者名の重複なし一覧」を作るなど、マスタリスト作成に最適です。

Sub AdvancedFilter_重複削除()
    Dim ws As Worksheet
    Set ws = ActiveSheet
    
    ' A列の担当者名から、重複を除いたユニークリストをD列に作成
    ws.Range("D:D").ClearContents
    
    ws.Range("A1:A1000").AdvancedFilter _
        Action:=xlFilterCopy, _
        CopyToRange:=ws.Range("D1"), _
        Unique:=True
    
    MsgBox "ユニークリストを作成しました!" & vbCrLf & _
           "件数:" & ws.Range("D1").CurrentRegion.Rows.Count - 1 & "件"
End Sub

応用:別シートにユニーク担当者リストを作成

Sub AdvancedFilter_別シートユニーク()
    Dim srcWs As Worksheet
    Dim destWs As Worksheet
    
    Set srcWs = Worksheets("売上データ")
    Set destWs = Worksheets("担当者マスタ")
    
    destWs.Range("A:A").ClearContents
    
    ' B列(担当者列)のユニークデータを別シートへ
    srcWs.Columns("B").AdvancedFilter _
        Action:=xlFilterCopy, _
        CopyToRange:=destWs.Range("A1"), _
        Unique:=True
    
    MsgBox "担当者マスタを更新しました!"
End Sub

実務サンプル:条件範囲をVBAで動的に作成する【応用編】

条件を毎回手動でシートに書くのではなく、VBA内で条件値を変数として扱い、条件範囲を自動生成するパターンです。

Sub AdvancedFilter_動的条件作成()
    Dim srcWs As Worksheet
    Dim destWs As Worksheet
    
    '-------------------------------------------
    ' シートの参照を設定
    '-------------------------------------------
    Set srcWs = Worksheets("売上データ")
    Set destWs = Worksheets("抽出結果")
    
    '-------------------------------------------
    ' 条件を一時的に書き込む(Z列以降などデータ外の空きエリアを使用)
    '-------------------------------------------
    srcWs.Range("Z1") = "担当者"    ' 元データの列名と一致させる!
    srcWs.Range("AA1") = "売上金額"  ' 元データの列名と一致させる!
    srcWs.Range("Z2") = "田中"       ' 条件値(変数で渡してもOK)
    srcWs.Range("AA2") = ">50000"    ' 数値条件
    
    '-------------------------------------------
    ' 出力先をクリアして抽出実行
    '-------------------------------------------
    destWs.Cells.ClearContents
    
    srcWs.Range("A1").CurrentRegion.AdvancedFilter _
        Action:=xlFilterCopy, _
        CriteriaRange:=srcWs.Range("Z1:AA2"), _
        CopyToRange:=destWs.Range("A1")
    
    '-------------------------------------------
    ' 一時条件エリアをクリア(後片付け)
    '-------------------------------------------
    srcWs.Range("Z1:AA2").ClearContents
    
    ' 結果確認
    Dim cnt As Long
    cnt = destWs.Range("A1").CurrentRegion.Rows.Count - 1
    
    If cnt > 0 Then
        MsgBox "抽出完了!" & cnt & "件が見つかりました。"
    Else
        MsgBox "条件に一致するデータがありませんでした。"
    End If
End Sub

ポイント:条件値を変数化することで、InputBox や UserForm から受け取った値を条件として動的に使えます。業務ツール化に最適なパターンです。


よくあるエラーと対処法

エラー/症状原因対処法
実行時エラー 1004別シート抽出でsrcWs以外からAdvancedFilterを呼び出している必ずsrcWs.Range(...).AdvancedFilterの形で呼び出す
抽出件数が0件になる条件範囲のヘッダーが元データの列名と不一致ヘッダー名を元データからコピーして完全一致させる
全件が抽出されるCriteriaRangeの条件行が空白条件値を正しく入力し、範囲指定を正確に
前回の結果が残る出力先のクリアを忘れている実行前にdestWs.Cells.ClearContentsを追加
ワイルドカードが効かない条件セルの書式が数値になっている条件セルの書式を「文字列」か「標準」に変更
比較演算子(>等)が文字として扱われる条件セルが文字列扱いになっていないセル値を ">50000" のように文字列で代入する

FAQ(よくある質問)

Q1. AdvancedFilterで日付の範囲指定はできますか?

A. できます。条件セルに >2025/1/1 のように日付比較演算子で記述してください。AND条件で >=2025/1/1(同じ行の別セルに)<=2025/3/31 と書けば日付範囲指定になります。

Q2. 抽出結果の列順を元データと変えることはできますか?

A. できます。CopyToRangeに「見たい列名のヘッダーだけ」を事前に入力しておくと、その列だけ・その順番で出力されます。不要な列を省いた抽出結果を作れます。

Q3. 元データがテーブル(ListObject)の場合でも使えますか?

A. 使えます。テーブルの場合は ListObject.Range.AdvancedFilter(...) のように呼び出してください。DataBodyRangeではなくRangeを指定するのがポイントです。

Q4. 共有ブックでAdvancedFilterは使えますか?

A. 旧形式の共有ブック(レガシー共有)ではAdvancedFilterが使えない場合があります。その場合はAutoFilterで代替するか、共同編集(共有ブック)の設定を見直してください。

Q5. AutoFilterよりAdvancedFilterの方が速いですか?

A. 条件が単純な場合はAutoFilterの方が速いことが多いです。AdvancedFilterは「複雑な条件」「別シート出力」「重複除去」が必要なときに使うのが最適です。


まとめ

AdvancedFilterのポイントまとめ:

  • AND条件 → 条件範囲の同じ行に横並び
  • OR条件 → 条件範囲の別々の行に縦並び
  • 別シート出力 → 元データ側のシートからメソッドを呼び出す
  • 重複除去Unique:=True
  • 毎回出力先を ClearContents でリセットする習慣をつける
  • ヘッダー名は元データと完全一致が鉄則

AutoFilterでは対応できなかった複雑な抽出処理が、AdvancedFilterひとつで解決できます。ぜひ実務で活用してください!

スポンサーリンク
スポンサーリンク
ExcelVBA
いがぴをフォローする

コメント

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