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

【VBA】フィルター結果が0件のときに安全に処理する方法|エラーを出さずにスキップする

ExcelVBAでオートフィルタを使ってデータ抽出を自動化していると、
「条件に一致するデータが1件もない(=0件)」というケースにしばしば遭遇します。

この状態で削除やコピーなどの処理を行おうとすると、VBAがエラーを出して止まってしまうことがあります。
実務で安定したマクロを動かすには、フィルタ結果が0件のときに安全にスキップする処理を組み込むことが欠かせません。

この記事では、VBAで「フィルター結果が0件」の場合にエラーを防ぎ、
止まらずに次の処理へ進めるための基本構文と応用テクニックを詳しく紹介します。

✅ フィルターで0件になったときに起こる典型的なエラー

オートフィルタを使ったマクロの多くは次のような構文を含んでいます。

参考:【VBA】条件に一致するセルを複数取得する方法|Find・For Each・SpecialCells

Sub FilterAndDelete()
    Range("A1").AutoFilter Field:=1, Criteria1:="完了"
    Range("A1").CurrentRegion.Offset(1, 0).SpecialCells(xlCellTypeVisible).EntireRow.Delete
End Sub

一見すると正しく動きそうですが、
もし「完了」に該当するデータが1件もなければ、次のようなエラーが発生します。

実行時エラー '1004': 指定された種類のセルは見つかりません。

これは、SpecialCells(xlCellTypeVisible) が「可視セルを見つけられない」と判断し、
対象範囲を返せないために発生するエラーです。

参考:【VBA】RangeクラスのSelectメソッドが失敗しました:1004

つまり、フィルター後に0件になったとき(可視セルなし)に備えた対策を組み込む必要があるのです。


✅ フィルター結果が0件でも止まらない安全なコード構文

以下のコードは、該当データが0件の場合に安全にスキップする構成です。
VBA初心者から実務担当者まで使える定番パターンです。

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

    ' 該当データが0件(可視セルなし)ならスキップ
    If visibleRange Is Nothing Then
        MsgBox "「完了」に該当するデータは0件のため、処理をスキップします。", vbInformation
        ws.AutoFilterMode = False
        Exit Sub
    End If

    ' 可視セル(該当データ)がある場合の処理
    visibleRange.EntireRow.Delete

    ws.AutoFilterMode = False
    MsgBox "完了データを削除しました。", vbInformation
End Sub

ポイント解説

この3ステップを組み合わせることで、どんな条件でも「止まらないVBA」が実現します。


✅ フィルター結果が0件のときにスキップする理由

実務でマクロを動かしていると、次のような状況が頻繁に発生します。

  • 月末など、一部条件に該当するデータが存在しない
  • 前処理でデータが削除され、対象が空になっている
  • 同一シートで複数条件を順番に処理している

これらのケースでは、「該当データがない」こと自体はエラーではなく正常な状態です。
したがって、「エラーにしない(スキップして次へ進む)」設計が、実務で安定した自動処理を作るカギになります。

参考:【VBA】AutoFilterの複数条件を設定する方法|AND・ORを自在に操る実務向け活用術




✅ 応用①:条件を変数で指定しても0件時に安全に処理

実際の業務では、条件がセルや変数で動的に変わることが多いです。
次の例は、セルE1に入力された値をフィルタ条件に使う場合の構文です。

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

    ' 可視セルを取得(0件対策込み)
    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 & "」に該当するデータは0件です。", vbInformation
        ws.AutoFilterMode = False
        Exit Sub
    End If

    visibleRange.Copy Destination:=ThisWorkbook.Sheets("抽出結果").Range("A1")
    ws.AutoFilterMode = False
    MsgBox "条件「" & key & "」のデータを転記しました。", vbInformation
End Sub

これにより、たとえ条件に該当するデータが0件でもマクロは止まらず、
「0件です」とメッセージを出して終了します。

参考:【VBA】処理を止める「Exit」の使い方|Sub・Function・ループでの中断方法を解説


✅ 応用②:複数条件(OR検索)でも0件判定を入れる

複数条件を設定した場合も、0件のときに同じエラーが発生します。
以下のように、Operator:=xlOr を使って複数条件を指定しても、安全に処理できます。

Sub MultiConditionFilter()
    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 "「完了」または「中止」に該当するデータは0件です。", vbInformation
        ws.AutoFilterMode = False
        Exit Sub
    End If

    visibleRange.EntireRow.Delete
    ws.AutoFilterMode = False
End Sub

このように構成しておけば、複数条件でも安定して動作します。

参考:【VBA】If文の複数条件をリストで判定する方法|効率的な条件分岐の書き方と応用


✅ 応用③:0件時にログを残す(トレース対策)

実務では、スキップされた理由を記録しておくと後からトラブルを防げます。
以下のように「0件のときだけログシートに記録する」仕組みを組み込むのもおすすめです。

Sub FilterZeroLog()
    Dim ws As Worksheet
    Dim logWs As Worksheet
    Dim visibleRange As Range
    Dim nextRow As Long

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

    ws.Range("A1").AutoFilter Field:=2, 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
        nextRow = logWs.Cells(Rows.Count, "A").End(xlUp).Row + 1
        logWs.Range("A" & nextRow).Value = "未完了データなし:" & Format(Now, "yyyy/mm/dd HH:NN:SS")
        ws.AutoFilterMode = False
        Exit Sub
    End If

    visibleRange.Copy Destination:=ThisWorkbook.Sheets("結果").Range("A1")
    ws.AutoFilterMode = False
End Sub

ログを残すことで、「0件スキップ」がいつ発生したかを後から確認でき、
自動化の信頼性を高めることができます。

参考:【VBA】特定の文字を含む列の処理:検索・削除・別シートにコピー


✅ 注意点と安定稼働のコツ

・① On Error Resume Next は限定的に使う

全体に適用するとバグを見逃す原因になります。
必ず SpecialCells の前後だけで使い、直後に On Error GoTo 0 で戻すようにしましょう。

・② AutoFilterMode の解除を忘れない

フィルタを解除しないまま次の処理を行うと、範囲ズレや処理漏れが起こります。
マクロの最後で必ず ws.AutoFilterMode = False を実行しましょう。

・③ 「0件」は正常な結果と捉える

0件はエラーではなく、「該当なし」という正しい結果です。
エラー扱いせず、スキップやログ出力で終わらせるのがプロの設計です。


✅ 実務での応用:繰り返し処理でも止まらないVBAにする

複数の条件を順に処理するようなマクロでは、「どの条件も0件」になるケースがあります。
たとえば営業部別のデータを順番に抽出するような処理です。

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

このとき、1つでもエラーが出ると全体が止まってしまいます。
しかし「0件ならスキップ」を入れておけば、すべての条件をスムーズに処理し続けられます。
これが**「止まらない自動化」**を実現するコツです。


✅ まとめ:フィルター0件でも止まらないマクロを作ろう

  • SpecialCells(xlCellTypeVisible) は0件のときにエラー1004を返す
  • On Error Resume NextIf visibleRange Is Nothing の組み合わせで回避可能
  • 0件は「該当なし」という正常な状態 → エラーではなくスキップで処理
  • 動的条件・複数条件・ログ出力にも応用できる
  • AutoFilterMode = False で必ずフィルタ解除を行う

VBAの安定性を高めるうえで、「0件でも止まらない構文」を覚えておくことは非常に重要です。
この仕組みを入れておくだけで、日常業務のマクロが格段に信頼できるものになります。
ぜひ今日から、「0件対策」をあなたのVBAに組み込んでみてください。

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