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

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

ExcelでVBAを使ってデータを自動処理する際、よく使われるのが「可視セル(見えているセル)」の操作です。
たとえばフィルタで抽出された行や、非表示行を除いた範囲だけを処理するなど、実務では頻繁に登場します。

しかしこのとき、「可視セルが1つもない」状態で SpecialCells(xlCellTypeVisible) を実行すると、
次のようなエラーが発生します。

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

つまり、フィルタで絞り込みすぎて結果がゼロ件になったり、すべての行を非表示にしていた場合、
そのまま処理を続けるとマクロが止まってしまうのです。

この記事では、「可視セルがない場合にエラーを出さず安全にスキップするVBAの書き方」 を、実務目線で解説します。


✅ 可視セルとは?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

このコードでは、

  1. On Error Resume Next で一時的にエラーを無視
    参考:【VBA】On Error Resume Nextでエラーを無視してエラーの制御
  2. 可視セルがないときは visibleRangeNothing のまま
  3. 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の信頼性を高めるには、「例外ケースを潰す」ことが何より大切です。
特にフィルタや非表示を使った処理では、「可視セルがない」ケースを必ず想定しておきましょう。
このひと工夫で、業務自動化が格段に安定します。

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