VBAで自動化 VBA一覧 フィルタリング 抽出・検索処理

【VBA】AutoFilter結果の件数を正しく取得する完全ガイド

Excel VBAでAutoFilterを使ったあと、
「抽出された件数を取得したい」
「フィルター結果が何行あるのか知りたい」
と考えたことはありませんか。

一見すると、
Rows.CountCountA を使えば簡単に取れそうですが、
AutoFilterが絡んだ瞬間に件数が合わなくなるケースが非常に多く発生します。

実務では、

  • フィルター後なのに全件数が返ってくる
  • 見た目と件数が一致しない
  • 0件のはずなのにエラーになる

といったトラブルが頻発します。

この記事では、
「VBA × AutoFilter × 件数取得」という
実務で必ずぶつかるテーマを、

  • なぜズレるのか
  • 正しい件数の考え方
  • 安全で再利用できるコード

という視点で、徹底的に解説します。

目次

✅ AutoFilter後の「件数」がズレる根本原因

AutoFilterを使うと、
Excelの画面上ではデータが減ったように見えます。

しかしVBAから見ると、
行は削除されておらず、非表示になっているだけです。


・ここで起きる誤解

  • フィルター後は行数も減っていると思ってしまう
  • Rows.Count が抽出結果を返すと思ってしまう

この認識のズレが、
件数取得ミスの最大原因です。


・重要な前提

  • AutoFilter = 表示制御
  • 行の存在自体は変わらない

👉 「可視行だけを数える」意識が必須です。


✅ やってはいけない件数取得方法

まずは、
実務でよく見かけるNG例から確認します。


・NG例①:Rows.Countをそのまま使う

Dim cnt As Long
cnt = Rows.Count

このコードは、
シート全体の最大行数を返します。

AutoFilter結果とは一切関係ありません。


・NG例②:最終行 − 見出し行

cnt = Cells(Rows.Count, 1).End(xlUp).Row - 1

これは「データ件数」ではありますが、
フィルター前の全件数です。


・NG例③:CountAで範囲を数える

cnt = Application.WorksheetFunction.CountA(Range("A:A"))

これも非表示行を含むため、
抽出件数にはなりません。


✅ AutoFilter結果の件数を取得する正しい考え方

AutoFilter結果の件数とは、
「表示されている行数」です。

VBAではこれを、
可視セル(Visible Cells)として扱います。


・件数取得の基本方針

  1. AutoFilterをかける
  2. 可視セルだけを対象にする
  3. 見出し行を除外する

この流れが、
すべての正解パターンの基礎になります。


✅ 基本パターン①:SpecialCellsで件数を取得する

最も代表的で、
実務使用率が高い方法です。


・基本コード例

Dim cnt As Long

On Error Resume Next
cnt = Range("A2:A100").SpecialCells(xlCellTypeVisible).Count
On Error GoTo 0

・このコードの意味

  • A列のデータ行だけを対象
  • 可視セルのみカウント
  • 抽出結果が0件でもエラーを防止

・なぜOn Errorが必要なのか

AutoFilterの結果が0件の場合、
SpecialCellsエラーを返します。

そのため、
実務では必ずエラー対策が必要です。

参考:【VBA】On Error Resume Nextでエラーを無視してエラーの制御|危険な理由




✅ 見出し行を含めないための注意点

AutoFilterを使う場合、
見出し行の扱いを誤ると件数が1件ズレます。


・正しい範囲指定

Range("A2:A" & lastRow)

・よくあるミス

Range("A1:A" & lastRow)

この場合、
見出し行も件数に含まれてしまうため注意が必要です。

参考:【VBA】AutoFilterの複数条件を設定する方法|AND・ORを自在に操る実務向け活用術


✅ 基本パターン②:Rows.Hiddenを使って件数を数える

For Nextを使って、
可視行だけを数える方法もあります。


・基本コード例

Dim i As Long
Dim cnt As Long

