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

VBA

完成イメージ(Before / After)

Before(手動フィルタ — 5部署分で30分)

Before(実行前)のExcel画面
A B C D
1 部署 氏名 日付 売上
2 営業部 田中 2026/01/15 150000
3 開発部 鈴木 2026/02/10 80000
4 営業部 佐藤 2026/02/20 200000
5 総務部 高橋 2026/03/05 50000
6 営業部 伊藤 2026/03/15 120000

毎回プルダウンで条件を選んでコピー→貼り付け→解除の繰り返し。

After(VBAで「営業部」だけ自動抽出)

After(実行後)のExcel画面
A B C D
1 部署 氏名 日付 売上
2 営業部 田中 2026/01/15 150000
3 営業部 佐藤 2026/02/20 200000
4 営業部 伊藤 2026/03/15 120000

ボタン1つで条件指定のフィルタが完了。条件ミスもゼロ。

営業部 佐藤 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 に絞り込みたい値を指定します

コードの流れを詳しく解説:

最初の If ActiveSheet.AutoFilterMode Then のブロックは、既にフィルタがONになっている場合にリセットするための処理です。AutoFilterメソッドはトグル動作(ONならOFF、OFFならON)をするため、フィルタがかかった状態でもう一度呼ぶとフィルタが解除されてしまいます。意図しない解除を防ぐために、最初に必ずリセットしてからフィルタをかけるのが安全な書き方です。

Range("A1").AutoFilter でフィルタを設定していますが、ここでA1セルを指定しているのは「データ範囲の左上」を教えるためです。Excelはここからデータの連続する範囲を自動検出してフィルタ範囲にします。途中に空行や空列があると、そこでデータ範囲が切れてしまう点には注意してください。

Field:=1 はフィルタ範囲の左端を基準にした列番号です。A1からフィルタ範囲が始まっていればField:=1はA列ですが、もしC1から始まっていればField:=1はC列になります。「シート上の何列目か」ではなく「フィルタ範囲の何列目か」という相対位置で指定する点が重要です。

前提として、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件の場合はメッセージを表示して処理をスキップ
  • コピー後にフィルタを自動解除するので、データシートは元通り

実務版コードの流れを詳しく解説:

まず On Error Resume NextOn Error GoTo 0 で囲んでいる部分は、「抽出結果」シートが存在するかどうかの確認です。存在しないシートを Sheets("抽出結果") で取得しようとするとエラーになるため、一時的にエラーを無視して変数がNothingかどうかで判定しています。シート操作でよく使うパターンなので覚えておくと便利です。

SpecialCells(xlCellTypeVisible) は、フィルタで非表示になっている行を除外して、見えている行だけを選択するメソッドです。普通にCopyすると非表示行も含まれてしまうので、この1行が極めて重要。フィルタ結果のコピーでは必ず SpecialCells を通すのが鉄則です。

PasteSpecial を2回呼んでいるのは、値と書式を別々に貼り付けるためです。xlPasteValues で値だけを貼り付け、xlPasteFormats で書式(セルの色、フォント、罫線など)を貼り付けています。xlPasteAll で一括貼り付けもできますが、数式やハイパーリンクまでコピーしたくない場合はこの方法が安全です。

Application.CutCopyMode = False は、コピー状態(セルの点線枠)を解除する処理です。これを入れておかないと、マクロ実行後もセルが点線で囲まれたままになります。

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

落とし穴

自分も最初に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 で可視セルだけコピーする
6 フィルタ後に最終行を取得したら、非表示行を含む行番号が返った End(xlUp) は非表示行も含めた最終行を返す フィルタ後の可視セルの件数は SpecialCells(xlCellTypeVisible).Count で取得する
7 フィルタ条件をセルから動的に取得したら空文字でエラーになった セルが空の状態でCriteria1に空文字を渡すとフィルタが意図通りに動かない フィルタ実行前に If Len(条件セル.Value) = 0 Then Exit Sub で空チェックを入れる

VBAでオートフィルタが解除できないときの対処法

「AutoFilterMode = False を実行したのにフィルタが消えない」という場合、原因はコードの対象シートと実際に操作しているシートが異なっていることが多い。たとえば ActiveSheet.AutoFilterMode = False と書いているのに、実際にフィルタがかかっているのは別のシートだったというケース。自分もシート名を間違えて「なぜ解除されないんだ?」と10分悩んだことがある。対処法は、Worksheets("シート名").AutoFilterMode = False のようにシート名を明示的に指定すること。また、AutoFilterMode はフィルタ矢印を消すプロパティなので、絞り込みだけ解除したい場合は ShowAllData を使う。

VBAでAutoFilterの複数条件がうまくいかないときの対処法

「3つ以上の値でOR条件のフィルタをかけたいのに、2つまでしか動かない」という場合、原因は Operator:=xlOr を使っていることだ。xlOr は2値までしか対応しておらず、3値以上を渡してもエラーにはならないが意図通りにフィルタされない。対処法は、Criteria1:=Array("値1", "値2", "値3")Operator:=xlFilterValues を組み合わせること。自分も最初これを知らなくて、3部署のOR条件が2部署しか表示されず原因究明に30分かかった。xlOr は2値限定、3値以上は xlFilterValues と覚えておけば迷わない。

VBAでフィルタ結果をコピーしたら非表示行まで含まれてしまうときの対処法

「フィルタで絞り込んだ結果だけをコピーしたいのに、非表示行のデータまでコピーされてしまう」という場合、原因は通常の Range.Copy を使っていることだ。VBAのCopyメソッドはデフォルトで非表示行も含めてコピーする。対処法は、.SpecialCells(xlCellTypeVisible).Copy で可視セルだけを選択してからコピーすること。この1行を入れるだけで、フィルタで表示されている行だけが確実にコピーされる。実務版コードではこの方法を使っているので、そのままコピペすればOKだ。

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 でフィルタ結果だけを別シートにコピー

オートフィルタはExcelの基本機能だけど、VBAで自動化すると「条件の設定ミスがなくなる」「毎回同じ操作を繰り返さなくて済む」という2つの大きなメリットがあります。特に実務版のフィルタ結果コピーは、週次・月次レポートの作成を劇的に効率化できます。フィルタ条件をセルから動的に取得する仕組みと組み合わせれば、ユーザーが条件を入力するだけで自動抽出されるツールも作れます。

関連記事:

次にやりたくなること

  • フィルタだけでなく、条件に合うデータを別シートに抽出したい複数条件でデータを抽出してまとめる方法
  • フィルタ後のデータを並び替えたい → データを複数条件で自動並び替えする方法
  • 抽出したデータをCSVに書き出したい → データをCSVファイルに書き出す方法
  • 条件に合う行だけコピーしたい → 条件に合う行をコピーする方法
  • フィルタの実行ログを残して管理したい → マクロの実行ログをファイルに自動記録する方法
  • フィルタ結果をDictionaryで集計したい → Dictionaryでデータを集計する方法

コメント

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