Excel VBA 逆引き集 | フィルタで表示中の行だけ処理

Excel VBA
スポンサーリンク

フィルタで表示中の行だけ処理

フィルタ後に「見えている行だけ」を対象にする最短手は、SpecialCells(xlCellTypeVisible) を使うこと。AutoFilterの結果範囲から可視セルだけを取り出し、コピー・削除・集計・ループ処理に渡します。テーブル(ListObject)でも同様の考え方で安全に扱えます。


基本:フィルタ結果の“可視セルだけ”を取得して処理

Sub ProcessVisibleRows_Basic()
    '見出しは A1、データは A2: 以降想定
    Dim rng As Range, vis As Range
    Set rng = Range("A1").CurrentRegion        '表全体
    rng.AutoFilter Field:=2, Criteria1:="営業A" '例:B列で絞り込み

    On Error Resume Next
    Set vis = rng.SpecialCells(xlCellTypeVisible) '可視セルだけ
    On Error GoTo 0

    If Not vis Is Nothing Then
        '例:可視行だけ背景色を変更
        vis.Offset(1).EntireRow.Interior.Color = RGB(255, 235, 156)
    End If
End Sub
VB
  • ポイント:
    • SpecialCells(xlCellTypeVisible): フィルタで隠れた行を除外し、見えているセル・行だけを対象にできます。
    • CurrentRegion: 見出しセルから連続データ領域をまとめて取得して扱うと安全。

行単位で扱うときの定石(1列に限定→Rowで行番号)

Sub ProcessVisibleRows_RowWise()
    Dim lo As Range, vis As Range, c As Range
    Set lo = Range("A1").CurrentRegion
    lo.AutoFilter Field:=3, Criteria1:=">=80"  '例:C列が80以上

    '列1(見出し列)に限定して可視セルを取得
    On Error Resume Next
    Set vis = lo.Columns(1).SpecialCells(xlCellTypeVisible)
    On Error GoTo 0

    If Not vis Is Nothing Then
        For Each c In vis.Cells
            '見出し行(A1)は除外
            If c.Row > lo.Row Then
                '例:可視行だけ合計列(E)へフラグを書き込む
                Cells(c.Row, "E").Value = "対象"
            End If
        Next
    End If
End Sub
VB
  • ポイント:
    • 列を1列に絞る: 可視セル取得を列全体に対して行うと、行単位処理で列数分の重複が出る。1列に限定し、Rowで行番号を使うとスマート。
    • 行番号の使い回し: 可視セル群から行番号を抽出して、他列の更新や削除にも応用できる。

可視行だけコピー・削除・集計

Sub CopyVisibleRows()
    Dim tbl As Range, vis As Range
    Set tbl = Range("A1").CurrentRegion
    tbl.AutoFilter Field:=4, Criteria1:="=完了"

    On Error Resume Next
    Set vis = tbl.Offset(1).Resize(tbl.Rows.Count - 1).SpecialCells(xlCellTypeVisible) 'データ部のみ
    On Error GoTo 0

    If Not vis Is Nothing Then
        vis.Copy Destination:=Range("H2")
    End If
End Sub

Sub DeleteVisibleRows()
    Dim tbl As Range, vis As Range
    Set tbl = Range("A1").CurrentRegion
    tbl.AutoFilter Field:=5, Criteria1:="=0"  '例:金額=0

    On Error Resume Next
    Set vis = tbl.Offset(1).Resize(tbl.Rows.Count - 1).SpecialCells(xlCellTypeVisible)
    On Error GoTo 0

    If Not vis Is Nothing Then
        vis.EntireRow.Delete
    End If
End Sub

Sub SumVisibleRows()
    Dim tbl As Range, vis As Range, s As Double, c As Range
    Set tbl = Range("A1").CurrentRegion
    tbl.AutoFilter Field:=2, Criteria1:="営業A"

    On Error Resume Next
    Set vis = tbl.Offset(1).Resize(tbl.Rows.Count - 1).Columns(5).SpecialCells(xlCellTypeVisible) '金額列(E)
    On Error GoTo 0

    If Not vis Is Nothing Then
        For Each c In vis
            s = s + Val(c.Value)
        Next
        Range("G2").Value = s
    End If
End Sub
VB
  • ポイント:
    • データ部に限定: 見出しを除いてデータ部だけを対象にするため Offset/Resize で1行下から範囲指定するのが定番。
    • 可視列だけ集計: 金額列の可視セルだけを回して合計すれば、フィルタ条件に一致するデータの集計が簡単。

テーブル(ListObject)の可視行だけ処理

Sub ProcessVisibleRows_ListObject()
    Dim lo As ListObject, vis As Range, r As Range
    Set lo = ActiveSheet.ListObjects("売上テーブル")

    '例:担当=営業Aで絞り込み(列名で指定)
    lo.Range.AutoFilter Field:=lo.ListColumns("担当").Index, Criteria1:="営業A"

    On Error Resume Next
    Set vis = lo.DataBodyRange.SpecialCells(xlCellTypeVisible) 'データ部の可視セル
    On Error GoTo 0

    If Not vis Is Nothing Then
        For Each r In vis.Areas
            '各可視ブロックの行に対して処理
            r.EntireRow.Interior.Color = RGB(198, 239, 206)
        Next
    End If
End Sub
VB
  • ポイント:
    • DataBodyRange: テーブルのデータ部だけに限定して SpecialCells するのが安全。
    • 列名で指定: ListColumns(“列名”).Index で列を特定すれば、列順が変わっても壊れにくい。

実務テンプレート:フィルタ状態の初期化→適用→可視行ループ

Sub VisibleRowsPipeline()
    Dim ws As Worksheet: Set ws = ActiveSheet
    Dim rg As Range, vis As Range, c As Range
    Set rg = ws.Range("A1").CurrentRegion

    '既存フィルタをクリア(安全運用)
    If ws.FilterMode Then ws.ShowAllData

    '新規条件でフィルタ
    rg.AutoFilter Field:=3, Criteria1:=">=20", Operator:=xlAnd, Criteria2:="<30" '例:年齢20代

    '見出し列に限定して可視セルを取得
    On Error Resume Next
    Set vis = rg.Columns(1).SpecialCells(xlCellTypeVisible)
    On Error GoTo 0

    If Not vis Is Nothing Then
        For Each c In vis.Cells
            If c.Row > rg.Row Then
                '例:可視行の氏名(A列)をメッセージに出す
                Debug.Print Cells(c.Row, "A").Value
            End If
        Next
    End If
End Sub
VB
  • ポイント:
    • ShowAllData: 既存の別条件フィルタが残っていると誤動作しやすい。開始前にクリアしてから適用が安定。
    • 可視セル取得→Row活用: 列1に限定し Row を使って、行単位の処理に展開するのが定番。

実務の落とし穴と対策

  • 可視セルが0件のときのエラー: SpecialCells は0件だとエラーになるため、On Error と Nothing チェックでガードする。
  • 列複数での重複取得: 表全体で可視セルを取得すると列数分セルが返り、行単位処理で重複になる。1列に限定して Row を使う。
  • テーブルと通常範囲の違い: テーブルは DataBodyRange を使うなど、対象の取り方が異なる。ListObjectのAPIを優先。
  • 既存フィルタの干渉: FilterModeを確認し、必要に応じて ShowAllData で解除してから新条件を適用する。
タイトルとURLをコピーしました