VBAで自動化 VBA一覧 フィルター結果の取得・判定 抽出・検索処理

【VBA】フィルター時のエラーを回避する方法|実務で止まらないマクロ設計のコツ

ExcelVBAでデータ処理を自動化する際、よく利用されるのが 「オートフィルタ」 機能です。
特定の条件でデータを抽出したり、該当する行を削除・転記するなど、業務効率化に欠かせない機能ですが、同時に「フィルター関連のエラー」でマクロが止まることも多いものです。

たとえば、

  • フィルタをかけたが該当データがなかった
  • オートフィルタが未設定のシートで .AutoFilter.Range を呼び出した
  • フィルタを解除し忘れて次の処理でエラーになった

といったトラブルは、実務で非常によく起こります。

この記事では、VBAでフィルタ処理を行う際の典型的なエラー原因とその回避方法を、実際のコード例を交えて詳しく紹介します。

✅ フィルターでよく起こる3つのエラー原因

VBAでフィルタを使うときに特に多いのは、次の3つのエラーです。

・① 「指定された種類のセルは見つかりません」エラー(1004)

これは、SpecialCells(xlCellTypeVisible) を使ったときに可視セルが存在しない場合に発生します。
つまり、フィルタ結果が0件だった場合です。

参考:【VBA】特定のセル(空白セル・数式セル・エラーセル)を見つけ出す:SpecialCells メソッド

・② 「オートフィルタが設定されていません」エラー

ws.AutoFilter.Range を参照したときに、シートにオートフィルタが存在しないとエラーになります。
意図せず削除されていたり、新しいデータに置き換えた後などに発生しやすいです。

参考:【VBA】可視セルがない場合の安全な処理方法|エラー回避と実務での応用

・③ フィルタ解除忘れによる後続処理エラー

一度フィルタを設定したまま次の操作に進むと、意図しないデータが隠れた状態で処理が実行され、削除・コピーなどの結果が崩れることがあります。

これらを防ぐには、「事前チェック」+「エラー回避構文」+「フィルタ解除」 の3つを徹底することがポイントです。

参考:【VBA】フィルターの一部だけを解除する方法|特定列だけ再表示したいときの解決策


✅ エラー回避の基本構文:On Error と Nothingチェック

・基本的な安全構成の例

Sub SafeFilterProcess()
    Dim ws As Worksheet
    Dim visibleRange As Range

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

    ' --- フィルタ設定(例:A列で「完了」を抽出) ---
    ws.Range("A1").AutoFilter Field:=1, Criteria1:="完了"

    ' --- 可視セルを取得(ヘッダーを除く) ---
    On Error Resume Next
    Set visibleRange = ws.AutoFilter.Range.Offset(1, 0).Resize(ws.AutoFilter.Range.Rows.Count - 1).SpecialCells(xlCellTypeVisible)
    On Error GoTo 0

    ' --- 可視セルがない場合の処理 ---
    If visibleRange Is Nothing Then
        MsgBox "該当データがないため、処理をスキップします。", vbInformation
        ws.AutoFilterMode = False
        Exit Sub
    End If

    ' --- データ処理(例:削除) ---
    visibleRange.EntireRow.Delete

    ' --- フィルタ解除 ---
    ws.AutoFilterMode = False
    MsgBox "完了データを削除しました。", vbInformation
End Sub

この構文では、フィルタで該当データがなかったときもマクロが止まらず、
「該当なし→スキップ」という安全な流れを実現しています。

参考:【VBA】Findの戻り値を理解する方法|Nothing判定と実務での活用例を解説

参考:【VBA】On Error Resume Nextでエラーを無視してエラーの制御


✅ コード解説:なぜこの方法で安全に動くのか

・1. On Error Resume Next で一時的にエラーを無視

SpecialCells(xlCellTypeVisible) は、表示セルが存在しないときにエラー1004を返します。
これを防ぐために、一時的にエラーを無視し(Resume Next)、その直後で明示的に判定を行います。

・2. If visibleRange Is Nothing で該当なしを判定

該当セルがなかった場合、visibleRange には何も代入されず「Nothing」になります。
この状態を利用して「スキップ」などの条件分岐を行うのが最も安定的です。

・3. AutoFilterMode = False でフィルタ解除

どんな場合でも最後にフィルタを解除しておくことで、後続処理への影響を防ぎます。
特に連続でマクロを実行するような環境では重要なポイントです。


✅ フィルタ設定前に「オートフィルタが存在するか」を確認

オートフィルタが設定されていない状態で AutoFilter.Range を呼び出すとエラーになります。
この場合は、If ws.AutoFilterMode = False Then で事前チェックを行いましょう。

If ws.AutoFilterMode = False Then
    MsgBox "オートフィルタが設定されていません。", vbExclamation
    Exit Sub
End If

また、「シートにオートフィルタはあるが、フィルタ条件が未設定」の場合は、FilterMode プロパティを使って確認できます。

If ws.FilterMode = False Then
    MsgBox "現在フィルタは適用されていません。", vbInformation
End If

この2つを組み合わせることで、どのような状態でもマクロが安全に動作します。

参考:【VBA】フィルター結果を取得する方法|抽出データを自在に活用する実践テクニック




