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

【VBA】可視セルの一つ下に移動・取得する方法|非表示行をスキップして正確に処理

Excelでデータを扱っていると、「見えているセルの一つ下に移動したい」「フィルタ後の次の可視セルを取得したい」という場面があります。

しかし、単純に Offset(1, 0) を使うと、非表示の行やフィルタで隠されたセルまで含まれてしまうため、意図しないセルを参照してしまうことがあります。

このような問題を解決するには、「可視セルの一つ下」を取得する方法を正しく理解する必要があります。
この記事では、SpecialCells(xlCellTypeVisible) を活用して、見えている次のセルだけに移動・処理する方法を実務的に解説します。

✅ なぜ「可視セルの一つ下」が必要なのか

・フィルタ後や非表示行を含む処理で誤動作を防ぐため

オートフィルタや行の非表示を使ってデータを整理している場合、見た目では連続しているように見えるセルでも、実際の行番号には間が空いていることがあります。
たとえば以下のような表を考えてみましょう。

行番号A列(データ)表示状態
1東京表示
2大阪非表示
3名古屋表示
4福岡表示

この状態で「A1 の一つ下へ移動」としたとき、
Range("A1").Offset(1, 0) は A2(非表示)を返してしまいます。
しかし本当に求めたいのは、次に見えているセル(A3) です。
このように、通常のOffsetでは「見た目の次のセル」を取得できないため、VBAで可視セルを扱うテクニックが必要になります。


✅ 可視セルの一つ下を取得する基本構文

・SpecialCellsを活用する基本例

Sub GetNextVisibleCell()
    Dim ws As Worksheet
    Dim visibleCells As Range
    Dim cell As Range
    Dim nextCell As Range

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

    ' 可視セルを取得
    On Error Resume Next
    Set visibleCells = ws.Range("A1:A10").SpecialCells(xlCellTypeVisible)
    On Error GoTo 0

    ' 取得できない場合は終了
    If visibleCells Is Nothing Then
        MsgBox "可視セルが見つかりません。", vbExclamation
        Exit Sub
    End If

    ' 現在のセルをA1と仮定
    Set cell = ws.Range("A1")

    ' 一つ下の可視セルを取得
    For Each nextCell In visibleCells
        If nextCell.Row > cell.Row Then
            MsgBox "一つ下の可視セルは " & nextCell.Address & " です。", vbInformation
            Exit For
        End If
    Next nextCell
End Sub

このコードでは、

  1. 対象範囲の可視セルをまとめて取得
  2. 現在セルより下の行を探して最初に見つかったセルを表示
    という流れで、「次に見えているセル」を正確に判定します。参考:【VBA】条件に一致するセルを複数取得する方法|Find・For Each・SpecialCells

✅ コードのポイント解説

・1. SpecialCells(xlCellTypeVisible) の役割

このメソッドは「現在表示されているセルだけ」を取得します。
非表示の行・列、フィルタで除外されたセルは含まれません。
そのため、Offsetでは取得できない「見た目上の次のセル」を探すのに適しています。

・2. For Each で行番号を比較

可視セルは飛び飛びになる場合があるため、
If nextCell.Row > cell.Row Then で行番号を比較し、
「現在より下の最初の可視セル」を見つけ出しています。

参考:【VBA】For Each ステートメントの使い方と活用例

・3. エラー制御を入れて安全化

SpecialCells は該当セルがないときにエラーを返します。
On Error Resume Next を使って安全にスキップすることで、データが空でも止まらずに実行可能です。

参考:【VBA】On Error Resume Nextでエラーを無視してエラーの制御


✅ 応用例①:オートフィルタ後の可視セルを対象に一つ下へ移動

実務では、「フィルタで抽出されたデータの中で次のセルへ移動したい」という場面が多いです。
次の例では、オートフィルタを設定した上で可視セルの一つ下を取得しています。

Sub MoveToNextVisibleAfterFilter()
    Dim ws As Worksheet
    Dim rng As Range
    Dim visibleCells As Range
    Dim cell As Range
    Dim nextCell As Range

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

    ' B列で「完了」以外を抽出
    ws.Range("A1").AutoFilter Field:=2, 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

    ' 先頭セルを設定
    Set cell = ws.Range("A2")

    ' 一つ下の可視セルを取得
    For Each nextCell In visibleCells
        If nextCell.Row > cell.Row Then
            ws.Activate
            nextCell.Select
            MsgBox "次の可視セルに移動しました:" & nextCell.Address, vbInformation
            Exit For
        End If
    Next nextCell

    ws.AutoFilterMode = False
