VBAでオートフィルタを操作する方法|絞り込み・解除・集計まで現場で使えるコードをコピペOK

INFO

※本記事の数式やコードは、Microsoft 365(旧Office365)にて動作検証を行っています。


「VBAでオートフィルタを使いたいけど、どう書けばいいかわからない…」 「フィルタをかけたまま別の処理をしたいのに、うまくいかない…」

こんな悩みはありませんか?

オートフィルタは Excelの日常業務で頻繁に使う機能ですが、VBAで操作しようとすると「あれ?思った通りに動かない」と詰まりやすい箇所も多いです。

この記事では、VBAでオートフィルタを操作するための基本から応用まで、現場ですぐ使えるコードをまるごと解説します。コピペして即戦力にできるコードばかりなので、ぜひ手元で試しながら読んでみてください。


目次

オートフィルタとは?VBAで操作するとどんなことができる?

オートフィルタとは、表の列に条件を指定してデータを絞り込む機能です。手動でも使えますが、VBAで操作することで次のようなことが自動化できます。

  • 特定の条件に一致する行だけを瞬時に絞り込む
  • 絞り込んだ行だけに処理を行う(色塗り・コピー・集計など)
  • 処理が終わったらフィルタを自動で解除する

手動でフィルタをかける場合と比べると、次のような違いがあります。

比較項目手動VBA
操作時間毎回数ステップ1クリックで完了
再現性手順を覚える必要ありコードが手順を記憶
ミスのリスク条件のかけ間違いが起きやすい条件を一度書けば確実
大量データへの対応時間がかかる一瞬で処理

月次レポートの作成や、部門ごとのデータ抽出など、繰り返しの多い作業に特に威力を発揮します。


VBAでオートフィルタを使う手順

基本の構文を確認しよう

VBAでオートフィルタを操作する基本の書き方は次のとおりです。

Range("表内のセル").AutoFilter Field:=列番号, Criteria1:="条件"
  • Field :フィルタをかける列番号(表の左端の列を1とした番号)
  • Criteria1 :絞り込む条件(文字列や数値)
STEP
テーブル範囲を確認する

まず、フィルタをかけたい表がどのシートのどのセルにあるかを確認します。ここでは A1 を起点にした表を例にします。

STEP
オートフィルタをかけるコードを書く

次のコードは、A列〜D列のデータ表に対して、B列が「東京」のデータだけを絞り込む例です。

Sub フィルタをかける()
    Dim ws As Worksheet
    Dim lastRow As Long
    
    Set ws = ThisWorkbook.Worksheets("Sheet1")
    
    ' 最終行を動的に取得
    lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
    
    ' 既存のフィルタをいったん解除してから設定
    If ws.AutoFilterMode Then ws.AutoFilterMode = False
    
    ' A1:D[最終行] の範囲にフィルタをかける(B列=東京)
    ws.Range("A1:D" & lastRow).AutoFilter Field:=2, Criteria1:="東京"
End Sub
けんけん
lastRow を使って最終行を動的に取得することで、データ件数が変わっても正しい範囲にフィルタがかかります。行数を固定で書くのはNGです!
STEP
複数条件でフィルタをかける(AND・OR)

複数条件を使う場合は Criteria2Operator を追加します。

OR条件(東京または大阪):

ws.Range("A1:D" & lastRow).AutoFilter _
    Field:=2, _
    Criteria1:="東京", _
    Operator:=xlOr, _
    Criteria2:="大阪"

AND条件(数値範囲:100以上200以下):

ws.Range("A1:D" & lastRow).AutoFilter _
    Field:=3, _
    Criteria1:=">=100", _
    Operator:=xlAnd, _
    Criteria2:="<=200"
STEP
フィルタを解除するコードを書く

処理が終わったらフィルタを解除するのが鉄則です。解除方法は2通りあります。

全フィルタを完全オフにする(オートフィルタ矢印ごと消す):

If ws.AutoFilterMode Then ws.AutoFilterMode = False

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

If ws.FilterMode Then ws.ShowAllData

時短・効率化テクニック|現場で使える応用コード

テクニック1:フィルタ後の見えている行だけをコピーする

フィルタで絞り込んだ後、見えている行だけを別シートにコピーしたい場面はよくあります。

Sub フィルタ後コピー()
    Dim ws As Worksheet
    Dim wsDest As Worksheet
    Dim lastRow As Long
    
    Set ws = ThisWorkbook.Worksheets("Sheet1")
    Set wsDest = ThisWorkbook.Worksheets("抽出結果")
    
    lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
    
    ' フィルタをかける(C列が100以上)
    ws.Range("A1:D" & lastRow).AutoFilter Field:=3, Criteria1:=">=100"
    
    ' 見えているセル(SpecialCells)だけをコピー
    ws.Range("A1:D" & lastRow).SpecialCells(xlCellTypeVisible).Copy _
        Destination:=wsDest.Range("A1")
    
    ' フィルタ解除
    ws.AutoFilterMode = False
    
    MsgBox "コピー完了しました!"
