【VBA】オートフィルタでデータを絞り込み・解除する方法(コピペOK)

VBA
スポンサーリンク

記事ID: 062
タイトル: 【VBA】オートフィルタでデータを絞り込み・解除する方法(コピペOK)
カテゴリ: シート操作
一次キーワード: VBA オートフィルタ 抽出 解除
想定読者: 毎回同じフィルタ条件を手動でかけている事務・管理職
検索意図: VBAでオートフィルタの設定・複数条件の絞り込み・解除を自動化したい
読者の悩み(1文): 毎回同じ条件でフィルタをかける手作業が面倒
読了後にできること(1文): VBAでオートフィルタの設定・複数条件・解除をボタン1つで自動化できる
前提条件:
  - Excel版: Excel 2016以降 / Microsoft 365
  - OS: Windows 10/11
  - 保存形式: .xlsm(マクロ有効ブック)
  - 貼り付け場所: 標準モジュール
  - 実行方法: マクロ実行(F5)またはボタン割り当て
更新日: 2026-03-11
スポンサーリンク

この記事でわかること

VBAでオートフィルタを自動化する方法を、コピペで動くコード付きで解説します。

  • 対象:毎回同じフィルタ条件を手動でかけている人
  • 所要時間:コピペ → 実行まで3分

完成イメージ

実行前

部署 氏名 日付 売上
営業部 田中 2026/1/15 150,000
開発部 鈴木 2026/2/10 80,000
営業部 佐藤 2026/2/20 200,000
総務部 高橋 2026/3/05 50,000
営業部 伊藤 2026/3/15 120,000

実行後(A列「部署」=「営業部」でフィルタ):

部署 氏名 日付 売上
営業部 田中 2026/1/15 150,000
営業部 佐藤 2026/2/20 200,000
営業部 伊藤 2026/3/15 120,000

さらに実務版では、フィルタ結果だけを「抽出結果」シートに自動コピーできます。


自分も週次の報告資料を作るたびに、部署別・月別にフィルタを手動でかけて、結果をコピーして別シートに貼って…を繰り返していました。正直めんどくさかったし、フィルタ条件を間違えて最初からやり直すこともあって地味にストレスでした。

VBAでフィルタを自動化してからは、ボタン1つで部署別の集計シートが一瞬でできるようになりました。週次報告の準備が30分から5分に縮まりました。

同じようにフィルタをポチポチかけている人が、この記事でサクッと自動化できるようになればうれしいです。


基本:オートフィルタを1条件でかける

まずは最もシンプルな例。A列「部署」が「営業部」の行だけを表示します。


Sub フィルタ_1条件()
    ' 既にフィルタがかかっていたら解除
    If ActiveSheet.AutoFilterMode Then
        ActiveSheet.AutoFilterMode = False
    End If

    ' A列(Field:=1)が「営業部」の行だけ表示
    Range("A1").AutoFilter Field:=1, Criteria1:="営業部"
End Sub

ポイント

  • Range("A1") はデータ範囲の左上セルを指定します。Excelが自動的にデータ範囲を検出します
  • Field:=1フィルタ範囲の左端列から数えて1列目を意味します
  • Criteria1 に絞り込みたい値を指定します

前提として、1行目が見出し行(「部署」「氏名」など)になっている必要があります。見出しがないとデータの1行目がフィルタ対象外になります。

データの最終行を正確に取得する方法を使えば、フィルタ範囲を動的に指定することもできます。

複数条件で絞り込む(AND / OR)

OR条件:2つの値のどちらかに一致

「営業部」または「開発部」の行を表示する場合:


Sub フィルタ_OR条件_2値()
    If ActiveSheet.AutoFilterMode Then
        ActiveSheet.AutoFilterMode = False
    End If

    ' 「営業部」または「開発部」
    Range("A1").AutoFilter Field:=1, _
        Criteria1:="営業部", _
        Operator:=xlOr, _
        Criteria2:="開発部"
End Sub

OR条件:3つ以上の値のどれかに一致

「営業部」「開発部」「総務部」のいずれかを表示する場合は、ArrayxlFilterValues を使います:


Sub フィルタ_OR条件_3値以上()
    If ActiveSheet.AutoFilterMode Then
        ActiveSheet.AutoFilterMode = False
    End If

    ' 3つ以上の値はArrayで指定
    Range("A1").AutoFilter Field:=1, _
        Criteria1:=Array("営業部", "開発部", "総務部"), _
        Operator:=xlFilterValues
End Sub

注意: 3値以上のOR条件では Operator:=xlFilterValues が必須です。xlOr は2値までしか対応していません。

AND条件:複数列の条件を組み合わせる

A列「部署」が「営業部」かつ D列「売上」が10万以上の行を表示:


Sub フィルタ_AND条件_複数列()
    If ActiveSheet.AutoFilterMode Then
        ActiveSheet.AutoFilterMode = False
    End If

    ' A列(Field:=1)が「営業部」
    Range("A1").AutoFilter Field:=1, Criteria1:="営業部"

    ' さらにD列(Field:=4)が10万以上
    Range("A1").AutoFilter Field:=4, Criteria1:=">=100000"
