ExcelでVBAを使ってデータ処理を自動化していると、「オートフィルタで条件抽出を行ったが、該当データが1件もない」場面にしばしば遭遇します。
この状態で削除やコピーなどの処理を続行すると、VBAが 実行時エラー1004(指定された種類のセルは見つかりません) を返し、マクロが停止してしまいます。
このような問題を防ぐためには、該当データがない場合にスキップして安全に終了する仕組み を入れることが重要です。
この記事では、オートフィルタで「該当なし」のときに処理をスキップする方法を、初心者でも理解できるように詳しく解説します。
目次
- ✅ なぜ「該当なしスキップ」が必要なのか
- ・通常のフィルタ処理ではエラーが出る
- ✅ 基本構文:該当なしならスキップする安全なコード
- ・最もシンプルで安定した書き方
- ✅ コードのポイント解説
- ・① On Error Resume Next で一時的にエラーを無視
- ・② If visibleRange Is Nothing Then で安全に分岐
- ・③ フィルタ解除を忘れない
- ✅ 応用:動的条件でも安全にスキップ処理を行う
- ✅ 応用:複数条件フィルタでもスキップを実現
- ✅ 応用:該当なしの場合にログを残しておく
- ✅ 注意点:スキップ処理を確実に行うためのコツ
- ・① フィルタ範囲は必ず AutoFilter.Range を使う
- ・② On Error Resume Next は必要最小限に
- ・③ フィルタ解除を忘れない
- ✅ 実務での活用例:自動レポート生成でスキップを活用
- ✅ まとめ:オートフィルタの「該当なし」は安全にスキップ!
✅ なぜ「該当なしスキップ」が必要なのか
・通常のフィルタ処理ではエラーが出る
次のような単純なマクロを見てみましょう。
Sub DeleteFilteredRows()
Range("A1").AutoFilter Field:=1, Criteria1:="完了"
Range("A1").CurrentRegion.Offset(1, 0).SpecialCells(xlCellTypeVisible).EntireRow.Delete
End Sub
一見シンプルで正しく見えますが、
もし「完了」に該当するデータが1件もなかった場合、以下のようなエラーが発生します。
参考:【VBA】RangeクラスのSelectメソッドが失敗しました:1004
実行時エラー '1004':指定された種類のセルは見つかりません。
つまり、該当データが存在しないときに .SpecialCells(xlCellTypeVisible)
が対象を見つけられずにエラーを出すのです。
このエラーを防ぐために、VBAでは「可視セルがあるかどうか」を事前に確認する必要があります。
参考:【VBA】条件に一致するセルを取得する方法|Find・For Each・SpecialCells
✅ 基本構文:該当なしならスキップする安全なコード
・最もシンプルで安定した書き方
Sub SafeDeleteFilteredRows()
Dim ws As Worksheet
Dim rng As Range
Dim visibleRange As Range
Set ws = ThisWorkbook.Sheets("データ")
' A列で「完了」を抽出
ws.Range("A1").AutoFilter Field:=1, Criteria1:="完了"
' フィルタ範囲を取得
Set rng = ws.AutoFilter.Range
' フィルタ後の可視セルを取得(ヘッダー除外)
On Error Resume Next
Set visibleRange = rng.Offset(1, 0).Resize(rng.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初心者が最初に覚えるべき「安定したオートフィルタ処理」と言っても良い構成です。
参考:【VBA】On Error Resume Nextでエラーを無視してエラーの制御
✅ コードのポイント解説
・① On Error Resume Next で一時的にエラーを無視
SpecialCells(xlCellTypeVisible)
は、表示されているセルが1件もないときにエラーを返します。
そのため、一時的にエラーを無視して、後で「該当がない」かどうかを自分で判定します。
参考:【VBA】特定のセル(空白セル・数式セル・エラーセル)を見つけ出す:SpecialCells メソッド
・② If visibleRange Is Nothing Then で安全に分岐
該当データがない場合、visibleRange
には何も代入されない(=Nothingのまま)ので、
この条件を利用して安全にスキップできます。
参考:【VBA】Findが見つからないときの原因と解決方法|Nothing判定・コードの書き方を解説
・③ フィルタ解除を忘れない
スキップする場合でも、最後に ws.AutoFilterMode = False
でフィルタ状態を解除しておくと、
後続処理への影響を防げます。
特に複数マクロを連続実行する環境では、この行が安定動作の鍵になります。
✅ 応用:動的条件でも安全にスキップ処理を行う
実務では、固定条件だけでなく「セルや変数で指定された値」を使ってフィルタをかけることもよくあります。
この場合でも、同じ考え方で安全にスキップ処理が可能です。
Sub DynamicFilterSkip()
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】処理を止める「Exit」の使い方|Sub・Function・ループでの中断方法を解説
✅ 応用:複数条件フィルタでもスキップを実現
オートフィルタでは Operator:=xlOr
などを使って複数条件を設定することもありますが、
その場合でも可視セルの有無をチェックする方法は同じです。
Sub MultiConditionFilterSkip()
Dim ws As Worksheet
Dim visibleRange As Range
Set ws = ThisWorkbook.Sheets("データ")
' A列で「完了」または「中止」を抽出
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
複数条件のときも、「Nothingチェック」 さえ入っていれば、どんな条件にも対応可能です。
✅ 応用:該当なしの場合にログを残しておく
スキップしただけでは後から判断できないため、
「どの条件でスキップされたか」をログシートに残しておくのも実務的な工夫です。
Sub FilterSkipWithLog()
Dim ws As Worksheet
Dim logWs As Worksheet
Dim visibleRange As Range
Dim nextRow As Long
Dim condition As String
Set ws = ThisWorkbook.Sheets("データ")
Set logWs = ThisWorkbook.Sheets("ログ")
condition = ws.Range("E1").Value
ws.Range("A1").AutoFilter Field:=2, Criteria1:=condition
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 = "条件「" & condition & "」:該当なし(" & 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
このようにログを残せば、後で「なぜ処理されなかったのか」を簡単に確認できます。
実務で信頼性を高めるうえで非常に有効です。
✅ 注意点:スキップ処理を確実に行うためのコツ
・① フィルタ範囲は必ず AutoFilter.Range を使う
CurrentRegion
でも動作しますが、フィルタ範囲外のデータが含まれる可能性があります。
確実に対象範囲を取得するために、ws.AutoFilter.Range
を使うのが推奨です。
・② On Error Resume Next は必要最小限に
SpecialCells
の部分だけに使い、直後で On Error GoTo 0
で解除するのが安全です。
長い範囲でエラー無視を使うと、他のバグを見逃してしまうことがあります。
・③ フィルタ解除を忘れない
AutoFilterMode = False
を毎回入れておくことで、後続処理が安定します。
特にループ処理や複数条件の自動処理では欠かせません。
✅ 実務での活用例:自動レポート生成でスキップを活用
営業レポートや日次報告の自動化で、
「データが存在しない営業担当者はスキップして次へ進む」処理にこの仕組みを使うことができます。
For Each担当者 In 担当者リスト
Call ReportFor担当者(担当者)
Next担当者
このようなループ内で「該当なしスキップ」を組み込んでおけば、
マクロが止まることなくすべての処理をスムーズに実行できます。
特に複数部門・複数日付の帳票生成では、この安全設計が大きな差を生みます。
✅ まとめ:オートフィルタの「該当なし」は安全にスキップ!
SpecialCells(xlCellTypeVisible)
は該当なしのときエラーを返すOn Error Resume Next
とIf visibleRange Is Nothing Then
の組み合わせで安全にスキップ- 動的条件・複数条件でも同じ仕組みで対応可能
- ログ出力やフィルタ解除を加えるとさらに実務で安定
- 自動レポートや削除処理など、業務自動化で欠かせない基本構文
「該当なしスキップ」を組み込むことで、マクロが途中で止まらず、安心して繰り返し運用できるようになります。
日常業務を自動化するうえで欠かせない安全設計です。
ぜひこの記事のコードをそのまま活用して、「落ちないVBA」 を実現してください。