End Sub
けんけん
SpecialCells(xlCellTypeVisible) を使うのが絞り込み後コピーの鉄板テクニックです。これを忘れると隠れている行もコピーされてしまいます。

テクニック2:フィルタ後の行数を数えてメッセージ表示する

絞り込んだ件数を確認したい場合は次のように書きます。

Sub フィルタ件数確認()
    Dim ws As Worksheet
    Dim lastRow As Long
    Dim visibleCount As Long
    
    Set ws = ThisWorkbook.Worksheets("Sheet1")
    lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
    
    ws.Range("A1:D" & lastRow).AutoFilter Field:=2, Criteria1:="東京"
    
    ' ヘッダー行を除いた可視行数をカウント
    visibleCount = ws.Range("A2:A" & lastRow).SpecialCells(xlCellTypeVisible).Count
    
    MsgBox "絞り込み結果:" & visibleCount & " 件"
End Sub

テクニック3:フィルタ後の合計をSUBTOTAL関数で取得する

フィルタで絞り込んだ行だけの合計を求めたい場合は WorksheetFunction.Subtotal を使います。

Sub フィルタ後合計()
    Dim ws As Worksheet
    Dim lastRow As Long
    Dim goukei As Double
    
    Set ws = ThisWorkbook.Worksheets("Sheet1")
    lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
    
    ws.Range("A1:D" & lastRow).AutoFilter Field:=2, Criteria1:="東京"
    
    ' 9 = SUBTOTAL関数のSUM(見えている行だけ合計)
    goukei = WorksheetFunction.Subtotal(9, ws.Range("C2:C" & lastRow))
    
    MsgBox "東京の合計:" & goukei
End Sub

トラブルシューティング|うまくいかないときに確認すること

症状1:「インデックスが有効範囲にありません」エラーが出る

原因Field に指定した列番号が、フィルタ範囲の列数を超えている。

解決策Field:=2 は「フィルタ範囲の左端から2列目」を意味します。Range("A1:D" & lastRow) ならA列が1、B列が2、C列が3、D列が4です。範囲外の番号を指定していないか確認してください。

症状2:絞り込んだはずなのに全データが表示される

原因:条件の文字列が完全に一致していない(スペースや全角・半角の違い)。

解決策:セルの値を直接コピーしてコードに貼り付け、意図しないスペースや文字コードの違いがないか確認してください。次のデバッグコードで確認できます。

' B2セルの実際の値を確認する
MsgBox "[" & ws.Range("B2").Value & "]"

症状3:ShowAllData 実行時に「エラー 1004」が出る

原因:フィルタがかかっていない状態で ShowAllData を呼び出している。

解決策:実行前に FilterMode で確認してから呼び出してください。

If ws.FilterMode Then ws.ShowAllData

症状4:フィルタ後のコピーで隠れた行も含まれてしまう

原因SpecialCells(xlCellTypeVisible) を使わずに Range.Copy をしている。

解決策:フィルタ後のコピーには必ず SpecialCells(xlCellTypeVisible) をセットで使ってください(前掲のテクニック1を参照)。


まとめ

  • VBAのオートフィルタは AutoFilter メソッドで操作する
  • Field は範囲の左端から数えた列番号で指定する
  • 最終行は必ず End(xlUp).Row で動的に取得する
  • フィルタ後のコピーには SpecialCells(xlCellTypeVisible) が必須
  • フィルタ後集計は WorksheetFunction.Subtotal(9, 範囲) を使う
  • 処理後は AutoFilterMode = False または ShowAllData で解除する

オートフィルタをVBAで自動化できるようになると、「毎月同じ手作業でやっていたフィルタ作業」がボタン1つで完結します。ぜひ今日から業務に組み込んでみてください!


次のステップへ進もう

オートフィルタを使いこなしたら、次はこれらの機能を覚えるとさらに業務効率が上がります。

  • VBA 最終行の取得:今回の記事でも使いましたが、これはVBA業務自動化の超基本テクニックです。データ件数が変わっても正しく動くコードを書くために必須の知識です。
  • VBA ループ処理:フィルタで絞り込んだ行に対して1行ずつ処理を行いたい場合に必要です。オートフィルタとループを組み合わせると処理の幅が一気に広がります。
  • VBA VLOOKUP・Findメソッドによるデータ検索:フィルタで絞り込む前に、別表からコードや名称を参照して条件を自動設定したい場面で役立ちます。オートフィルタと組み合わせてさらに高度な自動化が実現できます。
よかったらシェアしてね!
  • URLをコピーしました!
目次