End Sub

ポイント: 複数列のAND条件は、AutoFilterを列ごとに1行ずつ書くだけでOKです。2行目のAutoFilterを書いても、1行目のフィルタは解除されません。

日付範囲や部分一致でフィルタする

日付範囲:2026年1月〜3月のデータだけ表示


Sub フィルタ_日付範囲()
    If ActiveSheet.AutoFilterMode Then
        ActiveSheet.AutoFilterMode = False
    End If

    ' C列(日付列)を期間で絞り込み
    Range("A1").AutoFilter Field:=3, _
        Criteria1:=">=" & CLng(DateSerial(2026, 1, 1)), _
        Operator:=xlAnd, _
        Criteria2:="<=" & CLng(DateSerial(2026, 3, 31))
End Sub

重要: 日付でフィルタするときは CLng(DateSerial(...)) でシリアル値に変換します。文字列のまま ">=2026/1/1" と書くと、日付の表示形式やロケール設定によって正しく動かない場合があります。また、セルの日付がテキスト形式になっていると、そもそもシリアル値での比較が効かない点にも注意してください。

部分一致:「東京」を含むデータだけ表示


Sub フィルタ_部分一致()
    If ActiveSheet.AutoFilterMode Then
        ActiveSheet.AutoFilterMode = False
    End If

    ' B列に「東京」を含む行を表示
    Range("A1").AutoFilter Field:=2, Criteria1:="*東京*"
End Sub

ワイルドカード * を使えば、「東京」を含む任意の文字列にマッチします。

文字列の検索・置換については、セルの文字列を一括置換する方法も参考になります。

フィルタを解除する(全解除 / 特定列だけ解除)

全解除:フィルタ矢印ごと消す


Sub フィルタ_全解除()
    ' フィルタ矢印ごと完全に消す
    If ActiveSheet.AutoFilterMode Then
        ActiveSheet.AutoFilterMode = False
    End If
End Sub

絞り込みだけ解除:フィルタ矢印は残す


Sub フィルタ_絞り込みだけ解除()
    ' 絞り込みを解除して全行表示(フィルタ矢印は残る)
    If ActiveSheet.FilterMode Then
        ActiveSheet.ShowAllData
    End If
End Sub

特定の列だけフィルタ解除


Sub フィルタ_特定列だけ解除()
    ' A列(Field:=1)のフィルタだけ解除(他の列のフィルタは維持)
    Range("A1").AutoFilter Field:=1
End Sub

使い分け:

AutoFilterMode = False → フィルタ矢印ごと消す(完全リセット)

ShowAllData → 矢印は残して、全行を表示する

AutoFilter Field:=n(条件なし)→ 特定列だけ解除

実務版:フィルタ結果だけを別シートにコピーする

※ 実行前にブックを上書き保存しておくと安心です。

自分はこの方法を覚えてから、月次レポートの部署別シート分割もマクロ1本で済むようになりました。「毎月の定例作業がボタン1つ」になると、正直かなりラクになります。


Sub フィルタ結果を別シートにコピー()
    Dim wsData As Worksheet
    Dim wsResult As Worksheet
    Dim lastRow As Long

    Set wsData = ThisWorkbook.Sheets("データ")

    ' --- 「抽出結果」シートがなければ作成 ---
    On Error Resume Next
    Set wsResult = ThisWorkbook.Sheets("抽出結果")
    On Error GoTo 0

    If wsResult Is Nothing Then
        Set wsResult = ThisWorkbook.Sheets.Add(After:=wsData)
        wsResult.Name = "抽出結果"
    Else
        wsResult.Cells.Clear  ' 既存データをクリア
    End If

    ' --- データシートでフィルタ ---
    wsData.Activate

    ' 既存フィルタを解除
    If wsData.AutoFilterMode Then
        wsData.AutoFilterMode = False
    End If

    ' A列が「営業部」でフィルタ
    wsData.Range("A1").AutoFilter Field:=1, Criteria1:="営業部"

    ' --- フィルタ結果(可視セル)をコピー ---
    lastRow = wsData.Cells(wsData.Rows.Count, 1).End(xlUp).Row

    If lastRow >= 2 Then  ' データが1行以上ある場合
        wsData.Range("A1:D" & lastRow).SpecialCells(xlCellTypeVisible).Copy
        wsResult.Range("A1").PasteSpecial xlPasteValues   ' まず値を貼り付け
        wsResult.Range("A1").PasteSpecial xlPasteFormats  ' 次に書式を貼り付け
        Application.CutCopyMode = False
    Else
        MsgBox "条件に一致するデータがありませんでした。", vbInformation
    End If

    ' --- フィルタを解除 ---
    wsData.AutoFilterMode = False

    ' --- 結果シートに移動 ---
    wsResult.Activate
    wsResult.Columns.AutoFit

    Dim resultCount As Long
    resultCount = wsResult.Cells(wsResult.Rows.Count, 1).End(xlUp).Row - 1
    If resultCount > 0 Then
        MsgBox "抽出結果シートにコピーしました(" & resultCount & "件)"
    End If