For i = 2 To lastRow
    If Rows(i).Hidden = False Then
        cnt = cnt + 1
    End If
Next i

・この方法の特徴

  • 可視/非表示を明示的に判定できる
  • 条件分岐を組み込みやすい

・注意点

  • データ量が多いと処理が遅くなる
  • 速度重視の処理には不向き

✅ 基本パターン③:ListObject(テーブル)で件数を取得する

データがテーブル化されている場合、
最も安定して件数を取得できる方法です。


・テーブルの可視行数を取得する例

Dim tbl As ListObject
Dim cnt As Long

Set tbl = Worksheets("データ").ListObjects("tblData")

On Error Resume Next
cnt = tbl.DataBodyRange.SpecialCells(xlCellTypeVisible).Rows.Count
On Error GoTo 0

・ListObjectを使うメリット

  • フィルター状態を正確に反映
  • 列追加・削除に強い
  • 可読性が高い

✅ AutoFilter結果が0件かどうかを判定する方法

件数取得と同時に、
0件判定も実務では非常に重要です。


・0件判定の基本例

If cnt = 0 Then
    MsgBox "該当データはありません。"
    Exit Sub
End If

・この判定を入れるべき理由


✅ AutoFilter結果を使った実務パターン①:件数チェック後に処理

If cnt > 0 Then
    ' 抽出結果ありの場合の処理
Else
    ' 抽出結果なし
End If

・よくある活用場面

  • メール送信対象の有無確認
  • CSV出力の要否判定
  • RPA連携前のガード処理

✅ AutoFilter結果を使った実務パターン②:件数をメッセージ表示

MsgBox "抽出結果は " & cnt & " 件です。"

ユーザー操作マクロでは、
件数を見せるだけでも安心感が大きく向上します。


✅ フィルター解除後に件数がズレるケースに注意

AutoFilter解除のタイミングを誤ると、
件数取得が無意味になることがあります。


・NGな流れ

  1. フィルター
  2. 解除
  3. 件数取得

この場合、
常に全件数が返ります。


・正しい流れ

  1. フィルター
  2. 件数取得
  3. 処理
  4. フィルター解除

✅ AutoFilter × 件数取得 × 転記処理の実務例

Dim r As Range
Dim destRow As Long

destRow = 2

For Each r In Range("A2:A" & lastRow).SpecialCells(xlCellTypeVisible)
    Cells(destRow, 10).Value = r.Value
    destRow = destRow + 1
Next r

👉 件数取得と同じロジックを使えば、
処理の一貫性が保てます。

参考:【VBA】フィルター抽出結果を別シートに自動転記する方法|業務を効率化する実践マクロ


✅ UiPath・RPAと連携する場合の考え方

RPAとExcelを連携する場合、
AutoFilter結果の件数は 非常に重要な制御情報です。


・おすすめ設計

  • VBAで件数取得まで完結
  • RPAには結果(件数・転記後データ)のみ渡す

これにより、
RPA側の例外処理が激減します。


✅ よくある失敗まとめ

  • 全件数と抽出件数を混同する
  • SpecialCellsのエラー未対策
  • 見出し行を含めてしまう
  • フィルター解除の順序ミス



✅ まとめ:VBA AutoFilter結果の件数は「可視セル」がすべて

  • AutoFilterは非表示にするだけ
  • 件数取得は可視セル基準で行う
  • SpecialCellsが最も実務向き
  • 0件対策は必須
  • 処理順序を間違えない

VBA AutoFilter 結果 件数は、
一度正しく理解すれば、
抽出・集計・転記処理の信頼性が一気に向上します。

「なぜ件数が合わなかったのか」を意識しながら、
ぜひ既存マクロを見直してみてください。

参考:【VBA】条件に一致するセルを取得する方法|Find・For Each・SpecialCells

    -VBAで自動化, VBA一覧, フィルタリング, 抽出・検索処理