ListObjectの絞り込み解除
ListObjectについて、下記のようなシリーズで説明しています。・ListObjectの作成と概要
・ListObjectの並べ替え
・ListObjectの絞り込み
・ListObjectの絞り込み解除 ←今回
・ListObjectの絞り込みデータの配列化
・ListObjectのデータ追加
・ListObjectのデータ変更
・ListObjectのデータ削除
今回は、ListObjectオブジェクトの「絞り込み解除」について説明します。
1.手動でのテーブルの絞り込み解除
まず手動で絞り込みを解除する手順を確認します。通常は図1のように、絞り込みを解除したい列の「フィルターボタン①」をクリックします。フィルターボタンは絞り込み等がされていない場合は、下三角形「」の形をしていますが、絞り込みを行っている列ではロートの付いた「」形になります。
(なお、昇順並び替え+絞り込みの場合は「」、また降順並び替え+絞り込みの場合は「」の形となっています。)
図1
絞り込みの「フィルターボタン①」をクリックするとメニューが現れ、その下の方に「(すべて選択)」に続いたリスト項目のチェックボックスが並んでいます。その「(すべて選択)」のチェックボックスにチェック②を入れると、全てのチェックボックスにチェックが入り③、OKボタンをクリック④することで絞り込みが解除⑤されます。
また図2のように、テーブルの一部をセル選択⑥し、リボンの「データ」タブ→「並べ替えとフィルター」グループ→「クリア⑦」をクリックすることで、テーブルの全列の絞り込み解除がまとめて行えます。但し、この操作では「並べ替えも解除」されてしまうので注意が必要です。
図2
2.マクロでのテーブルの絞り込み解除
絞り込みをVBA側から解除するには、以下の4種類の方法がありそうです。- [テーブル].Range.AutoFilter Field:=列位置 …… Fieldパラメータのみを指定して1列ずつ解除
- [テーブル].Range.AutoFilter …… 全パラメータを指定せずにフィルタ―ボタンを消去・再表示
- [テーブル].ShowAutoFilter …… False/True設定でフィルタ―ボタンを消去・再表示
- [テーブル].AutoFilter.ShowAllData …… 全データを表示(=解除)
2ー1.1列ずつ解除
他のサイトでも多く紹介されているのが、AutoFilterメソッドにFieldパラメータのみを指定することで「指定した列の絞り込みを解除」させる方法です。列が絞り込まれている状態か否かは「AutoFilter.Filters(列位置).Onプロパティ」の値を調べます。絞り込み解除の実行プロシージャを図3に示します。引数として対象のListObjectオブジェクトを指定します。
- '========== ⇩(1) 1列ずつ解除 ============
- Sub TableFilterOff_01(T As ListObject)
- Dim i As Integer '←カウンタ変数(列位置)
- If T.ShowAutoFilter = False Then
- T.ShowAutoFilter = True
- Exit Sub
- End If
- For i = 1 To T.ListColumns.Count
- If T.AutoFilter.Filters(i).On = True Then
- T.Range.AutoFilter Field:=i
- End If
- Next i
- End Sub
09行目「For i = 1 To T.ListColumns.Count」で、カウンタ変数iをテーブルの列数分だけ回して、1列ずつ処理を行います。「T.ListColumns.Count」の代わりに「T.HeaderRowRange.Count」や「T.AutoFilter.Filters.Count」でも同じようにテーブルの列数が得られます。
10行目「If T.AutoFilter.Filters(i).On = True Then」では、その対象の列が「絞り込まれているか否か」を調べます。
「テーブル.AutoFilter.Filter」には、図4のようなプロパティがありますので、その内の「Onプロパティ」を使用しています。
プロパティ | 内容 |
---|---|
Count | Filters.Countとすることで、フィルタの数を取得 |
Criteria1 | 絞り込み時のCriteria1の条件式を取得 絞り込んでいない列ではエラー発生 |
Criteria2 | 絞り込み時のCriteria2の条件式を取得 Criteria2が無い時や、絞り込んでいない列ではエラー発生 |
On | 絞り込みしている列はTrue |
Operator | 絞り込み時のOperatorの値 Criteria1のみの単純な絞り込みの時はゼロ値 |
10行目が成立した「絞り込まれている列(=True)」の場合は、11行目「T.Range.AutoFilter Field:=i」と、AutoFilterメソッドにFieldパラメータのみを指定(=Criteria1を指定していないため、全ての値を指定したことになる)することで「指定した列の絞り込みを解除」します。
但し09~13行目が成立するのは「フィルターボタンが表示されている」場合です。フィルターボタンが表示されていない状態で実行されると、10行目「T.AutoFilter.Filters(i).On」のOnプロパティ値を取得する時にエラーが発生します。
そのため04行目「If T.ShowAutoFilter = False Then」で、フィルターボタンが非表示の時には05行目「T.ShowAutoFilter
なお11行目「T.Range.AutoFilter Field:=i」では、フィルターボタンが無くてもエラーは発生せず、「フィルターボタンを再表示」するだけ という動作となります。ですので、04~07行目のフィルターボタン有無での処理、及び10行目の絞り込み有無の判断を無くした図5のようなプロシージャでもOKです。
但し、全ての列に対して(絞り込みがされていても、いなくても)絞り込み解除の処理をしますので、処理時間は他のコードよりも多くかかります。
- '========== ⇩(2) 絞り込まれていなくても1列ずつ解除 ============
- Sub TableFilterOff_02(T As ListObject)
- Dim i As Integer '←カウンタ変数(列位置)
- For i = 1 To T.ListColumns.Count
- T.Range.AutoFilter Field:=i
- Next i
- End Sub
2ー2.AutoFilterメソッドでボタン消去・再表示
AutoFilterメソッドをパラメータ無しで実行する方法が図6です。- '========== ⇩(3) AutoFilterメソッドでボタン消去・再表示 ============
- Sub TableFilterOff_03(T As ListObject)
- If Not T.AutoFilter Is Nothing Then
- T.Range.AutoFilter
- End If
- T.Range.AutoFilter
- End Sub
44行目・47行目の「T.Range.AutoFilter」は、実行されるたびに「フィルターボタンを消去・表示」を繰り返します。ですので、フィルターボタンが表示されている状態から「AutoFilter 実行」→「AutoFilter 実行」と2回繰り返せば、フィルターボタン表示→「消去」→「再表示」となり、「表示→消去」の時に絞り込みが解除されることになります。
ただし初期状態が「フィルターボタン無し」の状態から2回「AutoFilter 実行」を繰り返してしまうと、最後が「消去」の状態となってしまいます。フィルターボタンが無い状態は「テーブル.AutoFilter = Nothing」で判断できますので、43行目「If Not T.AutoFilter Is Nothing Then」で、フィルターが存在する場合だけ2回(フィルターが無い状態では1回のみ)繰り返すようにしています。
2ー3.ShowAutoFilterプロパティでボタン消去・再表示
テーブルのShowAutoFilterプロパティを操作し「フィルターボタンを消去・再表示」させて絞り込みを解除させるのが図7です。- '========== ⇩(4) ShowAutoFilterプロパティでボタン消去・再表示 ============
- Sub TableFilterOff_04(T As ListObject)
- If T.ShowAutoFilter = True Then
- T.ShowAutoFilter = False
- End If
- T.ShowAutoFilter = True
- End Sub
「テーブル.ShowAutoFilter」は状態取得/設定の両方が可能なプロパティで、取得時にTrue値ならば「フィルターボタンが表示」されている事を表しています。またTrueに設定するとフィルターボタンが表示され、Falseに設定すると消去されます。
ですので「フィルターボタンが表示されている状態」→「False設定でフィルターボタン消去」→「True設定で再表示」すれば、表示→消去の段階で絞り込みが解除されることになります。
但し、最初から「フィルターボタンが無い(=絞り込みが既に解除されている)」状態ならば、False設定でボタンを消去する必要はありません。ですので63行目「If T.ShowAutoFilter = True Then」で「フィルターボタンが存在している時」だけ64行目「T.ShowAutoFilter = False」で「(絞り込みの有無にかかわらずに)フィルターボタンを消去」し、67行目「T.ShowAutoFilter = True」でフィルターボタンを再表示しています。
なお、フィルターボタンの存在有無を確認する方法として今回の「ShowAutoFilterプロパティ」を使う以外に、図6の43行目のような「If Not T.AutoFilter Is Nothing Then」の方法も使えます。
2ー4.ShowAllDataで全データを表示
ShowAllDataメソッドを使い、全データを表示することで絞り込みを解除する方法が図8です。- '========== ⇩(5) ShowAllDataで全データを表示 ============
- Sub TableFilterOff_05(T As ListObject)
- If T.AutoFilter Is Nothing Then
- T.Range.AutoFilter
- Exit Sub
- End If
- If T.AutoFilter.FilterMode = True Then
- T.AutoFilter.ShowAllData
- End If
- End Sub
フィルターボタンが存在する時には、89行目「T.AutoFilter.ShowAllData」で全データを表示させて「絞り込みを解除」させます。なお絞り込まれていない場合は無駄になりますので、88行目「If T.AutoFilter.FilterMode = True Then」で絞り込まれている場合にのみ実行するようにしています。
但しフィルターボタンが無い場合は、88行目・89行目ともエラーが発生してしまいますので、83~86行目で「フィルターボタンが存在しない(=絞り込みも解除済み)場合は、フィルターボタンを表示させて終了」するようにしています。
83行目「If T.AutoFilter Is Nothing Then」でフィルターボタンの存在を確認し、存在しない場合は84行目「T.Range.AutoFilter」でフィルターボタンを表示させて、85行目「Exit Sub」で制御を呼び出し側に戻しています。
なお、図3の04~07行目のようなコードを使ってもOKです。
他のサイトでは、ワークシート(ActiveSheet)に対してFilterModeプロパティを使用して絞り込み有無を確認し、ShowAllDataで絞り込みを解除する手法を良く紹介しています。FilterMode・ShowAllDataはWorksheetクラスだけでは無く、AutoFilterクラスにも存在します。但し微妙に仕様が異なるので、その比較を図9にまとめました。
今回はAutoFilter側を使用しています。セル選択位置に影響されないという特性からもAutoFilter側の方が使い易い気がしますが、それぞれの特徴を把握した上で使って下さい。
ActiveSheet | [テーブル] | |||
---|---|---|---|---|
フィルター ボタン有 | FilterMode プロパティ | 手動 絞込 | 選択セルのテーブルが絞り込まれていればTrue、 並べ替えのみではFalse。 テーブル以外を選択時はFalse | 対象テーブルが絞り込まれていればTrue 並べ替えのみではFalse |
VBA 絞込 | シート上の1テーブルが絞り込まれていれば、どこを選択中でもTrue。 但し、選択領域を移動(テーブル⇔テーブル以外、テーブル→異なるテーブル)すると、手動絞込と同状態になる。 また並べ替えのみではFalse | |||
ShowAllData メソッド | 絞り込み+並べ替えが解除。 ActiveSheetのFilterModeがFalseの時はエラー発生 | 絞り込みが解除されるが、並べ替えは解除されず。 テーブルのFilterModeがTrue/Falseどちらでもエラーは発生せず | ||
フィルター ボタン無 | FilterMode プロパティ | False | エラー | |
ShowAllData メソッド | エラー | エラー |
図9
アプリ実例
「DVD等の内容・保管場所等管理システム」「先行予約可能な備品予約・貸出システム」
「ToDoリストで個人タスク管理」
「会社番号検索システム」