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

【VBA】フィルター後の値を取得する方法|可視セルから安全にデータを読み取る

Excelでデータを扱う際、「フィルターで抽出した結果だけを処理したい」「非表示データを除外して値を取得したい」という場面は多いものです。
しかし、VBAで通常の範囲指定を行うと、フィルターで非表示になっている行も含まれてしまうため、意図しない計算や集計ミスにつながることがあります。

このような問題を解決するためには、「フィルター後の値(=可視セルのみ)」を取得する方法を理解しておくことが重要です。
この記事では、SpecialCells(xlCellTypeVisible) を活用し、オートフィルタで抽出されたデータのみをVBAで安全に取得・処理する方法を詳しく紹介します。

✅ フィルター後の値を取得する必要性

・通常のRange指定では非表示行も含まれる

たとえば以下のようなデータをフィルタで「営業部」のみ表示している場合を考えてみましょう。

部門氏名売上
営業部田中200
開発部佐藤150
営業部山田300
開発部鈴木180

この状態で次のようなVBAを実行すると…

MsgBox WorksheetFunction.Sum(Range("C2:C5"))

結果は 「830」(全行)になります。
見た目では「営業部」だけ表示されていますが、VBAは非表示の「開発部」データも含めて計算してしまうのです。

そこで使うのが、可視セルのみを対象とする「SpecialCells」です。
参考:【VBA】条件に一致するセルを取得する方法|Find・For Each・SpecialCells


✅ フィルター後の可視セルだけを取得する基本構文

・基本コード

Sub GetFilteredValues()
    Dim ws As Worksheet
    Dim rng As Range
    Dim visibleCells As Range
    Dim cell As Range
    Dim result As String

    ' シート設定
    Set ws = ThisWorkbook.Sheets("データ")

    ' オートフィルタが設定されていなければ終了
    If ws.AutoFilterMode = False Then
        MsgBox "オートフィルタが設定されていません。", vbExclamation
        Exit Sub
    End If

    ' フィルタ範囲を取得
    Set rng = ws.AutoFilter.Range

    ' 可視セル(フィルタ後の値)を取得(ヘッダー除外)
    On Error Resume Next
    Set visibleCells = rng.Offset(1, 0).Resize(rng.Rows.Count - 1).SpecialCells(xlCellTypeVisible)
    On Error GoTo 0

    ' 可視セルの値を取得
    If Not visibleCells Is Nothing Then
        For Each cell In visibleCells.Columns(3).Cells ' 3列目(売上列)を指定
            result = result & cell.Value & vbCrLf
        Next cell
        MsgBox "フィルター後の売上値:" & vbCrLf & result, vbInformation
    Else
        MsgBox "該当データがありません。", vbExclamation
    End If
End Sub

このコードでは、

  1. オートフィルタ範囲を特定
  2. 表示されている(可視)セルだけを抽出
    参考:【VBA】オートフィルタ後の可視セルを取得する方法|抽出データだけを扱う実務テクニック
  3. 指定列の値を順番に読み取る
    という手順で、フィルタ後の値を取得しています。

✅ コード解説:動作の仕組みを理解しよう

・1. AutoFilter.Range で範囲を動的取得

表全体のフィルタ設定範囲を自動的に特定します。
固定範囲を手動で指定するよりも柔軟に対応でき、どの列でフィルタしても機能します。

参考:【VBA】フィルタを使って空白行を削除する方法|効率的にデータを整理しよう

・2. .Offset(1, 0) でヘッダー行を除外

フィルタ範囲にはヘッダーも含まれるため、1行下から対象範囲を指定します。
この指定がないとヘッダー行も処理に含まれてしまいます。

参考:【Excel】OFFSET関数の使い方をわかりやすく解説|基礎から応用まで

・3. .SpecialCells(xlCellTypeVisible) で可視セルを抽出

これがポイントです。
非表示になっている行(フィルタ除外データ)は自動的に除外され、画面上に見えているセルだけが取得されます。

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

・4. On Error Resume Next で安全にエラー回避

フィルタ結果が0件の場合、SpecialCells はエラーを返すため、エラー制御を入れておくことで中断を防ぎます。

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


✅ 可視セルから値を配列として取得する

・配列に格納して高速処理

多くの行データを扱う場合、1セルずつループするより配列に格納する方が高速です。
次のコードは、フィルタ後の値を配列に格納して処理する例です。

