オートフィルタの設定と解除方法
オートフィルタは使い勝手がよく、とても便利な機能です。VBAでもオートフィルタの設定が可能で、シートに表形式のデータを作成した場合などに、自動でオートフィルタの設定をすることができます。
ただし、VBAでオートフィルタのコードを書くときには注意が必要です。
いくつか問題があるのですが、それらの問題を考慮した上で、オートフィルタの設定を行う関数と、解除を行う関数をページの最後で紹介しています。
AutoFilterメソッドは設定と解除の両方を行う
オートフィルタの設定と解除は、どちらもRangeオブジェクトのAutoFilterメソッドで行います。
コードとしては以下の2行目のように設定も解除も全く同じ書き方になります。
当然、見ての通り、これでは設定するのか解除するのか分かりません。
AutoFilterプロパティはどういう挙動になるかというと、オートフィルタが設定されていれば解除し、解除されていれば設定する、という事前の状態に依存する動作になります。
1 2 3 |
Sub ConfuseAutoFilter() ActiveSheet.Range("A1").AutoFilter '// 設定 or 解除 End Sub |
AutoFilterメソッドとAutoFilterオブジェクト
上のコードで書いている「AutoFilter」メソッドの他に、同じAutoFilterという名前のオブジェクトがあります。
AutoFilterメソッドとAutoFilterオブジェクトはそれぞれ用途が異なります。
後でも書いていますが、AutoFilterメソッドはRangeオブジェクトのメソッドで、AutoFilterオブジェクトはワークシートのオブジェクトです。
個人的にはこういう混乱をまねくような、設定と解除が同じメソッド名で実装されていたり、プロパティとメソッドの名前が同じなのはVBAの言語としての実装ミスと思うのですが、そうは言っても仕方ありませんし、対応方法はありますので以下を参照してください。
オートフィルタが設定されているかの確認方法
オートフィルタの設定と解除を行う前に、今のシートがどういう状況かを確認する必要があります。
オートフィルタが設定され、絞込みができる状況にあるかどうかを調べるにはシートのAutoFilterModeプロパティで判定します。
Trueの場合は設定済み、Falseの場合は未設定です。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
Sub CheckAutoFilterStatus() '// オートフィルタが設定されている場合 If (ActiveSheet.AutoFilterMode = True) Then '// 省略 '// オートフィルタが解除されている場合 Else '// 省略 End If End Sub |
オートフィルタで絞込みが行われているかの確認方法
オートフィルタで何かの値で絞込みが行われているかどうかの確認はFilterModeプロパティで判定します。
FilterModeプロパティはシートのAutoFilterオブジェクトのプロパティになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
Sub CheckFilterModeStatus() '// オートフィルタ未設定時は処理を抜ける If (ActiveSheet.AutoFilterMode = False) Then Exit Sub End If '// 絞り込みされている場合 If (ActiveSheet.AutoFilter.FilterMode = True) Then '// 省略 '// 絞り込みされていない場合 Else '// 省略 End If End Sub |
なお、Excel操作で絞り込みを解除する場合は、データタブの「並べ替えとフィルター」のクリアボタンを押します。
AutoFilterオブジェクトとAutoFilterプロパティの違い
オートフィルタ周りのコードを書く際に「AutoFilter」と書く個所が出てきますが、文字は同じでも使い方には2種類あります。
1つはワークシートのオブジェクト(というかクラス)としてのAutoFilterで、もう1つはRangeオブジェクトのメソッドとしてのAutoFilterです。
ワークシートのAutoFilterクラス
ワークシートのAutoFilterクラス(オブジェクト)は先に紹介しているFilterModeプロパティなどを持つクラスになります。
クラスのため、オブジェクト変数にコピーすることも可能です。
こんな感じです。
2行目で変数定義、5行目でクラス変数をコピー、8行目でクラス変数を使ってプロパティを利用しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
Sub CopyAutoFilterClass() Dim obj As AutoFilter '// AutoFilterクラス変数をコピー Set obj = ActiveSheet.AutoFilter '// AutoFilterクラス変数を使ってFilterModeプロパティで絞込み状態を判定 If (obj.FilterMode = True) Then '// 省略 Else '// 省略 End If End Sub |
RangeオブジェクトのAutoFilterメソッド
RangeオブジェクトのAutoFilterメソッドは、オートフィルターの設定と解除を行います。
全く同じコードで、設定と解除それぞれの処理を行いますので、確実に設定もしくは解除を行いたい場合はAutoFilterメソッドを使う前にオートフィルターの設定状況を確認する必要があります。
例えばこんなソースがあった場合、事前にオートフィルタが設定されているかどうかで結果が変わります。
設定されていれば、解除し、解除されていれば設定します。
1 2 3 4 5 |
Sub ConfuseAutoFilter() ActiveSheet.Range("A1").AutoFilter '// 設定 or 解除 ActiveSheet.Range("A1").AutoFilter '// 解除 or 設定 ActiveSheet.Range("A1").AutoFilter '// 設定 or 解除 End Sub |
しかし実際にコーディングする場合はそういうのは困るので、こんな感じで事前チェックを行った方が無難です。
1 2 3 4 5 6 7 8 9 10 |
Sub CheckdAutoFilter() '// 解除されているかを確認 If (ActiveSheet.AutoFilterMode = False) Then '// 解除されている場合は処理を抜ける Exit Sub End If '// オートフィルタを設定する ActiveSheet.Range("A1").AutoFilter End Sub |
オートフィルタの設定と解除を明確に切り分ける方法
先に書いたとおり、オートフィルタの設定と解除は同じ書き方で書けるのですが、そういうことをやると混乱の元ですのでやらない方がいいです。
ではどうするかというと、設定用の関数と解除用の関数をそれぞれ用意し、必要なときに呼び出すようにします。
オートフィルタ設定関数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
'// オートフィルタ設定関数 Sub AutoFilterOn() Dim sArray() As String '// 絞り込み文字列配列 '// オートフィルタが設定されている場合 If (ActiveSheet.AutoFilterMode = True) Then Exit Sub End If '// 列を指定し、オートフィルタを設定する Range("A1:K1").AutoFilter '// 絞り込む列のフィルター内容を格納する一次元配列 ReDim sArray(3) sArray(0) = "aaa" sArray(1) = "BBBBB" sArray(2) = "c" sArray(3) = "dd" '// オートフィルタの設定。 '// Field:オートフィルタが設定された列の左から順に1から番号が振られる。ここでは一番左の列のフィルタ初期値であることを示す。 '// Criteria1:抽出する文字列を配列で指定する。絞り込みした状態で表示される。 '// Operator:フィルタの種類を指定する。xlFilterValuesはフィルタの値であることを示す。 ActiveSheet.Range("A1").AutoFilter Field:=1, Criteria1:=Array(sArray), Operator:=xlFilterValues End Sub |
オートフィルタ解除関数
1 2 3 4 5 6 7 8 9 |
'// オートフィルタ解除関数 Sub AutoFilterOff() '// オートフィルタが解除されている場合 If (ActiveSheet.AutoFilterMode = False) Then Exit Sub End If ActiveSheet.Range("A1").AutoFilter End Sub |
上記の2つ関数ではAutoFilterメソッドで設定と解除を行っていますが、その関数自体の用途でどちらを行うのかを明確にしています。
それぞれの関数の先頭で、オートフィルタの状態を判定した上で処理を行うようにしています。
こうすることでより用途が明確になります。