VBAで自動化 VBA一覧 フィルター結果のコピー・抽出 抽出・検索処理

【VBA】オートフィルタの範囲を指定する方法|抽出漏れを防ぐ正しい設定手順

VBAでオートフィルタを使うと、条件に一致するデータを自動で抽出できます。
しかし「意図した範囲がフィルタされない」「空白があると正しく動かない」など、範囲指定でつまずく人が非常に多いです。

オートフィルタは、範囲の指定方法を間違えると正しく機能しません。
本記事では、VBAでオートフィルタの範囲を正確に指定する方法と、実務で役立つ応用テクニックを詳しく紹介します。

✅ オートフィルタの基本構文と範囲指定の考え方

まず、オートフィルタの基本形を確認しましょう。

Range("A1:D100").AutoFilter Field:=2, Criteria1:="完了"

これは、範囲A1:D100の中で「2列目(B列)」に「完了」という文字を含む行だけを表示する構文です。

基本構文の要点

  • Range("A1:D100"):フィルタをかけたい範囲を明示的に指定
  • Field:=2:範囲の左端を「1」として数える列番号
  • Criteria1:="完了":抽出条件(値や文字列など)

このように「範囲を正確に指定すること」が、オートフィルタを安定して動かすポイントです。

参考:【VBA】オートフィルタで「0以外」を抽出する方法|数値データの効率的な絞り込みテクニック


✅ 範囲指定でよくあるエラーと原因

・① 空白行があると範囲が途切れる

CurrentRegion を使って自動的に範囲を取得する方法は便利ですが、
途中に空白行があると範囲が分断され、正しく抽出されません。

Range("A1").CurrentRegion.AutoFilter Field:=1, Criteria1:="東京"

この方法では、空白行があると「A1~空白行の手前」までしか認識されません。
その結果、一部のデータがフィルタ対象から外れることがあります。

参考:【VBA】範囲選択に空白がある時の処理方法:Current Regionメソッド

・② 最終行が可変なのに固定範囲を使う

たとえば「A1:D1000」と固定していると、
実際にデータが1500行ある場合、1001行目以降は抽出されません。
逆に、空白行を含めすぎると無駄な処理が増えて速度低下の原因になります。

参考:【VBA】最終行番号を取得する方法


✅ 動的に範囲を指定する方法①:最終行と最終列を自動検出

実務では、毎回データ量が変わることが多いため、最終行・最終列を自動検出して範囲指定するのが安全です。

Sub DynamicFilterRange()
    Dim ws As Worksheet
    Dim lastRow As Long, lastCol As Long
    Dim filterRange As Range

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

    ' 最終行・最終列を取得
    lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
    lastCol = ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column

    ' 動的範囲を設定
    Set filterRange = ws.Range(ws.Cells(1, 1), ws.Cells(lastRow, lastCol))

    ' フィルタ設定
    filterRange.AutoFilter Field:=2, Criteria1:="完了"
End Sub

ポイント

  • Cells(1, 1) は開始セル(A1)
  • Cells(lastRow, lastCol) は終端セル(右下)
  • Field:=2 は範囲内の2列目を指定(A列が1、B列が2)

この方法なら、データ行が増減しても自動で範囲を調整できます。

参考:【VBA】範囲内に値があるか確認する方法


✅ 動的に範囲を指定する方法②:特定列から最終行を取得

売上表や顧客リストなど、「A列には必ずデータが入っている」場合は、
A列の最終行だけを基準にして範囲を決めることもできます。

Sub FilterByColumnA()
    Dim ws As Worksheet
    Dim lastRow As Long

    Set ws = Sheets("データ")
    lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row

    ws.Range("A1:D" & lastRow).AutoFilter Field:=3, Criteria1:="高評価"
End Sub

✅ メリット

⚠️ 注意

  • A列に空白がある場合、途中で範囲が途切れる可能性があります。
    その場合は「別の列(常に埋まっている列)」を基準にしましょう。



✅ 範囲指定+複数条件を組み合わせる

特定範囲に対して「複数条件」を指定することも可能です。

Sub FilterWithMultiConditions()
    Dim ws As Worksheet
    Dim lastRow As Long
    Set ws = Sheets("データ")

    lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row

    ws.Range("A1:D" & lastRow).AutoFilter Field:=2, _
        Criteria1:="完了", Operator:=xlOr, Criteria2:="進行中"
End Sub

Operator:=xlOr を使うことで、「完了」または「進行中」に一致する行だけを抽出します。
もし両方に該当するデータを取りたい場合は、xlAnd を指定します。

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


✅ 範囲指定をシートごとに自動で判定する

複数シートに同じ形式のデータがある場合、それぞれにフィルタを適用することも可能です。

