ExcelでVBAを使ってデータを自動処理する際、よく使われるのが「可視セル(見えているセル)」の操作です。
たとえばフィルタで抽出された行や、非表示行を除いた範囲だけを処理するなど、実務では頻繁に登場します。
しかしこのとき、「可視セルが1つもない」状態で SpecialCells(xlCellTypeVisible)
を実行すると、
次のようなエラーが発生します。
実行時エラー '1004': 指定された種類のセルは見つかりません。
つまり、フィルタで絞り込みすぎて結果がゼロ件になったり、すべての行を非表示にしていた場合、
そのまま処理を続けるとマクロが止まってしまうのです。
この記事では、「可視セルがない場合にエラーを出さず安全にスキップするVBAの書き方」 を、実務目線で解説します。
目次
- ✅ 可視セルとは?VBAでの扱い方をおさらい
- ・「可視セル」はフィルタや非表示設定後に残っているセル
- ✅ 可視セルがない場合に発生するエラーの原因
- ・エラー内容:「指定された種類のセルは見つかりません」
- ・なぜエラーが発生するのか
- ✅ 基本対策:可視セルがない場合にスキップするコード
- ✅ 応用例①:フィルタ後のデータを扱うときのエラー防止
- ✅ 応用例②:可視セルがあるときだけ合計を計算する
- ✅ 応用例③:バックアップ処理で可視セルがない場合をスキップ
- ✅ 注意点と実務でのコツ
- ・1. On Error Resume Next は範囲を限定して使う
- ・2. Nothing チェックはVBAでの鉄則
- ・3. フィルタ解除や画面更新制御を加えるとより安定
- ✅ 実務での応用:複数ブック処理でも安全にスキップ
- ✅ まとめ:可視セルがない場合は安全にスキップしよう
✅ 可視セルとは?VBAでの扱い方をおさらい
・「可視セル」はフィルタや非表示設定後に残っているセル
可視セルとは、「現在表示されているセル」を意味します。
オートフィルタで条件を絞ったり、行・列を非表示にした状態で残っているセルのことです。
通常、VBAでこれを取得するには以下のように記述します。
Set rng = Range("A1:A10").SpecialCells(xlCellTypeVisible)
このコードを実行すると、範囲A1:A10のうち見えているセルのみが取得されます。
非表示のセルやフィルタで除外された行は含まれません。
しかし、もし可視セルが1つもない場合(つまりすべて非表示)には、VBAが対象を見つけられず、エラーを返してしまいます。
参考:【VBA】条件に一致するセルを複数取得する方法|Find・For Each・SpecialCells
✅ 可視セルがない場合に発生するエラーの原因
・エラー内容:「指定された種類のセルは見つかりません」
以下のようなシンプルなコードでも、対象範囲に可視セルがなければエラーになります。
Sub SampleError()
Dim rng As Range
Set rng = Range("A1:A10").SpecialCells(xlCellTypeVisible)
End Sub
もしA1:A10のすべての行が非表示、またはフィルタで隠されている場合、
このマクロは実行時エラー1004で停止します。
参考:【VBA】RangeクラスのSelectメソッドが失敗しました:1004
・なぜエラーが発生するのか
SpecialCells
メソッドは、「該当するセルが1つもないとき」にエラーを返す仕様だからです。
他のメソッドのように「Nothing」や空の範囲を返すわけではないため、
エラー制御を自分で書かなければなりません。
参考:【VBA】特定のセル(空白セル・数式セル・エラーセル)を見つけ出す:SpecialCells メソッド
✅ 基本対策:可視セルがない場合にスキップするコード
最も基本的で安全な対策は、「エラーを一時的に無視して、可視セルが取得できなかったら何もしない」構成です。
Sub SafeVisibleCells()
Dim ws As Worksheet
Dim rng As Range
Dim visibleRange As Range
Set ws = ThisWorkbook.Sheets("データ")
Set rng = ws.Range("A1:A20")
' 可視セルを取得(対象がない場合でも停止しない)
On Error Resume Next
Set visibleRange = rng.SpecialCells(xlCellTypeVisible)
On Error GoTo 0
' 可視セルがない場合はスキップ
If visibleRange Is Nothing Then
MsgBox "可視セルがありません。処理をスキップしました。", vbInformation
Exit Sub
End If
' 可視セルがある場合のみ処理
visibleRange.Interior.Color = vbYellow
MsgBox "可視セルを検出し、色を変更しました。", vbInformation
End Sub
このコードでは、
On Error Resume Next
で一時的にエラーを無視
参考:【VBA】On Error Resume Nextでエラーを無視してエラーの制御- 可視セルがないときは
visibleRange
がNothing
のまま If visibleRange Is Nothing Then
で条件分岐し、安全にスキップ
という流れで、「可視セルがない場合でもエラーを出さずに終了」できます。
✅ 応用例①:フィルタ後のデータを扱うときのエラー防止
実務では、オートフィルタで条件抽出した結果に対して処理を行うケースが多いです。
たとえば、以下のように「完了」のデータだけ削除するマクロを考えます。
Sub DeleteFilteredRows()
Dim ws As Worksheet
Dim visibleCells As Range
Set ws = ThisWorkbook.Sheets("データ")
' A列で「完了」行を抽出
ws.Range("A1").AutoFilter Field:=1, Criteria1:="完了"
' 可視セル取得(ヘッダー除外)
On Error Resume Next
Set visibleCells = ws.AutoFilter.Range.Offset(1, 0).Resize(ws.AutoFilter.Range.Rows.Count - 1).SpecialCells(xlCellTypeVisible)
On Error GoTo 0
' 該当なし → スキップ
If visibleCells Is Nothing Then
MsgBox "「完了」データが存在しないため、処理をスキップしました。", vbInformation
ws.AutoFilterMode = False
Exit Sub
End If
' 該当があれば削除
visibleCells.EntireRow.Delete
ws.AutoFilterMode = False
MsgBox "完了データを削除しました。", vbInformation
End Sub
このマクロは、該当がないときに「可視セルがありません」と判断してスキップするため、
業務中に止まることがなく、安定した運用が可能です。
参考:【VBA】オートフィルタ後の可視セルを取得する方法|抽出データだけを扱う実務テクニック
✅ 応用例②:可視セルがあるときだけ合計を計算する
集計処理でも「可視セルがない」可能性があります。
たとえば、フィルタ後の売上データを合計する場合、対象データがなければ WorksheetFunction.Sum
は0を返せますが、
SpecialCells
を使うときはエラー対策が必要です。
Sub SumVisibleCells()
Dim ws As Worksheet
Dim visibleRange As Range
Dim total As Double
Set ws = ThisWorkbook.Sheets("データ")
On Error Resume Next
Set visibleRange = ws.Range("C2:C100").SpecialCells(xlCellTypeVisible)
On Error GoTo 0
If visibleRange Is Nothing Then
MsgBox "可視セルがありません。合計を計算できません。", vbExclamation
Exit Sub
End If
total = WorksheetFunction.Sum(visibleRange)
MsgBox "可視セルの合計値は " & total & " です。", vbInformation
End Sub
このように If visibleRange Is Nothing Then
を加えておくと、
データが0件でもマクロが安全に終了します。
参考:【VBA】オートフィルタの対象がない場合に何もしないようにする方法|安全な自動処理の基本
✅ 応用例③:バックアップ処理で可視セルがない場合をスキップ
レポートや集計結果を別シートにコピーするマクロでも、可視セルがないときはコピー対象が存在せずエラーになります。
次のように記述すれば、自動でスキップできます。
Sub CopyVisibleCells()
Dim ws As Worksheet
Dim visibleCells As Range
Set ws = ThisWorkbook.Sheets("データ")
On Error Resume Next
Set visibleCells = ws.Range("A1").CurrentRegion.SpecialCells(xlCellTypeVisible)
On Error GoTo 0
If visibleCells Is Nothing Then
MsgBox "コピー対象の可視セルがありません。", vbExclamation
Exit Sub
End If
visibleCells.Copy Destination:=ThisWorkbook.Sheets("結果").Range("A1")
MsgBox "可視セルをコピーしました。", vbInformation
End Sub
実務では「データが存在しない場合にコピーしない」ことが多いため、
このスキップ構造は非常に役立ちます。
参考:【VBA】特定の文字を含む列の処理:検索・削除・別シートにコピー
✅ 注意点と実務でのコツ
・1. On Error Resume Next は範囲を限定して使う
全体でエラーを無視するのは危険です。
必ず SpecialCells
の直前と直後だけに入れるようにしましょう。
・2. Nothing チェックはVBAでの鉄則
Is Nothing
を忘れると、可視セルがない状態で処理を続けてしまい、
Object variable or With block variable not set
という別のエラーが発生します。
・3. フィルタ解除や画面更新制御を加えるとより安定
大量データを扱う場合は、以下を加えて高速化・安定化を図るのもおすすめです。
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
' 処理本体
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
✅ 実務での応用:複数ブック処理でも安全にスキップ
たとえば、フォルダ内の複数Excelファイルを順番に開いて処理する場合でも、
「可視セルがないファイルをスキップする」ことで自動化が止まらずスムーズに進みます。
If visibleRange Is Nothing Then
Debug.Print "ファイル:" & wb.Name & " はスキップされました。"
wb.Close SaveChanges:=False
GoTo NextFile
End If
このようにログ出力やスキップ制御を組み合わせると、
「止まらないVBA」「エラーに強い自動化」が実現できます。
✅ まとめ:可視セルがない場合は安全にスキップしよう
SpecialCells(xlCellTypeVisible)
は該当セルがないとエラーを返すOn Error Resume Next
+If rng Is Nothing Then Exit Sub
で安全に回避できる- 集計・コピー・削除・転記など、あらゆる処理に共通して使える
- スキップメッセージやログ出力を加えると信頼性が向上
- 「止まらないVBA」は、日常業務の自動化で最も重要なポイント
VBAの信頼性を高めるには、「例外ケースを潰す」ことが何より大切です。
特にフィルタや非表示を使った処理では、「可視セルがない」ケースを必ず想定しておきましょう。
このひと工夫で、業務自動化が格段に安定します。