Sub GetFilteredValuesArray()
    Dim ws As Worksheet
    Dim visibleCells As Range
    Dim arr As Variant
    Dim i As Long

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

    ' フィルタ範囲から可視セルを取得
    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 "該当データがありません。", vbExclamation
        Exit Sub
    End If

    ' 可視セルの3列目(売上)を配列に格納
    arr = visibleCells.Columns(3).Value

    ' 出力確認
    For i = 1 To UBound(arr, 1)
        Debug.Print arr(i, 1)
    Next i
End Sub

この方法を使えば、抽出されたデータを一括で処理できます。
集計や他シート転記など、実務でも効率的に応用可能です。

参考:【VBA】セルの値を変数配列に取得:ループ処理




✅ 応用例①:フィルタ後の合計値を求める

フィルタ後のデータだけを対象に合計を出すには、WorksheetFunction.Sum と可視セルを組み合わせます。

Sub SumVisibleValues()
    Dim ws As Worksheet
    Dim visibleCells As Range
    Dim total As Double

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

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

    If Not visibleCells Is Nothing Then
        total = WorksheetFunction.Sum(visibleCells)
        MsgBox "フィルター後の合計値:" & total, vbInformation
    Else
        MsgBox "集計対象が見つかりません。", vbExclamation
    End If
End Sub

このコードを実行すると、フィルタで表示されている行の合計値のみが計算されます。
非表示行は無視されるため、誤集計を完全に防げます。

参考:【Excel】自動計算による足し算を行う方法|SUM関数・オートSUM・テーブルの活用まで解説


✅ 応用例②:フィルタ後の値を別シートに転記

レポート作成などで、フィルタ後の結果だけを別シートに出力したい場合もあります。

Sub CopyFilteredValues()
    Dim ws As Worksheet
    Dim visibleCells As Range

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

    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 Not visibleCells Is Nothing Then
        visibleCells.Copy Destination:=ThisWorkbook.Sheets("抽出結果").Range("A1")
        MsgBox "フィルター後のデータを転記しました。", vbInformation
    Else
        MsgBox "抽出結果がありません。", vbExclamation
    End If
End Sub

このマクロでは、オートフィルタ後の表示行だけを一括コピーして「抽出結果」シートに貼り付けます。
報告資料の作成や、データ加工の中間ステップとして非常に便利です。

参考:【VBA】VLOOKUP を別シートで使う方法と実用例


✅ 注意点とエラー対策

・1. 可視セルがない場合にエラーが発生する

SpecialCells は対象がないと「実行時エラー1004」を返します。
必ず On Error Resume Next で制御しましょう。

・2. フィルタが設定されていない場合

AutoFilter.Range はフィルタ未設定時に存在しないため、
If ws.AutoFilterMode = False Then で事前確認が必要です。

・3. 複数範囲(Areas)が生成されるケース

抽出結果が途切れた場合、visibleCells は複数範囲(Areas)に分かれます。
その場合は次のようにループして処理します。

Dim area As Range
For Each area In visibleCells.Areas
    Debug.Print area.Address
Next area

✅ 実務での活用:集計・チェック・転記を自動化

実務では次のようなシーンで「フィルタ後の値取得」が役立ちます。

  • 「特定条件で抽出したデータだけを別シートにまとめる」
  • 「フィルタで抽出された営業担当者の売上を合計する」
  • 「未処理タスクだけをリストアップして別表に転記する」

これらの作業をVBAで自動化すれば、毎日の報告やデータ整理がわずか数秒で完了します。
また、非表示データを誤って処理しないため、業務の正確性も高まります。


✅ まとめ:VBAでフィルター後の値を正確に取得しよう

  • SpecialCells(xlCellTypeVisible) で可視セル(フィルタ後の値)を取得できる
  • 通常の範囲指定では非表示行も含まれるため誤処理の原因になる
  • On Error Resume NextAutoFilterMode チェックで安全に動作
  • 合計・転記・配列処理など、応用範囲が非常に広い
  • レポート作成やデータ抽出の自動化に最適

フィルタ後の値を正確に取得できれば、Excelの操作を「目で見る作業」から「ロジックで制御する作業」に変えられます。
業務の再現性とスピードが劇的に向上しますので、ぜひこの方法を日常業務に取り入れてみてください。

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