Excelのフィルター機能を使ってデータを絞り込んだあと、「表示されている値だけを取得したい」と思ったことはありませんか?
たとえば、営業部のデータを抽出して合計を出したり、抽出後の行だけを別シートに転記したいときなどです。
しかし、VBAでは単純に Range("A2:A100")
のように指定しても、非表示のセルも含まれてしまうため、正確に抽出結果を扱うことができません。
そこで活躍するのが、「SpecialCells(xlCellTypeVisible)」 です。
この記事では、このメソッドを使って「フィルター後の値だけを取得・利用」する方法を徹底的に解説します。
目次
- ✅ フィルター後の値を取得する基本構文
- 基本構文
- 例:抽出結果の可視セルを取得
- ✅ 実践:オートフィルターで絞り込み → 表示データの値を取得
- 例:営業部だけ抽出し、表示された「売上金額」を取得する
- ✅ フィルター後の値を配列に格納する
- コード例:抽出結果を配列に格納
- 応用:配列を使って別シートへ転記
- ✅ フィルター後の行番号を取得する
- コード例:可視セルの行番号を取得
- ✅ フィルター後の値を別シートにコピーする
- コード例:フィルター後の値をコピーして転記
- ✅ エラーを防ぐためのベストプラクティス
- 安全なテンプレート構文
- ✅ よくある失敗例と解決法
- ✅ フィルター後の値を高速に扱うコツ
- 1. 画面更新を止める
- 2. 自動計算を止める
- 3. イベントを止める
- テンプレート例
- ✅ 実務応用シナリオ
- ① 部署ごとの売上集計を自動で出力
- ② 抽出データを日付フォルダに保存
- ③ 特定条件の抽出+メール送信
- ■ まとめ:フィルター後の値を取得すればExcel自動化が加速する
✅ フィルター後の値を取得する基本構文
オートフィルターで抽出したデータのうち、「表示されているセル」だけを取得するには、以下の構文を使います。
基本構文
Range("範囲").SpecialCells(xlCellTypeVisible)
この「SpecialCells」は、セルの特定条件(空白・数式・コメント・可視など)を指定して取得するメソッドです。
その中でも xlCellTypeVisible
は「表示されているセル(非表示を除く)」を対象にします。
例:抽出結果の可視セルを取得
Sub GetVisibleCells()
Dim rng As Range
Set rng = Range("A1:A100").SpecialCells(xlCellTypeVisible)
rng.Select
End Sub
このコードでは、A1:A100のうち、現在表示されているセルのみを選択します。
もしオートフィルターで非表示になっている行があっても、それらは無視されます。
参考:【VBA】指定したシートを開く方法|Activate・Select・Visibleの違いと実務活用
⚠ 注意点
SpecialCells
は「該当セルが存在しない場合」に**エラー(1004)**を返すことがあります。
安全に扱うには、On Error Resume Next
でエラーを回避しておくのが一般的です。
参考:【VBA】On Error Resume Nextでエラーを無視してエラーの制御
✅ 実践:オートフィルターで絞り込み → 表示データの値を取得
ここからは、実際にフィルターを設定してから値を取得する一連の流れを紹介します。
例:営業部だけ抽出し、表示された「売上金額」を取得する
Sub GetFilteredValues()
Dim rng As Range
Dim cell As Range
Dim total As Double
' フィルターを設定(B列:部署、C列:売上)
Range("A1:C100").AutoFilter Field:=2, Criteria1:="営業部"
' フィルター後の可視セルを取得(C列の値を対象)
On Error Resume Next
Set rng = Range("C2:C100").SpecialCells(xlCellTypeVisible)
On Error GoTo 0
' 抽出結果がある場合のみ処理
If Not rng Is Nothing Then
For Each cell In rng
total = total + cell.Value
Next cell
MsgBox "営業部の売上合計は " & total & " 円です。"
Else
MsgBox "条件に一致するデータがありません。"
End If
' フィルター解除
ActiveSheet.AutoFilterMode = False
End Sub
処理の流れ
- A1:C100にフィルターを設定
- B列で「営業部」を抽出
- C列のうち表示されているセルだけを取得
- ループで合計値を計算
- 最後にフィルター解除
このように、可視セルだけを対象にすることで、抽出結果に正確に基づいた処理ができます。
出力例
営業部の売上合計は 360 円です。
✅ フィルター後の値を配列に格納する
抽出した値を配列に格納すれば、別の処理(転記・検証・計算など)を効率的に行えます。
コード例:抽出結果を配列に格納
Sub GetFilteredArray()
Dim rng As Range
Dim arr As Variant
Dim i As Long
' フィルターを設定
Range("A1:C100").AutoFilter Field:=2, Criteria1:="開発部"
' 可視セル(B列のデータ)を取得
On Error Resume Next
Set rng = Range("B2:B100").SpecialCells(xlCellTypeVisible)
On Error GoTo 0
If Not rng Is Nothing Then
arr = rng.Value
For i = 1 To UBound(arr, 1)
Debug.Print arr(i, 1)
Next i
Else
MsgBox "開発部のデータは見つかりません。"
End If
ActiveSheet.AutoFilterMode = False
End Sub
解説
arr = rng.Value
で抽出結果を二次元配列に格納
参考:【VBA】2次元配列を使用して一括で格納・格納データをループで処理する方法- 配列をループすることで、値を1つずつ扱える
- 実際に画面を動かさず、非表示で高速処理が可能
応用:配列を使って別シートへ転記
Sheets("結果").Range("A1").Resize(UBound(arr, 1), 1).Value = arr
この1行で、配列内のデータを「結果」シートに一括書き込みできます。
参考:【VBA】特定の文字を含む列の処理:検索・削除・別シートにコピー
✅ フィルター後の行番号を取得する
値ではなく、「どの行が表示されているか」を取得したい場合もあります。
これにより、特定行を削除・変更・コピーする処理が容易になります。
コード例:可視セルの行番号を取得
Sub GetVisibleRows()
Dim rng As Range
Dim cell As Range
Dim msg As String
Range("A1:C100").AutoFilter Field:=2, Criteria1:="総務部"
On Error Resume Next
Set rng = Range("A2:A100").SpecialCells(xlCellTypeVisible)
On Error GoTo 0
If Not rng Is Nothing Then
For Each cell In rng
msg = msg & cell.Row & vbCrLf
Next cell
MsgBox "表示されている行番号:" & vbCrLf & msg
Else
MsgBox "該当データはありません。"
End If
ActiveSheet.AutoFilterMode = False
End Sub
出力例
表示されている行番号:
2
5
9
このように、表示された行のインデックスを正確に取得できます。
参考:【VBA】条件に一致するセルを複数取得する方法|Find・For Each・SpecialCells
✅ フィルター後の値を別シートにコピーする
最も実務で使われるのが「抽出結果を別シートに転記」する処理です。
これも、可視セルをそのままコピーするだけで簡単に実現できます。
コード例:フィルター後の値をコピーして転記
Sub CopyFilteredData()
Dim wsSrc As Worksheet
Dim wsDst As Worksheet
Dim rngVisible As Range
Set wsSrc = Sheets("データ")
Set wsDst = Sheets("結果")
wsDst.Cells.ClearContents
' フィルターを設定
wsSrc.Range("A1:C100").AutoFilter Field:=2, Criteria1:="営業部"
' 可視セルを取得
On Error Resume Next
Set rngVisible = wsSrc.Range("A1:C100").SpecialCells(xlCellTypeVisible)
On Error GoTo 0
' 可視セルをコピー
If Not rngVisible Is Nothing Then
rngVisible.Copy Destination:=wsDst.Range("A1")
MsgBox "抽出結果を結果シートに転記しました。"
Else
MsgBox "条件に一致するデータがありません。"
End If
wsSrc.AutoFilterMode = False
End Sub
実務での使い道
- 営業部や支店別のデータを自動で出力
- 部署ごとのレポートを瞬時に作成
- さらにPDF化・メール送信などにも応用可能
このように「抽出結果をそのまま出力」できるのが、VBA+フィルターの大きな強みです。
✅ エラーを防ぐためのベストプラクティス
SpecialCells(xlCellTypeVisible)
は便利ですが、該当セルが存在しないときにエラーが出やすいため、以下の対策を入れておきましょう。
安全なテンプレート構文
On Error Resume Next
Set rng = Range("A2:A100").SpecialCells(xlCellTypeVisible)
On Error GoTo 0
If rng Is Nothing Then
MsgBox "抽出結果がありません。"
Exit Sub
End If
これにより、条件に一致しない場合もマクロが途中で停止せず、
「抽出結果がない」と丁寧に通知できます。
✅ よくある失敗例と解決法
問題 | 原因 | 対処法 |
---|---|---|
取得結果に非表示行が含まれる | SpecialCellsを使っていない | .SpecialCells(xlCellTypeVisible) を追加 |
空白セルも含まれる | フィルター対象がずれている | Range 指定を見直す(ヘッダー含む範囲) |
フィルターが解除されない | AutoFilterMode未解除 | ActiveSheet.AutoFilterMode = False を追加 |
エラー1004発生 | 該当データがない | On Error Resume Next でエラー制御 |
✅ フィルター後の値を高速に扱うコツ
大量データを扱う場合、処理速度を上げるには次の3点を組み合わせましょう。
1. 画面更新を止める
Application.ScreenUpdating = False
2. 自動計算を止める
Application.Calculation = xlCalculationManual
3. イベントを止める
Application.EnableEvents = False
これらを処理前に設定し、処理後に元に戻すとマクロ全体が格段に速くなります。
テンプレート例
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Application.EnableEvents = False
' --- フィルター処理 ---
' 可視セル取得・転記など
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
Application.EnableEvents = True
✅ 実務応用シナリオ
① 部署ごとの売上集計を自動で出力
- 各部門を順にフィルター
- 表示データの売上を合計して別シートに書き出す
② 抽出データを日付フォルダに保存
- 可視セルをコピーして新しいブックに貼り付け
- 日付名で保存する(月次処理に最適)
③ 特定条件の抽出+メール送信
- 条件を満たすデータを抽出
- そのリストをHTML形式でOutlookメールに自動貼り付け
■ まとめ:フィルター後の値を取得すればExcel自動化が加速する
- フィルター後の値は
.SpecialCells(xlCellTypeVisible)
で取得できる - 配列化・ループ・コピーなどで自由に活用可能
On Error Resume Next
でエラー対策を忘れずに- 集計・転記・レポート生成まで自動化できる
- 大量データでも画面更新停止で高速処理が可能
VBAでフィルター後の値を正確に取得できるようになると、
単なる手作業の分析から「完全自動化された集計・出力システム」へ進化します。
ぜひ、この記事のコードを自社データやレポート作成に活かしてみてください。