Sub MultiSheetFilter()
    Dim ws As Worksheet
    Dim lastRow As Long

    For Each ws In ThisWorkbook.Worksheets
        If ws.Name <> "集計結果" Then
            lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
            ws.Range("A1:D" & lastRow).AutoFilter Field:=3, Criteria1:="在庫あり"
        End If
    Next ws
End Sub

このように、全シートを一括処理してフィルタをかけるマクロも作成可能です。
在庫管理や部署別データのチェックなどで役立ちます。

参考:【Excel】【在庫管理】在庫数に応じて発注判断を自動化するIF関数の設定方法|ムダなく効率的な仕入れを実現


✅ オートフィルタ範囲を変数で扱うメリット

オートフィルタ範囲を Range 変数に格納しておくと、
後続処理(コピー・削除・転記)を柔軟に行えます。

Sub FilterRangeVariable()
    Dim ws As Worksheet
    Dim rng As Range
    Dim visibleRange As Range

    Set ws = Sheets("データ")

    Set rng = ws.Range("A1").CurrentRegion
    rng.AutoFilter Field:=4, Criteria1:="不良"

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

    If Not visibleRange Is Nothing Then
        visibleRange.Copy Sheets("不良一覧").Range("A1")
    Else
        MsgBox "該当データがありません。", vbInformation
    End If

    ws.AutoFilterMode = False
End Sub

このようにすれば、「範囲を定義 → 抽出 → 可視セルコピー」とスムーズに処理できます。

参考:【VBA】オートフィルタ後の可視セルを取得する方法|抽出データだけを扱う実務テクニック


✅ 範囲指定の自動化+ヘッダー行の確認を組み合わせる

オートフィルタは、必ず1行目(または指定行)を見出しとして認識します。
見出しを誤って含めないと、抽出条件が適用されません。

以下のように、「ヘッダー行を固定して範囲を動的に指定」すると安定します。

Sub FilterWithHeaderCheck()
    Dim ws As Worksheet
    Dim lastRow As Long, lastCol As Long
    Dim rng As Range

    Set ws = Sheets("データ")
    lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
    lastCol = ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column

    Set rng = ws.Range(ws.Cells(1, 1), ws.Cells(lastRow, lastCol))

    ' 見出しがあるかチェック
    If ws.Cells(1, 1).Value = "" Then
        MsgBox "見出し行がありません。", vbExclamation
        Exit Sub
    End If

    rng.AutoFilter Field:=3, Criteria1:="売上>100000"
End Sub

ヘッダーの存在確認を入れておくことで、誤動作を防げます。

参考:【VBA】オートフィルタ結果を「見出しを除いてコピー」する方法|自動抽出の基本テクニック


✅ 範囲指定のエラーを防ぐチェックリスト

トラブル内容原因対策
フィルタが効かない範囲外のセルを指定しているCells で動的指定する
一部しか抽出されないCurrentRegionで空白が分断明示的な範囲を指定する
条件が適用されない見出しが含まれていないA1などヘッダーを必ず含める
0件時にエラー可視セルなしOn Error Resume NextNothing判定

✅ 実務での応用例:売上表を自動抽出して別シートへ出力

オートフィルタの範囲指定を組み合わせれば、
「条件抽出 → 結果コピー」を1クリックで自動化できます。

Sub ExportFilteredSales()
    Dim ws As Worksheet, wsOut As Worksheet
    Dim lastRow As Long
    Dim rng As Range, visibleRange As Range

    Set ws = Sheets("売上データ")
    Set wsOut = Sheets("高売上")
    wsOut.Cells.Clear

    lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
    Set rng = ws.Range("A1:E" & lastRow)

    rng.AutoFilter Field:=5, Criteria1:=">100000"

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

    If Not visibleRange Is Nothing Then
        rng.Rows(1).Copy wsOut.Range("A1") ' 見出し
        visibleRange.Copy wsOut.Range("A2")
    End If

    ws.AutoFilterMode = False
End Sub

これで「売上10万円以上のデータ」を自動で抽出して、別シートに転記できます。
範囲指定を動的にしているため、行数が増えても安心です。


✅ まとめ:正しい範囲指定がオートフィルタ成功の鍵

  • 空白行があると CurrentRegion は分断される
  • データの増減に対応するには lastRowlastCol を使って動的範囲指定
  • AutoFilter.Range を変数で扱うとコピー・削除が簡単
  • ヘッダー行を含めて範囲を指定するのが鉄則
  • 0件時のエラー対策 (On Error Resume NextNothingチェック) は必須

VBAのオートフィルタは、範囲指定を正確に行うかどうかで安定性が大きく変わります
今回紹介した構文を使えば、どんなシートでも確実に抽出できる堅牢なマクロが作れます。

ぜひあなたの業務にも、「正しい範囲指定によるフィルタ自動化」を取り入れてみてください。

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