✅ 応用:エラー回避付きの「動的条件フィルタ」

実務では、毎回同じ条件ではなく、セルや変数の値を使って条件を設定するケースも多いです。
動的条件でも同じ構文でエラーを防げます。

Sub DynamicFilterSafe()
    Dim ws As Worksheet
    Dim key As String
    Dim visibleRange As Range

    Set ws = ThisWorkbook.Sheets("データ")
    key = ws.Range("E1").Value ' 条件をセルから取得

    ' --- オートフィルタ設定 ---
    ws.Range("A1").AutoFilter Field:=1, Criteria1:=key

    ' --- 可視セル取得(安全構文) ---
    On Error Resume Next
    Set visibleRange = ws.AutoFilter.Range.Offset(1, 0).Resize(ws.AutoFilter.Range.Rows.Count - 1).SpecialCells(xlCellTypeVisible)
    On Error GoTo 0

    If visibleRange Is Nothing Then
        MsgBox "条件「" & key & "」に該当するデータはありません。", vbInformation
        ws.AutoFilterMode = False
        Exit Sub
    End If

    ' --- 該当がある場合の処理 ---
    visibleRange.Copy Destination:=ThisWorkbook.Sheets("結果").Range("A1")

    ws.AutoFilterMode = False
    MsgBox "条件「" & key & "」のデータを転記しました。", vbInformation
End Sub

このように、「可視セルがない場合はスキップ」+「フィルタ解除」 を組み合わせれば、
どんな条件でも止まらない安定したマクロを実現できます。

参考:【VBA】オートフィルタの対象がない場合に何もしないようにする方法|安全な自動処理の基本


✅ 応用:複数条件フィルタでもエラーを防ぐ

Operator:=xlOr などを使って複数条件を設定した場合も、基本は同じ構文でエラーを防げます。

Sub MultiConditionSafe()
    Dim ws As Worksheet
    Dim visibleRange As Range

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

    ws.Range("A1").AutoFilter Field:=1, Criteria1:="完了", Operator:=xlOr, Criteria2:="中止"

    On Error Resume Next
    Set visibleRange = ws.AutoFilter.Range.Offset(1, 0).Resize(ws.AutoFilter.Range.Rows.Count - 1).SpecialCells(xlCellTypeVisible)
    On Error GoTo 0

    If visibleRange Is Nothing Then
        MsgBox "完了・中止データが見つかりません。", vbInformation
        ws.AutoFilterMode = False
        Exit Sub
    End If

    visibleRange.EntireRow.Delete
    ws.AutoFilterMode = False
    MsgBox "該当データを削除しました。", vbInformation
End Sub

複数条件でも同じエラー(1004)が発生するため、この「Nothingチェック」は必須です。


✅ 高速化と安定化のための補足テクニック

・1. 画面更新を止める

フィルタや削除を繰り返す処理では、画面更新を止めると処理速度が向上します。

Application.ScreenUpdating = False
' 処理本体
Application.ScreenUpdating = True
 参考:【VBA】Application.ScreenUpdatingプロパティの使用方法と特徴

・2. 再計算を一時停止

数式が多いブックでは、再計算を止めると安定します。

Application.Calculation = xlCalculationManual
' 処理
Application.Calculation = xlCalculationAutomatic

・3. フィルタ解除を忘れない

マクロ終了時に必ず ws.AutoFilterMode = False を入れておきましょう。
フィルタが残ると、次回実行時に範囲指定がずれて予期せぬ挙動になります。

参考:【VBA】フィルター解除を全て実行する方法|複数シート・複数フィルター対応の完全自動化解説


✅ 実務での活用例:自動レポート作成のエラー防止

日次・週次レポートの自動生成では、営業部門などのデータを条件ごとに抽出する処理が多く使われます。
たとえば、全社員リストから部門別にデータを抽出する場合、
「該当データがない部門」があってもマクロを止めずに処理を続行する必要があります。

For Each 部門名 In 部門一覧
    Call FilterByDepartment(部門名)
Next 部門名

ここに「可視セルがない場合はスキップ」を入れておけば、
どの部門にもデータがなくても全体処理が止まることはありません。
これが“止まらない自動化”の鍵です。


✅ まとめ:VBAフィルターのエラーは事前チェックで確実に防げる

  • SpecialCells(xlCellTypeVisible) は可視セルがないとエラー1004を返す
  • On Error Resume NextIf visibleRange Is Nothing Then の組み合わせで回避可能
  • AutoFilterModeFilterMode でフィルタ状態をチェック
  • フィルタ解除 (AutoFilterMode=False) を常に最後に入れる
  • 動的条件・複数条件にも共通して使える汎用構文

オートフィルタはVBAの中でも特に便利な機能ですが、
エラー対策を入れないと「現場で止まるマクロ」になってしまいます。
今回紹介した安全構文を取り入れることで、どんなデータ状況でも落ちない堅牢なVBA を構築できます。

ぜひ、あなたの業務マクロにもこのエラー回避テクニックを組み込み、
「安定して動くプロのVBA」を目指してください。

-VBAで自動化, VBA一覧, フィルター結果の取得・判定, 抽出・検索処理