End Sub

このマクロでは、

  1. フィルタで「完了」以外の行を表示
  2. 可視セルを取得
  3. 現在位置より下の可視セルを特定して選択
    という流れで動作します。参考:【VBA】フィルタを使って空白行を削除する方法|効率的にデータを整理しよう



✅ 応用例②:次の可視セルを取得して値を入力

見えているデータの中で、現在位置の一つ下に自動入力したい場合もあります。
たとえば、業務報告データで次の入力位置を自動で見つけたいときに便利です。

Sub WriteToNextVisibleCell()
    Dim ws As Worksheet
    Dim visibleCells As Range
    Dim cell As Range
    Dim nextCell As Range

    Set ws = ThisWorkbook.Sheets("データ")
    Set cell = ws.Range("B2") ' 現在セル

    On Error Resume Next
    Set visibleCells = ws.Range("B2:B50").SpecialCells(xlCellTypeVisible)
    On Error GoTo 0

    If visibleCells Is Nothing Then Exit Sub

    For Each nextCell In visibleCells
        If nextCell.Row > cell.Row Then
            nextCell.Value = "次のデータ"
            MsgBox "一つ下の可視セルに値を入力しました:" & nextCell.Address, vbInformation
            Exit For
        End If
    Next nextCell
End Sub

このようにすれば、非表示セルを飛ばして次の入力欄へ自動で書き込むことができます。
報告表・在庫管理・タスク一覧などに応用可能です。


✅ 注意点とトラブル対策

・1. 可視セルが複数列にまたがる場合

複数列範囲で SpecialCells を使うと、可視セルが複数ブロック(Areas)に分かれます。
その場合は、次のように Areas でループ処理すると確実です。

Dim area As Range
For Each area In visibleCells.Areas
    For Each nextCell In area
        ' 処理内容
    Next nextCell
Next area

・2. 最後のセルで「一つ下」が存在しない場合

最後の可視セルで次を探そうとすると何も見つからず、MsgBox が表示されません。
必要に応じて「最終セルの場合は先頭に戻す」などの条件分岐を加えると親切です。

参考:【VBA】特定のセル(空白セル・数式セル・エラーセル)を見つけ出す:SpecialCells メソッド

・3. フィルタ設定中は解除処理を忘れずに

マクロ終了時にフィルタを解除しないと、次回処理で意図しない動作になります。
最後に ws.AutoFilterMode = False を必ず入れましょう。


✅ 実務での活用例:報告リストで次の入力行を自動検出

例えば、営業日報シートで「未入力の担当者行だけ表示して順番に記入していく」といったケースがあります。
その際に、VBAで次の可視セルへ自動的に移動させることで、記入ミス防止や作業効率化が可能です。

Sub MoveToNextTask()
    Dim ws As Worksheet
    Dim visibleCells As Range
    Dim currentRow As Long
    Dim nextRow As Long
    Dim cell As Range

    Set ws = ThisWorkbook.Sheets("日報")

    ' 状況列で「未入力」を抽出
    ws.Range("A1").AutoFilter Field:=3, 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

    ' 現在位置より下の可視セルへ移動
    currentRow = ActiveCell.Row
    For Each cell In visibleCells
        If cell.Row > currentRow Then
            ws.Activate
            cell.Select
            MsgBox "次の未入力行に移動しました:" & cell.Address, vbInformation
            Exit For
        End If
    Next cell

    ws.AutoFilterMode = False
End Sub

このマクロを実行すれば、「次に入力すべき行」へ自動でカーソルが移動します。
可視セルを一つずつ進める動作は、日常業務の中で非常に重宝します。


✅ まとめ:VBAで可視セルの一つ下を取得して安全に自動化しよう

  • SpecialCells(xlCellTypeVisible) で「見えているセルのみ」を正確に取得できる
  • Offsetでは非表示行まで含まれるため、行番号比較で「次の可視セル」を判断する
  • オートフィルタと組み合わせれば、抽出データの中で次の処理対象へ安全に移動可能
  • エラー制御・フィルタ解除・最終行判定を加えると実務で安定動作
  • 報告・チェックリスト・進捗管理など、繰り返し作業の効率化に最適

「見た目どおりに動くマクロ」を作るには、可視セルを扱うVBAテクニックが欠かせません。
単純なOffsetでは再現できない「ユーザー視点の動作」を実現することで、業務の信頼性とスピードを大幅に向上できます。
ぜひ今回の方法を活用し、フィルタ後でも正確に動くスマートなマクロを作成してみてください。

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