End Sub

このコードのポイント:

  • 「抽出結果」シートがなければ自動作成、あればクリアして上書き
  • SpecialCells(xlCellTypeVisible)可視セル(フィルタで表示されている行)だけをコピー
  • 値→書式の順で2回PasteSpecialを呼ぶので、見た目もそのまま
  • 0件の場合はメッセージを表示して処理をスキップ
  • コピー後にフィルタを自動解除するので、データシートは元通り

シートの条件を変えたり、ボタンに割り当てれば、部署ごとのシート分割も自動化できます。エラー処理の基本はエラー処理で止まらないマクロを作る方法を参照してください。

落とし穴

自分も最初にAutoFilterを使ったとき、既にフィルタがかかっている状態でもう一度AutoFilterを呼んだら、フィルタが解除されてしまいました。トグル動作を知らなくて30分悩みました。「コードは合ってるのになぜ動かない?」と思ったら、実はフィルタが勝手にOFFになっていた、というオチです。

# 症状 原因 対策
1 AutoFilterを実行したらフィルタが解除された 既にフィルタがONの状態でAutoFilterを呼ぶとトグル動作でOFFになる 実行前に If ActiveSheet.AutoFilterMode Then AutoFilterMode = False で一度リセットする
2 フィルタしたのにデータが1件も表示されない 条件値がデータと完全一致していない(全角/半角、前後スペース等) データを事前にTrim/StrConvで統一するか、ワイルドカード *条件* を使う
3 日付でフィルタしたのに結果がおかしい 日付を文字列のまま比較している CLng(DateSerial(...)) でシリアル値に変換する
4 Field番号を間違えて別の列がフィルタされた Fieldはフィルタ範囲の左端列からの相対位置 Range(“A1”)からならField:=1がA列。Range(“C1”)からならField:=1がC列
5 フィルタ結果をコピーしたら非表示行も含まれた 通常のCopyは非表示行も含む .SpecialCells(xlCellTypeVisible).Copy で可視セルだけコピーする

FAQ

Q1. フィルタがかかっているかどうかをVBAで判定するには?

AutoFilterModeFilterMode の2つを使い分けます。


' フィルタ矢印が表示されているか
If ActiveSheet.AutoFilterMode Then
    MsgBox "フィルタ矢印あり"
End If

' 絞り込み中か(行が非表示になっているか)
If ActiveSheet.FilterMode Then
    MsgBox "絞り込み中"
End If

Q2. フィルタ後に表示されている件数を数えるには?


Dim cnt As Long
On Error Resume Next
cnt = ActiveSheet.AutoFilter.Range.Columns(1) _
    .SpecialCells(xlCellTypeVisible).Count - 1  ' 見出し行を除く
On Error GoTo 0

If cnt > 0 Then
    MsgBox "表示件数: " & cnt & "件"
Else
    MsgBox "条件に一致するデータはありません"
End If

0件の場合はSpecialCellsがエラーになるので、On Error Resume Next で囲みます。cntが0のままなら「該当なし」と判定できます。エラー処理の詳しい使い方はエラー処理で止まらないマクロを作る方法を参照。

Q3. 3つ以上の値でOR条件を指定するには?

ArrayxlFilterValues を組み合わせます。


Range("A1").AutoFilter Field:=1, _
    Criteria1:=Array("営業部", "開発部", "総務部"), _
    Operator:=xlFilterValues

xlOr は2値までしか対応していないので、3値以上は必ず xlFilterValues を使ってください。

Q4. AutoFilterとAdvancedFilterの違いは?

項目 AutoFilter AdvancedFilter
操作 シート上で絞り込み表示 条件を別範囲に書いて抽出
条件指定 コード内で直接指定 セルに条件を書く
結果の出力先 同じシート(非表示で絞り込み) 別の場所にコピー可能
おすすめ場面 シンプルな絞り込み 複雑な条件・結果を別場所に出力

より高度な抽出は複数条件でデータを抽出してまとめる方法で解説しています。

Q5. 保護されたシートでフィルタを使えますか?

Protect メソッドのオプションで許可できます。


ActiveSheet.Protect Password:="pass", AllowFiltering:=True

シート保護の詳しい使い方は特定シートだけ保護・解除する方法を参照。

まとめ

この記事では、VBAでオートフィルタを自動化する方法を解説しました。

  • 基本: Range("A1").AutoFilter Field:=列番号, Criteria1:=条件 で1行でフィルタがかかる
  • 複数条件: OR条件は xlOr(2値)か xlFilterValues(3値以上)、AND条件は列ごとにAutoFilterを書く
  • 日付: CLng(DateSerial(...)) でシリアル値に変換して比較
  • 解除: AutoFilterMode = False(完全解除)、ShowAllData(絞り込みだけ解除)
  • 実務版: SpecialCells(xlCellTypeVisible).Copy でフィルタ結果だけを別シートにコピー

関連記事:

次にやりたくなること

関連記事

コメント

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