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
ポイント解説
On Error Resume Next
可視セルがない(0件)場合でも、VBAが停止しないように一時的にエラーを無視します。
参考:【VBA】On Error Resume Nextでエラーを無視してエラーの制御If visibleRange Is Nothing Then
SpecialCellsは0件時に「Nothing(空の状態)」を返すため、この判定でスキップできます。
参考:【VBA】特定のセル(空白セル・数式セル・エラーセル)を見つけ出す:SpecialCells メソッドws.AutoFilterMode = False
最後にフィルタを解除しておくことで、次回の処理に影響しません。
この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 NextとIf visibleRange Is Nothingの組み合わせで回避可能- 0件は「該当なし」という正常な状態 → エラーではなくスキップで処理
- 動的条件・複数条件・ログ出力にも応用できる
AutoFilterMode = Falseで必ずフィルタ解除を行う
VBAの安定性を高めるうえで、「0件でも止まらない構文」を覚えておくことは非常に重要です。
この仕組みを入れておくだけで、日常業務のマクロが格段に信頼できるものになります。
ぜひ今日から、「0件対策」をあなたのVBAに組み込んでみてください。