VBAで自動化 VBA一覧 フィルター操作・制御 抽出・検索処理

【VBA】フィルター イベントを擬似的に扱う実務設計完全解説

Excelでオートフィルターを使った業務をしていると、「フィルター条件が変わった瞬間に処理を実行したい」「抽出結果に応じて自動で集計・出力したい」と考える場面は少なくありません。
しかし実際にVBAを書き始めると、多くの人が最初にぶつかる壁があります。

「フィルターのイベントが発火しない」

これはバグでも書き方の問題でもなく、Excel VBAの仕様です。
この記事では、Excel VBAにおける「フィルターイベント」という考え方を正しく整理し、擬似的にイベントとして扱う実務的な実装方法を、コード例とともに徹底解説します。

✅ Excel VBAにフィルター専用イベントが存在しない理由

※ここを誤解したまま進むと、必ず設計が破綻します。

Excel VBAには、次のようなイベントは用意されていません。

  • フィルター変更時イベント
  • 抽出条件変更イベント
  • オートフィルター実行イベント

つまり、「フィルター操作そのもの」を直接検知することは不可能です。

・なぜ存在しないのか

オートフィルターは、

  • UI操作
  • 表示制御
  • 内部計算
  • 並び替え・非表示制御

が複雑に絡んだ機能であり、
VBAとしては「単独イベントとして切り出せない」仕様になっています。

そのため実務では、
「フィルター操作によって結果が変わった事実」を検知する
という発想に切り替える必要があります。


✅ フィルター操作時に関係するVBAイベント

※どのイベントが「使える可能性があるか」を整理します。

・Worksheet_Changeイベント

フィルター条件の変更によってセルの値が変わる場合に発火します。

Private Sub Worksheet_Change(ByVal Target As Range)
    MsgBox "セルが変更されました"
End Sub

なぜこれが関係するのか

  • フィルター条件をセル入力で制御している場合
  • 条件セルが変更された瞬間を検知できる

注意点

  • 標準のオートフィルター操作では発火しない
  • フィルター操作=必ずChangeではない

・Worksheet_Calculateイベント

フィルター条件に数式が関係している場合、再計算時に発火します。

Private Sub Worksheet_Calculate()
    MsgBox "再計算が行われました"
End Sub

実務での注意

  • 非常に発火頻度が高い
  • 無条件で処理を書くとExcelが重くなる

✅ フィルター変更を擬似イベントとして検知する基本設計

※この記事の最重要ポイントです。

・考え方の整理

フィルター操作は検知できない
フィルター結果の変化を検知する

代表的なのは、
「表示されている行数(可視行数)」の変化です。


✅ 可視行数の変化でフィルター変更を検知する方法

※実務で最も安定する方法です。

・基本ロジック

  1. 現在の可視行数を取得
  2. 前回の行数と比較
  3. 差があれば「フィルター変更」と判断

・可視行数を取得するコード例

Function GetVisibleRowCount(targetRange As Range) As Long
    On Error Resume Next
    GetVisibleRowCount = targetRange.SpecialCells(xlCellTypeVisible).Rows.Count
    On Error GoTo 0
End Function

コード解説


・Worksheet_Calculateと組み合わせた実装例

Dim beforeCount As Long

Private Sub Worksheet_Activate()
    beforeCount = GetVisibleRowCount(Me.Range("A2:A1000"))
End Sub

Private Sub Worksheet_Calculate()
    Dim afterCount As Long
    afterCount = GetVisibleRowCount(Me.Range("A2:A1000"))
    
    If beforeCount <> afterCount Then
        Call FilterChangedProcess
        beforeCount = afterCount
    End If
End Sub

なぜこの構成なのか

  • フィルター操作後は再計算が走ることが多い
  • 差分比較で「変更があった瞬間」だけ処理可能



✅ フィルター適用・解除を判定する方法

※解除時の処理漏れが最も多いです。

・FilterModeとAutoFilterModeの違い

プロパティ意味
AutoFilterModeフィルターが存在するか
FilterMode抽出状態かどうか

・解除を検知するコード例

If Me.FilterMode = False And Me.AutoFilterMode = True Then
    MsgBox "フィルターが解除されました"
End If

実務での使いどころ


✅ フィルター変更時に実行する処理例

※「何をさせるか」が明確になります。

・抽出件数を表示する処理

Sub FilterChangedProcess()
    Dim cnt As Long
    cnt = GetVisibleRowCount(Sheet1.Range("A2:A1000"))
    
    If cnt = 0 Then
        MsgBox "該当データがありません"
    Else
        MsgBox "抽出件数:" & cnt & "件"
    End If
End Sub

・フィルター結果を別シートへ転記

Sub CopyFilteredData()
    Sheet1.Range("A1:D1000").SpecialCells(xlCellTypeVisible).Copy _
        Destination:=Sheet2.Range("A1")
End Sub

注意点

  • ヘッダー行を含めるかは要件次第
  • 可視セル0件時のエラー対策が必須

✅ イベント多重発火を防ぐ実務テクニック

※ここを怠ると無限ループになります。

Application.EnableEvents = False
' 処理
Application.EnableEvents = True

なぜ必要か

  • フィルター処理 → 再計算 → イベント再発火
  • 無限ループ防止のため必須

✅ フィルター×VBA×業務自動化の考え方

※中級者以上向けの視点です。

Excel VBAでフィルターをイベント的に扱えるようになると、

  • 条件変更 → 自動集計
  • 抽出完了 → 帳票出力
  • 解除 → 初期化

といった 業務フロー制御 が可能になります。

さらに、
この処理をUiPathなどのRPAと組み合わせることで、

  • 人が操作しないExcel処理
  • 夜間バッチ処理
  • 定型業務の完全自動化

へと発展させることができます。


✅ 実務でよくある失敗例

※ここを避けるだけで品質が上がります。

  • フィルターイベントがあると勘違い
  • Changeイベントに全処理を書く
  • 可視セル0件のエラー未対策
  • 解除時の状態管理不足



✅ まとめ:Excel VBAでフィルターイベントを扱う正解設計

  • フィルター専用イベントは存在しない
  • 結果の変化を擬似イベントとして扱う
  • 可視行数チェックが最も安定
  • 解除時の処理設計が重要
  • 自動化前提で設計すると再利用性が高い

Excel VBAにおけるフィルター処理は、
「イベントがないからできない」のではなく、
「設計の考え方を変えることで実現できる」 分野です。

正しい理解と設計で、
一段上の実務ツールを構築していきましょう。

参考:【VBA】ユーザーフォームで出席確認ツールを作成する方法

    -VBAで自動化, VBA一覧, フィルター操作・制御, 抽出・検索処理