記事ID: 062
タイトル: 【VBA】オートフィルタでデータを絞り込み・解除する方法(コピペOK)
カテゴリ: シート操作
一次キーワード: VBA オートフィルタ 抽出 解除
想定読者: 毎回同じフィルタ条件を手動でかけている事務・管理職
検索意図: VBAでオートフィルタの設定・複数条件の絞り込み・解除を自動化したい
読者の悩み(1文): 毎回同じ条件でフィルタをかける手作業が面倒
読了後にできること(1文): VBAでオートフィルタの設定・複数条件・解除をボタン1つで自動化できる
前提条件:
- Excel版: Excel 2016以降 / Microsoft 365
- OS: Windows 10/11
- 保存形式: .xlsm(マクロ有効ブック)
- 貼り付け場所: 標準モジュール
- 実行方法: マクロ実行(F5)またはボタン割り当て
更新日: 2026-03-11
Contents
この記事でわかること
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つ以上の値のどれかに一致
「営業部」「開発部」「総務部」のいずれかを表示する場合は、Array と xlFilterValues を使います:
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で判定するには?
AutoFilterMode と FilterMode の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条件を指定するには?
Array と xlFilterValues を組み合わせます。
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でフィルタ結果だけを別シートにコピー
関連記事:
- 複数条件でデータを抽出してまとめる方法 — AdvancedFilterでさらに高度な抽出
- データを複数条件で自動並び替えする方法 — フィルタ後のデータをソート
- セルの値に応じて行を自動色分けする方法 — フィルタの代わりに視覚的に区別
次にやりたくなること
- フィルタだけでなく、条件に合うデータを別シートに抽出したい → 複数条件でデータを抽出してまとめる方法
- フィルタ後のデータを並び替えたい → データを複数条件で自動並び替えする方法

コメント