ListObjectの絞り込み
ListObjectについて、下記のようなシリーズで説明しています。・ListObjectの作成と概要
・ListObjectの並べ替え
・ListObjectの絞り込み ←今回
・ListObjectの絞り込みの解除
・ListObjectの絞り込みデータの配列化
・ListObjectのデータ追加
・ListObjectのデータ変更
・ListObjectのデータ削除
今回は、ListObjectオブジェクトの「絞り込み」について説明します。
1.手動でのテーブルの絞り込み
まず手動で絞り込みをする手順を確認します。通常は図1のように、絞り込みをしたい列の「フィルターボタン(下向き三角印)①」をクリックし、「テキストフィルター」「数値フィルター」「日付フィルター」など②を選択します。
「テキストフィルター②」を選択すると、更に「指定の値に等しい(E)」などの、今から指定する絞り込み値に対する「比較条件③」を選択することが出来ますので、希望の比較条件を選びます。どれを選択しても、同じ「カスタムオートフィルター④」のダイアログが表示されます(ダイアログ表示時に、目的の比較演算子が選択状態になるだけです)。
図1
「カスタムオートフィルター④」には、列名(対象列)が表示されていますので、まず確認が必要です。
絞り込みの条件式は「比較演算子」+「絞り込み値」のセットで設定します。比例演算子はドロップダウンリストの選択式になっており、図1の最右のように12種から選択します。
条件式が1つの場合は、上の段の選択・入力でOKですが、上限と下限で挟み込むような場合や2条件の場合は、下の段にも条件式を設定します。そしてその第一条件と第二条件の間の関係を「AND」または「OR」のオプションボタンで選択をします。
入力が完了し右下のOKボタンをクリックすれば、絞り込みが実行されます。
絞り込みがされた列のフィルタ―ボタンは、「」のようなロート付きの下向き三角マークに変わります。また絞り込みと併せて昇順の並べ替えがされている場合は「」、降順の場合は「」のマークとなります。
「テキストフィルター」の場合は図1のような流れになりますが、これをメニューの流れだけを示すと図2のようになります。
どれを選んでも「カスタムオートフィルター」ダイアログが起動します。
図2
「数値フィルター」「日付フィルター」の場合は少し異なります。
まず「数値フィルター」の方は図3のような流れになります。多くの項目はテキストフィルターと同様「カスタムオートフィルター」ダイアログが起動しますが、「トップテン」を選んだ時には「トップテン オートフィルター」というもので操作をします。「トップテン オートフィルター」では、「上位」「下位」の選択と、絞り込む数を「項目数」にするか「パーセント」にするかを選びます。
また「平均より上」「平均より下」についてはダイアログが現れずに、クリックした途端に絞り込みが実行されます。
図3
数値フィルターから開く「カスタムオートフィルター」にも「比較演算子を選択するコンボボックス」があり、内容は文字列の時と同じです。その中の「と等しい」から「以下」までの6種類は数値として当然使えるのですが、それより下の「で始まる」や「を含む」のように「数値とは思えない比較演算子」も選択できてしまいます。
しかし「1で始まる」や「2を含む」と設定しても、1000が抽出されたり123が抽出されたりする事はありません。マクロ記録で確認しても「"=*1"」や「"=*1*"」となり、数値を絞り込む式ではなくなっています。上側6種(「以下」まで)が使用可と考えた方が良いです。
「日付フィルター」の方は図4のようになり、ほとんどの項目でクリックした途端に絞り込みが実行されます。「日付を手入力」する上の方の項目と、一番下の「ユーザー設定フィルター」を選択した時だけ「カスタムオートフィルター」ダイアログが起動します。しかし「1で始まる」や「2を含む」と設定しても、1000が抽出されたり123が抽出されたりする事はありません。マクロ記録で確認しても「"=*1"」や「"=*1*"」となり、数値を絞り込む式ではなくなっています。上側6種(「以下」まで)が使用可と考えた方が良いです。
図4
日付フィルターから開く「カスタムオートフィルター」のコンボボックスは、文字列・数値の時とは多少表現が違いますが内容は一緒です。 (より大きい→より後、以上→以降、より小さい→より前、以下→以前)
そして、数値の時と同様に「で始まる」や「を含む」が選択できてしまいます。しかし数値の時と同様に、上側6種(「以下」まで)以外では抽出されません。
なおExcelを含めたOffice全般の話になりますが、メニューの後ろに「...」がついているものは「ダイアログ」が表示され、「」がついているものは「まだ、下位のメニューがある」ことを意味しています。なにもついていない項目は、クリックすればすぐに実行されます。
フィルタ―ボタンをクリックした時の表示が「テキストフィルター」「数値フィルター」「日付フィルター」のどのフィルターになるかは、列の各セルの値の中で「どの種類のデータ型が一番多いか」で決まるようです。 例えば10個のセルの内、日付が3個、数値が3個、文字列が4個だったら、テキストフィルターと表示されます。なお、同数の場合はテキストフィルターとなるようです。 |
2.マクロでのテーブルの絞り込み
2-1.構文
上記「テキストフィルター」「数値フィルター」「日付フィルター」を合わせると多くの「絞り込みメニュー」がありますが、VBAで表すと実行しているのは下記構文1つです。[ListObjectオブジェクト].Range.AutoFilter (Field, Criteria1, Operator, Criteria2, SubField, VisibleDropDown)
絞り込みの範囲としては、テーブルのタイトル部(フィルターボタンのある行)を含んだデータが必要なため、ListObjectの「Range」を対象範囲とします。また、AutoFilterメソッドのパラメータは、図5の6個です。
名前 | 型 | 内容 |
---|---|---|
Field | Variant | 列番号 |
Criteria1 | Variant | 1番目の抽出条件(数値、文字列、配列) |
Operator | XlAutoFilter | フィルター種類 |
Criteria2 | Variant | 2番目の抽出条件(数値、文字列、配列) |
SubField | Variant | 抽出条件を適用するデータ型のフィールド |
Visible | Variant | オートフィルタのドロップダウン矢印 |
「Field」にはテーブルの列番号を意味する「数値」を指定します。列名(文字列)で指定したい場合は「[ListObjectオブジェクト].Listcolumns([列名]).Index」とすることで「列番号(数値)」が得られます。また、このコードの「列名の場所に列番号の数値」を入れても、その列番号がそのまま戻されることになりますので、どちらでも使えるコードです。
また「複数の列に対して同じ絞り込み」をする場合は、Fieldに対して「列位置の配列」を指定することが出来ます。例えば「Field:=Array(1, 6)」とすれば「1列目」と「6列目」に対して、同じ絞り込みをします。
使い道としては、「複数の列に、同じある値があるデータ」を絞り込む時などがあると思います。
「Criteria1」「Criteria2」には、「絞り込みの条件式(文字列)」「絞り込み条件を表す値(数値)」または「条件の配列」を入れます。
文字列の「条件式」は、図6の比較演算子やワイルドカードを使用して作成します。また「条件を表す値」には図15・図21の定数・値や、項目数・パーセントを表す数値を入れます。
「Operator」には図7の定数・値を指定しますが、絞り込みの条件によって複雑に使い分けなければならず、詳細は「列のデータ型ごとの絞込み」で説明します。
「SubField」はExcel2016以降で設定されたパラメータで、「新しいデータ型である株式の[量]フィールドや、地理データ型の[人工]フィールドなどに条件を指定するときに使う引数」と各サイトで説明されていますが、使い方も指定の仕方も良く分かりませんでした。
「VisibleDropDown」にFalseを設定すると、絞り込み実行後に「指定列のドロップダウン矢印が非表示」になります。ドロップダウン矢印が非表示になってもマクロ側からは正常に操作が出来ますので、「マクロ側で絞り込んだ後は、ユーザーには手動で絞り込みをさせない」等の時には有効と思います。
記号 | 内容 | 例 |
---|---|---|
= | 等しい値に絞り込む (「=」は省略可) | "=道" 又は
"道" (「道」という値を抽出) |
<> | 等しく無い値に絞り込む | "<>道" (「道」という値以外を抽出) |
< | 未満 | "<10" (10未満の値を抽出) |
<= | 以下 | "<=10" (10以下の値を抽出) |
> | を超える | ">10" (10超の値を抽出) |
>= | 以上 | ">=10" (10以上の値を抽出) |
*(アスタリスク) | 任意の文字をゼロ個以上 | "=*道" (「道」で終わる値を抽出) |
?(クエスチョン) | 任意の文字を1個 | "=??道" (「道」で終わる3文字を抽出) |
~(チルダ) | 「*」「?」そのものを表す記号 | "=~*" (「*」という値を抽出) |
定数 | 値 | 内容 |
---|---|---|
xlAnd | 1 | Criteria1 と Criteria2 の論理 AND |
xlOr | 2 | Criteria1 または Criteria2 の論理 OR |
xlTop10Items | 3 | 表示される最も高い値のアイテム |
xlBottom10Items | 4 | 表示される最も低い値のアイテム |
xlTop10Percent | 5 | 表示される最も高い値のアイテム |
xlBottom10Percent | 6 | 表示される最も低い値のアイテム |
xlFilterValues | 7 | フィルターの値 |
xlFilterCellColor | 8 | セルの色 |
xlFilterFontColor | 9 | フォントの色 |
xlFilterIcon | 10 | フィルター アイコン |
xlFilterDynamic | 11 | 動的フィルター |
xlFilterNoFill | 12 | 内部使用 |
xlFilterAutomaticFontColor | 13 | 内部使用 |
xlFilterNoIcon | 14 | 内部使用 |
ここまで、いくつかの表を含めて説明してきましたが、これらの全ての組み合わせが自由に使える訳ではありません。中にはエラーが出たり、Excelが正常終了できなくなるほどの重症になることもあります。
そこで、テーブルの列のデータ型(文字列・数値・日付)ごとに可能な組み合わせを説明していきます。なお今回は、使い方の良く分からない「SubField」と、VBA側からテーブルのデータを操作する上では直接関係ないと思われる「VisibleDropDown」については省略したいと思います。
また「セルの色でフィルタ―」などはListObjectであると言う理由から除外しています。
なおSubFieldは、「SubField:=0」や「SubField:=""」のように「無効っぽく指定」してもエラーが出てしまう場合がありますので、使い方に不安がある内は記述しない方が良いと思います。
2-2.文字列の絞込み
まず、文字列の場合に使用できる絞り込みの組み合わせは図8のようになります。No | 目的 | Criteria | Operator | Criteria |
---|---|---|---|---|
1 | 単一文字列を | "=文字列" (「=」は省略可) | - (xlAnd,xlOr, | - |
2 | 単一文字列を含む | "=[?*]文字列[?*]" 文字列前後に「*」「?」を設置 (「=」は省略可) | - (xlAnd,xlOr, | - |
3 | 複数文字列を | Array( (「=」は省略可) | xlFilter (または 7) | - |
4 | 2つの文字列を | "=文字列" (「=」は省略可) | xlAnd または xlOr (1 または 2) | "=文字列" (「=」は省略可) |
No.1は「1つの文字列を絞り込む」場合で、最も良く使われるパターンだと思います。この場合は、Criteria1に「絞り込む文字列」を指定します。先頭の「=(イコール)」は省略可能ですが、イコールを付けた方が「数式っぽく見え」ますし、また「比較演算子の1つ」として明記した方が良いと思います。
この時のOperatorは指定しません。なお「xlAnd(値1)」,「xlOr(値2)」,「xlFilterValues(値7)」は指定しても無視されますが、その他の定数(値で3~6、8~11)を指定するとエラーが出てしまいます。
また「内部使用」の定数の内、No.12~13を使用すると「思った通りの絞り込みにならない(何を絞り込んでいるのか理解できない)」ですし、No.14の場合にはエラーとなりますので、使ってはいけません。
他のサイトでは、「1つの文字列を絞り込む」時には「xlFilterValues(値7)」を使う と説明している事もあります。確かに「xlFilterValues」というスペルを見ると、Operatorの既定値とも受け取れる定数名です。 しかしもし既定値であるならば、図8のNo.3のようにCriteria1に配列を指定した時にも省略可能なはずですし、また図16のNo.20でCriteria2に日付の配列を指定し、OperatorにxlFilterValuesを指定した時に、ついでにCriteria1に「単一の文字列」を指定するとCriteria1が無視されます。 Criteria1の方がCriteria2よりも優先度が高いはずなのに無視されることから、xlFilterValuesは「配列データに特化した定数」と思われます。 |
No.2は「1つの文字列を含む絞り込み」で、文字列の前後にワイルドカードの「*(アスタリスク)」と「?(クエスチョンマーク)」を配置します。
図6の中でも説明していますが、「*」は「任意の文字をゼロ個以上」を表し、「?」は「任意の文字1個」を表します。例えば「Criteria1:="=*東?道"」とすると、「自動車東北道」「東海道」等はヒットしますが、「東北海道」は「東」と「道」の間には2文字(指定したのは「?」1つなので、1文字分)があるためにヒットしない事になります。
No.3は「複数文字列をORで絞り込む」場合で、「Criteria1:=Array("=東海道","=東北道")」のように文字列をArray関数を使って配列にして指定します(イコールは省略可)。そしてOperatorには「xlFilterValues(値=7)」を指定します。配列に列記した各文字列は「OR」で繋がっていますので、「配列内のどれかの文字列」がヒットすればOKとなります。
なおArray関数内の要素数は1からOKですので、例えば「Criteria1:=Array("=東海道")」も有りです。
No.3の配列内の文字列に「*」と「?」のワイルドカードが使えるか試してみました。すると「2要素の配列までは正しく動作」するのですが、「3要素以上の配列では、ワイルドカードを使用した要素は無効」となるようです。 例えば「Criteria1:=Array("東*","南*")」は「東」と「南」で始まる文字列が絞り込まれますが、「Criteria1:=Array("東*","南*","北")」と3要素となると、ワイルドカードを使った「"東*"」と「"南*"」の条件は無効(=無視)となり、ワイルドカードを使っていない「北」の文字列でしか絞り込まれません。 この現象をどの様に解釈したら良いのか分かりませんが、正常動作とはとても思えないので「配列内ではワイルドカードを使わない」方が良いと思います。 またCriteria1に配列を指定した場合、OperatorにxlFilterValuesを設定しなくても(代わりにxlAnd,xlOrを指定した時も)実行時エラーは出ません。しかしこの時は「配列の最後の要素の文字列のみで絞り込み」がされてしまいますので、配列時は必ず「xlFilterValues(値=7)」を指定して下さい。 |
No.4は「2つの文字列を絞り込む」場合です。Criteria1に1つ目の文字列を、Criteria2に2つ目の文字列を指定し、Operatorには「xlAnd(値=1)」または「xlOr(値=2)」を指定します。Criteria1とCriteria2には、No.2で説明した「*」と「?」のワイルドカードも使えます。
2つの文字列を「AND」でつなげられるのはNo.4のパターンだけですが、文字列をANDでつなげる事は、No.2のワイルドカードを使っても表現できます。例えば「Criteria1:="=*道",Criteria2:="=東*",Operator:=xlAnd」は「Criteria1:="東*道"」と同じになります。
また文字列の絞込みとして意味があるかは疑問ですが、比較演算子「=」の代わりにイコール以外(「>」等)も使用可能です。例えば「Criteria1:=">道"」とすることで、「『道』を超えるもの?」で絞り込めます。この時に比較に使用しているデータは「文字コード」のようで、「道」はS-JISで「 0x93b9」ですので、それよりも大きな文字コード(例えば「南(0x93EC)」)がヒットする事となります。
No.1の親戚で「データ有り」「データ無し」を絞り込むのが図9です。これは文字列の列のみでは無く、数値や日付の列の場合にも使えます。
No | 目的 | Criteria | Operator | Criteria |
---|---|---|---|---|
5 | 空白以外を | "<>" | - (xlAnd,xlOr, | - |
6 | 空白を | "=" (「=」は省略可) | - (xlAnd,xlOr, | - |
No.5は「空白以外」のデータの絞り込みで「Criteria1:="<>"」とします。
No.6は「空白のみ」のデータの絞り込みで「Criteria1:="="」とします。イコールを省略し「Criteria1:=""」としても同じ結果が得られえます。
2-3.数値列の絞込み
数値の場合の使用できる絞り込みの組み合わせは図10のようになります。No | 目的 | Criteria | Operator | Criteria |
---|---|---|---|---|
7 | 1条件の | "比較演算子+値" (「=」は省略可) | 無し (xlAnd,xlOr | - |
8 | 複数値を | Array( (「=」は省略可) | xlFilter (または 7) | - |
9 | 2条件の | "比較演算子+値" (「=」は省略可) | xlAnd または xlOr (1 または 2) | "比較演算子+値" (「=」は省略可) |
10 | 上位 | "項目数の数値" | xlTop10 (または 3) | - |
11 | 下位 | "項目数の数値" | xlBottom10 (または 4) | - |
12 | 上位 | "パーセントの数値" | xlTop10 (または 5) | - |
13 | 下位 | "パーセントの数値" | xlBottom10 (または 6) | - |
14 | 平均より上 | xlFilter (または 33) | xlFilter (または 11) | - |
15 | 平均より下 | xlFilter (または 34) | xlFilter (または 11) | - |
No.7は「1つの条件」での絞り込みで「Criteria1:="比較演算子+値"」と指定します。例えば「20以上」に絞り込むのであれば、図6の比較演算子を使って「Criteria1:=">=20"」となります。
なお比較演算子にイコールを使った(または比較演算子を省略した)場合、Criteria1に指定した数値の書式とExcelシート上のセル書式が合っていないと、正しく絞り込まれません。
例えば「5000」という数値のセルを、書式設定で先頭に「¥マーク」をつけて「¥5000」としたり、3桁ごとに「,(カンマ)」をつけて「5,000」としたりすると、Criteria1:="=5000"という指定ではヒットしないことになります。
対策としては「Criteria1:="=¥5000"」や「Criteria1:="=5,000"」のようにすれば正しく絞り込めます。
但し書式が合わず、例えばシート側が「¥5,000」という書式になっていたとしても、「Criteria1:=">=5000"」と「不等号付きの比較演算子」を使用すれば、正しく「¥5,000以上」の値が絞り込まれます。
どうも、イコールの場合は「値での比較」と共に「書式の比較」も行うために「書式まで合っていないとTrueにならない」のですが、イコール以外では書式の比較が外れて「値だけでの比較」が行われるようで、この傾向は日付の場合も同じです。
AutoFilterメソッドでイコールで絞り込みをする場合、「シート上の見かけの表示に合わせて数値・日付を指定」する必要がありますが、以下の様な対応策も考えられます。
- シート側の書式設定は「標準」状態にしておく(手動で変更しない)
データベース的にテーブルを使用する場合は、ユーザーの目に触れないところにシートを置くことで書式を保護することが可能です。
- 絞り込み直前に書式を標準に直す(手動で変更される場合)
「[ListObjectオブジェクト].ListColumns(列位置).DataBodyRange.NumberFormatLocal = "G/標準"」などを絞り込み前に実行させ、絞り込む列の書式を標準にする。
- 「>=」「<=」を使って、値を挟み込んで指定
書式設定によって絞り込みが左右されるのは、前述した様に比較演算子に「=」を使っている時のみです。
ですので例えば「Criteria1:="=5000"」の代わりに、
「Criteria1:=">=5000",Criteria2:="<=5000" 」,Operator:=xlAnd
と指定すれば、書式に関係なく絞り込むことが可能です。(但し、図10のNo.8やNo.9のような複雑な条件による絞り込みが出来なくなってしまいますが)
図11
「Criteria1には文字列が基本」で、例外は「OperatorにxlFilterDynamic(値=11)を指定した時のみCriteria1に数値」です。
No.8は「複数の値をORで絞り込み」する場合で、「Criteria1:=Array("=値","=値",…)」とArray関数を使って配列指定します。イコールは省略可能なので「Criteria1:=Array("値","値",…)」としてもOKですし、要素が1つだけの配列「Criteria1:=
例えば「20」と「30」で絞り込むのであれば「Criteria1:=Array("=20","=30")」とします。但しこのパターンでは「=」以外は使用できませんので、「Criteria1:=Array("<20",">30")」のような指定をするとエラーとなります。
またNo.7と同様に、シート側と同じ書式で配列内の値を指定する必要があります。書式が異なっているとヒットしません。
No.9は「2条件の絞り込み」です。Criteria1に1つ目の条件を文字列として指定し、Criteria2に2つ目の条件を文字列として指定します。Operatorには「xlAnd(値=1)」または「xlOr(値=2)」を指定します。
例えば「20~30」の範囲に絞り込むためには、「Criteria1:=">=20",Criteria2:="<=30"),Operator:=xlAnd」とします。
なお比較演算子にイコールを使う場合は、シート側と同じ書式で値を指定する必要があります。
No.10~13は、手動で「数値フィルター」→「トップテン」とクリックした先の「トップテンオートフィルター」のVBA版です。手動時に表示されるダイアログとVBAの各パラメータの関係を図12に示します。
図12
「トップテンオートフィルター」には、「上位・下位」コンボボックスと「項目・パーセント」コンボボックスの2箇所が選択可能です。また何項目・何パーセントに絞り込むかの「値」を入力します。
Autofilterメソッドでは、Criteria1には項目数やパーセントの数値に両端を「"(ダブルクォーテーション)」で囲んだ文字列として指定し、Operatorには図13の中から選択をし定数・値を指定します。
なおCriteria1へは数値をそのまま指定しても正常に動作しますが、基本は「Criteria1へは文字列で指定」です。
組み合わせ | 定数 | 値 |
---|---|---|
上位 × 項目 | xlTop10Items | 3 |
下位 × 項目 | xlBottom10Items | 4 |
上位 × パーセント | xlTop10Percent | 5 |
下位 × パーセント | xlBottom10Percent | 6 |
例えば「上位10項目」で絞り込みするのであれば「Criteria1:="10",Operator:=xlTop10Items」とします。なお「上位」とは「値の大きい側」の事を指します。
絞り込まれる対象からは「文字列と空白は除かれる」ので、文字列のみの列や空白のみの列で使用するとエラーが出ます。逆に言うと、日付列でも使用できますし、文字列の中に1つでも数値とみなせる値(=日付でも可)があれば動作します。
Criteria1に指定できる値は「1~500」の範囲で、小数点以下も受け付けてくれます。しかし選ばれる項目数は整数ですので、例えば「全20項目中の8%」という絞り込みをすると、計算上では1.6項目ですが1項目がヒットします。かと言って「全20項目中の4%=計算上では0.8項目」の場合でも1項目がヒットするので、Excelの中では「最低でも1項目ヒット、それ以上は切り捨て」という計算をしているようです。
また、同じ値が存在する場合には、引きずられてヒット項目が増えることになります。
但しAutoFilterの対象が「[ListObjectオブジェクト].Range」である場合、上位10項目などの計算対象範囲は「表示されている範囲ではなく全範囲」となります。そのため、例えば事前の別の絞り込みで「ヒットしようとしていた行が非表示(=絞り込みから外れた)」だった場合には、上位10項目に入っていたとしても表示されない(≒ヒットしなかった)ことになります。
No.14~15は、手動での「数値フィルター」をクリックした時に表示される「平均より上」「平均より下」に相当します。メニューとの対比では図14のような関係になります。
図14
Criteria1に指定する定数・値は、図15から選択します。またOperatorには「xlFilterDynamic(値=11)」を指定します。なおOperatorに「xlFilterDynamic」を指定する場合だけは、Criteria1に文字列では無く「数値を指定」しないとエラーになります。
定数 | 値 | 内容 | |
---|---|---|---|
xlFilterAboveAverage | 33 | 平均より上 | |
xlFilterBelowAverage | 34 | 平均より下 |
例えば「平均より上」を絞り込むには、「Criteria1:=xlFilterAboveAverage, Operator:=xlFilterDynamic」または値を使って「Criteria1:=33, Operator:=11」とします。
なお「平均より」とは比較演算子で書くと「>平均」「<平均」ということのようです。例えば「1~9」の連続値が入っている9行のデータがあった時、平均は「5」となります。これを「平均より上」で絞り込むと「5」より大きな「6・7・8・9」の行が抽出され、「平均より下」で絞り込むと「5」より小さな「1・2・3・4」の行が抽出されます。
「ジャスト平均値」のデータは、どちらにも含まれないことに注意して下さい。
なお「平均より」とは比較演算子で書くと「>平均」「<平均」ということのようです。例えば「1~9」の連続値が入っている9行のデータがあった時、平均は「5」となります。これを「平均より上」で絞り込むと「5」より大きな「6・7・8・9」の行が抽出され、「平均より下」で絞り込むと「5」より小さな「1・2・3・4」の行が抽出されます。
「ジャスト平均値」のデータは、どちらにも含まれないことに注意して下さい。
2-4.日付列の絞込み
日付の場合の使用できる絞り込みの組み合わせは図16のようになります。No | 目的 | Criteria | Operator | Criteria |
---|---|---|---|---|
16 | 1条件の絞込み | "比較演算子+日付" (「=」は省略可) | - (xlAnd | - |
17 | 1条件の絞込み | "比較演算子" & [列先頭セル] (「=」は省略可) | - (xlAnd | - |
18 | 1条件の絞込み 「=」以外 | "比較演算子" & | - (xlAnd | - |
19 | 複数日付を ORで絞込み | Array("=日付","=日付",…) (「=」は省略可) | xlFilterValues (または 7) | - |
20 | 複数日付等を ORで絞込み | - | xlFilterValues (または 7) | Array(レベル,"日付", ※レベル:0~5 |
21 | 2条件の絞込み | "比較演算子+日付" (「=」は省略可) | xlAnd 又は xlOr (1 または 2) | "比較演算子+日付" (「=」は省略可) |
22 | 2条件の絞込み | "比較演算子" & [列先頭セル] | xlAnd 又は xlOr (1 または 2) | "比較演算子" & [列先頭セル] |
23 | 2条件の絞込み 「=」以外 | "比較演算子" & CLng(CDate("日付")) | xlAnd 又は xlOr (1 または 2) | "比較演算子" & CLng(CDate("日付")) |
24 | 既定の日付 | 図21の値(1 ~ 32) | xlFilter (または 11) | - |
No.16は「1つの条件」での絞り込みで「Criteria1:="比較演算子+日付"」と指定します。
例えば「2022/1/1」を絞り込むのであれば、図6の比較演算子を使い「Criteria1:="=2022/1/1"」とします。
但しこれでヒットするのは、日付列の書式が「YYYY/M/D」の場合のみです。他の書式、例えば「YYYY/MM/DD」になっている場合は「Criteria1:="=2022/01/01"」と、セル側の日付書式に合わせてコードを記述します。
イコールを使用する場合は「マクロ側の日付書式をセル側に合わせる」必要があります。
一方、不等号が入っている場合(例えば「Criteria1:=">=2022/1/1"」)は、「2022/01/01」も「令和4年1月1日」も絞り込みをしてくれます(バージョンによってはダメな場合もあるかもしれません)。
また日付は「"2022/01/01"」のように「/(スラッシュ)」を使って年月日を区切ります。「.(ピリオド)」を使った「"2022.01.01"」のような日付は無効です。
No.17は、シートの書式を数式内に盛り込んだ方法です。
絞り込む日付を、絞り込み列の先頭セルの書式にFormat関数で変換してからCriteria1に渡しています。例えば日付列が4列目だとすると、その先頭セルの位置は「ListColumns(4)
「"=" & Format(CDate("2022/1/1"),
但し、書式を参照しているのは「列全体では無く、先頭セルのみ」なので、行によって書式が異なるような場合(例えば、手動でシートの書式を変更できる場合など)には、誤った絞り込みをすることになりますので注意が必要です。
No.18は「日付を数値として扱う」方法です。例えば「Criteria1:=">=" & CLng(CDate("2022/1/1"))」とすることで、絞り込む日付を数値にしてからデータ比較し、絞り込みを行っています。なお日付→数値に変換してしまうため、見かけ上は日付では無くなってしまいます。AutoFilterは、イコールの場合は「見かけの表示で絞り込み」を行いますので、「Criteria1:="=" & CLng(CDate("2022/1/1"))」またはイコールを省略して「Criteria1:=CLng(CDate("2022/1/1"))」としても、決して「2022/1/1 はヒットしません」。使えるのは「イコール以外の比較演算子」です。
また、日付を数値で表す場合、セル上とVBAとでは、図17のように日付の基準が異なっている事に注意が必要です。
図17
絞り込むデータ自体はセル上に存在するために、1900/1/1を「1」とするシリアル値です。しかし操作するVBA側では「1」は1899/12/31となります。このズレは1900/3/1で解消するのですが、それまでの間では例えば「Criteria1:=">=" & CLng(CDate("1900/2/1"))」で絞り込むと、「1900/2/1は除外され、1900/2/2以降が絞り込まれる」ことになります。
また、シート上では1900/1/1以前の日付は「日付値として認識されない」のですが、VBAでは「西暦100年1月1日(値= -657434)」までは計算可能です。
昔の日付を計算する時には注意が必要です。
No.19は、複数日付を絞り込むものです。Criteria1にArray関数を用いて配列の日付を指定し、Operatorに「xlFilterValues
例えば「Criteria1:=Array("=2022/1/1","=2022/2/2"),Operator:=xlFilterValues」とすることで、「2022/1/1 または 2022/2/2」の日付データを抽出することが出来ます。但しセル書式とVBA側の書式が合っている事が前提です。
No.20も複数日付を絞り込むものですが、日付だけでは無く「年」「月」「日」「時」「分」「秒」の6つのレベルでの絞り込みが出来ます。なおこの方法の時には、日付の前にイコールを付ける(例えば「Array(2,"=2022/1/1")」)とエラーが出ます。当然ながら不等号なども使用できず、「単に日付値を"(ダブルクォーテーション)で囲む」ようにします。
この方法は「配列データをCriteria1 では無く Criteria2 に指定」するのが特徴です。例えば「2022/1/1」と「2022/2/2」を「日にち単位」で絞り込むのであれば、
「Criteria2:=Array(2, "2022/1/1", 2, "2022/2/2"), Operator:=xlFilterValues」とします。
配列内は2つで1つの条件となっており、前側の数値はレベルを指し、後ろ側の文字列は「日付」又は「日付+時刻」を文字列で指定します。
図18
レベルの値は図19のように、0~5の数値です。
値 | 内容 | 注意事項 |
---|---|---|
0 | 後ろに指定した日付の年 | 対象となるセルは 日付形式の事 (時刻形式データはダメ) |
1 | 後ろに指定した日付の月 | |
2 | 後ろに指定した日付の日 | |
3 | 後ろに指定した日付+時刻の時 | |
4 | 後ろに指定した日付+時刻の分 | |
5 | 後ろに指定した日付+時刻の秒 |
例えば「Criteria2:=Array(1,"2022/1/1",1,"2022/2/2"),Operator:=xlFilterValues」とすれば「月レベル」ですので、「2022年1月」と「2022年2月」のデータを抽出することになります。
また「Criteria2:=Array(3,"2022/1/1 12:00:00",3,"2022/2/2 13:00:00"),Operator:=xlFilterValues」とすれば「時レベル」ですので、「2022年1月1日の12時台」と「2022年2月2日の13時台」のデータを抽出することになります。全ての日付の12時台、13時台という意味ではありません。
この方式は、シート上の日付の書式にほぼ影響を受けないで絞り込めるようです。また「Criteria2:=
なお「何でCriteria2 なのか?」という疑問が湧き、色々試してみました。 その結果、Criteria2には日付+レベルの配列を、OperatorにはCriteria1にxlFilterValuesを指定しているところに、「図10のNo.8」や「図8のNo.3」のような「Criteria1:=Array("値","値")」を追加指定すると、「日付と併せて、文字列・数値でも絞り込み」が出来ることに気が付きました。 つまり「文字列・数値・日付」が混在している列で絞り込む場合に、Criteria1には文字列と数値の配列を、Criteria2には日付+レベルの配列を指定し、OperatorにxlFilterValues(値=7)を指定することで「文字列・数値・日付等」を同時に絞り込む条件にすることが可能になるのです。データ型混在の列の絞込みには有効かもしれません。 但しCriteria1に配列では無く「単独の文字列や数値」を指定すると、Criteria2側で指定した日付では絞り込まれますが、Criteria1側で指定した値はエラーは出ませんが無視されます。例えば「Criteria1:="東海道"」や「Criteria1:="20"」のような指定をした場合です。 「Operator:=xlFilterValues」は、基本的には配列データの場合のみに使うもののようです。 また「よりみち」でも紹介した「Criteria1に指定した配列内でワイルドカードが使えるか」をCriteria2に日付+レベルの配列を指定した状態で試してみたところ、1要素でも無効となってしまいます。 「ワイルドカードは、Criteria2が無ければ3要素以上は無効、Criteria2がある時は1要素から無効」となり、これも不思議な現象です。 |
No.21は「2つの日付条件で絞り込む」方法で、No.16の2条件版です。期間の範囲を絞り込む場合には必須ですが、イコールを使う場合は書式を合わせる必要があります。
No.22も「2つの日付条件で絞り込む」方法で、No.17の2条件版です。行によって書式が異なる場合は正しい絞り込みが出来ません。
No.23も「2つの日付条件で絞り込む」方法で、No.18の2条件版です。イコールが使えませんが、日付データでしたら一応正しく絞り込みが出来ますので「日付期間を絞る」場合には最も良い手法のようです。
またイコールの代わりに、例えば「2022/1/1」を絞り込むのであれば
「Criteria1:=">=" & CLng(CDate("2022/1/1")),Criteria2:="<=" & CLng(CDate("2022/1/1")),Operator:=xlAnd」
と単一日付を挟み込んで絞り込むという方法にも使えます。
No.24は、手動メニューに対応した「既定の日付」の絞込みです。Operatorには「xlFilterDynamic(値=11)」を指定します。
手動メニューとの対応を図20に示し、Criteria1に指定する定数一覧を図21に示します。なお、図21と図15は同じ「XlDynamicFilterCriteria列挙型」の定数です。
図20
定数 | 値 | 内容 | |
---|---|---|---|
xlFilterToday | 1 | 今日 | |
xlFilterYesterday | 2 | 昨日 | |
xlFilterTomorrow | 3 | 明日 | |
xlFilterThisWeek | 4 | 今週 | |
xlFilterLastWeek | 5 | 先週 | |
xlFilterNextWeek | 6 | 来週 | |
xlFilterThisMonth | 7 | 今月 | |
xlFilterLastMonth | 8 | 先月 | |
xlFilterNextMonth | 9 | 来月 | |
xlFilterThisQuarter | 10 | 今四半期 | |
xlFilterLastQuarter | 11 | 前四半期 | |
xlFilterNextQuarter | 12 | 来四半期 | |
xlFilterThisYear | 13 | 今年 | |
xlFilterLastYear | 14 | 昨年 | |
xlFilterNextYear | 15 | 来年 | |
xlFilterYearToDate | 16 | 今年の初めから今日まで | |
xlFilterAllDatesInPeriodQuarter1 | 17 | 期 間 内 の 全 日 付 | 第1四半期 |
xlFilterAllDatesInPeriodQuarter2 | 18 | 第2四半期 | |
xlFilterAllDatesInPeriodQuarter3 | 19 | 第3四半期 | |
xlFilterAllDatesInPeriodQuarter4 | 20 | 第4四半期 | |
xlFilterAllDatesInPeriodJanuary | 21 | 1月 | |
xlFilterAllDatesInPeriodFebruray | 22 | 2月 | |
xlFilterAllDatesInPeriodMarch | 23 | 3月 | |
xlFilterAllDatesInPeriodApril | 24 | 4月 | |
xlFilterAllDatesInPeriodMay | 25 | 5月 | |
xlFilterAllDatesInPeriodJune | 26 | 6月 | |
xlFilterAllDatesInPeriodJuly | 27 | 7月 | |
xlFilterAllDatesInPeriodAugust | 28 | 8月 | |
xlFilterAllDatesInPeriodSeptember | 29 | 9月 | |
xlFilterAllDatesInPeriodOctober | 30 | 10月 | |
xlFilterAllDatesInPeriodNovember | 31 | 11月 | |
xlFilterAllDatesInPeriodDecember | 32 | 12月 |
例えば「今日」を絞り込みたいのであれば「Criteria1:=xlFilterToday, Operator:=xlFilterDynamic」とします。
ちなみに同じ「今日」を絞り込む為には、他の方法として以下のようなものが考えられます。
No.17 | Criteria1:=Format(CDate(Date),[ListObjectオブジェクト].ListColumns(列番号) | |
No.20 | Criteria2:=Array(2, Date), Operator:=xlFilterValues | |
No.23 | Criteria1:=">=" & CLng(Date), Criteria2:="<=" & CLng(Date), Operator:=xlAnd |
2-5.テーブル絞り込みのプロシージャ
「文字列」「数値」「日付」の列の絞込みは、以上のように結構複雑です。これを1つの実行プロシージャにまとめる事に意味があるかは分かりませんが、とりあえず紹介します。プロシージャ呼び出しの際には、各パラメータを引数として渡すことにします。絞り込み対象のテーブルは必須の引数ですし、また絞り込みの列も必須とします。なお列設定は単一列指定と配列を使った複数列指定がありますが、今回は「単一列の絞込み」とします。
残りは「Criteria1」「Operator」「Criteria2」の3パラメータですが設定有無の組み合わせとなりますので、実行プロシージャ側としてはOptional(省略可能な引数)として受け取ることにします。あり得る組み合わせは図22のように8種類です。
この8種類の内、どの組み合わせが来ているのかの判別には、Criteria1が指定されたら「4」、Operatorは「2」、Criteria2は「1」を足し合わせた値(図22の合計欄)を使うこととします。
4 | 2 | 1 | 合 計 | 図8、図9、図10、図16 の組み合わせNo. |
---|---|---|---|---|
Criteria1 | Operator | Criteria2 | ||
× | × | × | 0 | (パラメータ無し→列の絞り込み解除) |
× | × | 〇 | 1 | - |
× | 〇 | × | 2 | - |
× | 〇 | 〇 | 3 | 22 |
〇 | × | × | 4 | 1,2,5,6,7,16, |
〇 | × | 〇 | 5 | - |
〇 | 〇 | × | 6 | 3,8,10,11,12, |
〇 | 〇 | 〇 | 7 | 4,9,17,23,24,25 |
AutoFilterメソッドのパラメータが取り得る組み合わせは4種類で、図22の合計欄が「3」「4」「6」「7」の場合です。なお、ゼロ(=Field以外のパラメータ無し)の場合は「列の絞り込み解除」の動作となりますので、今回はあり得る組み合わせの中に含め、合計5種とします。
図23は、その5種のAutoFilterメソッドをまとめたプロシージャです。
なおAutoFilterメソッドは、パラメータの単純な組み合わせだけで無く、例えば「Operator:=xlFilterDynamicの時は、Criteria1は数値」だったり、「Criteria1に配列が来たら、Operator:=xlFilterValues」のような細かな制限があります。しかしそれらを全て盛り込むのは大変なので、「On Error Resume Next」でAutoFilterメソッド実行時にエラーが出てもスルーさせ、その後でエラー番号を確認することでユーザー側に伝えることにします。
- '========== ⇩(1) テーブルの絞り込み ============
- Sub TableFilter(T As ListObject, col As Variant, _
- Optional C1 As Variant, Optional Ope As XlAutoFilterOperator, Optional C2 As Variant)
- '// T :操作対象のListObjectオブジェクト
- '// col :絞り込み列。列名(文字列)でも列位置(整数)でもOK
- '// C1 :Critical1(文字列、数値、配列)
- '// Ope:Operator(数値 1~34)
- '// C2 :Critical2(文字列、数値、配列)
- Dim Param As Integer '←指定したパラメータの組み合わせ値(0~7)
- If Not IsMissing(C1) Then Param = Param + 4
- If Ope >= 1 And Ope <= 34 Then Param = Param + 2
- If Not IsMissing(C2) Then Param = Param + 1
- On Error Resume Next
- Select Case Param
- Case 0
- T.Range.AutoFilter Field:=T.ListColumns(col).Index
- Case 3
- T.Range.AutoFilter Field:=T.ListColumns(col).Index, _
- Operator:=Ope, Criteria2:=C2
- Case 4
- T.Range.AutoFilter Field:=T.ListColumns(col).Index, _
- Criteria1:=C1
- Case 6
- T.Range.AutoFilter Field:=T.ListColumns(col).Index, _
- Criteria1:=C1, Operator:=Ope
- Case 7
- T.Range.AutoFilter Field:=T.ListColumns(col).Index, _
- Criteria1:=C1, Operator:=Ope, Criteria2:=C2
- Case Else
- MsgBox "引数の指定が間違っています"
- End Select
- If Not Err.Number = 0 Then MsgBox Err.Description
- On Error GoTo 0
- End Sub
プロシージャの引数は図24の5つです。
No | 変数 | 必/略 | データ型 | 内容 |
---|---|---|---|---|
1 | T | 必須 | ListObject | 操作対象のListObjectオブジェクト |
2 | col | 必須 | Variant | 絞り込み列。列名(文字列)でも列位置(整数)でもOK |
3 | C1 | 省略可 | Variant | 条件1(文字列、数値、配列) |
4 | Ope | 省略可 | XlAutoFilter | フィルター種類 |
5 | C2 | 省略可 | Variant | 条件2(文字列、数値、配列) |
11~13行目では「引数としてCriteria1,Operator,Criteria2のどれとどれを受け取ったのか」を計算しています。
計算は図22でも示したように「Criteria1を二進数の3桁目,Operatorを2桁目,Criteria2を1桁目と、各引数を二進数の桁に見立て」て、受け取ったパラメータの桁数に1を立てるという方法です。
11行目「If Not IsMissing(C1) Then Param = Param + 4」では、第三引数のC1(Criteria1)を受け取った場合は「Param = Param + 4」で変数Paramに4(二進数の3桁目に1を立てる)を足します。
12行目「If Ope >= 1 And Ope <= 34 Then Param = Param + 2」では、第四引数のOpe(Operator)を受け取った場合は「Param = Param + 2」で変数Paramに2(二進数の2桁目に1を立てる)を足します。
なお引数Opeのデータ型は「XlAutoFilterOperator(Long相当)」としていますので、たとえ引数を受け取らなかったとしても変数には「ゼロ」が入ってきてしまいますので「IsMissing(Ope)」では有無を判別できません。またXlAutoFilterOperator型は1~34の範囲の値ですので、不等号記号を使って正しい値に絞り込んでいます。「If Not Ope = 0 Then Param = Param + 2」でも実質的にはOKと思います。
13行目「If Not IsMissing(C2) Then Param = Param + 1」では、第五引数のC2(Criteria2)を受け取った場合は「Param = Param + 1」で変数Paramに1(二進数の1桁目に1を立てる)を足します。
11~13行目で計算をした「引数の組み合わせ値」を使い、16行目「Select Case Param」で、AutoFilterメソッド実行文を分岐していきます。
図22でも示したように、合計値Paramが「0」「3」「4」「6」「7」の時のみにAutoFilterメソッドを実行しますので、それぞれの値でCase分けをします。
Optionalの引数がゼロの時(17行目「Case 0」)には、18行目「T.Range.AutoFilter Field:=T.ListColumns(col).Index」で、Fieldパラメータまでを実行します。これにより「その列の絞込みを解除」することになります。
なお、Fieldパラメータには列位置を「数値」で指定する必要があるのですが、「列名」で指定したい場合もあると思います。そのため引数colはVariant型にしています。
しかし「Field:=col」としたのでは、文字列を指定してしまうためエラーとなります。そこで今回は「Field:=T.ListColumns(col).Index」とし、列名を列番号に変換して指定することにしました。なお、このコードであれば「colに列番号の数値」を入れても、その列番号がそのまま戻されることになります。
引数の組み合わせ値(Param)が「3」の時(19行目「Case 3」)は、引数が「Operator」と「Criteria2」ですので、20~21行目「T.Range.AutoFilter Field:=T.ListColumns(col).Index, Operator:=Ope, Criteria2:=C2 」となります。
組み合わせ値が「4」の時(22行目「Case 4」)は、引数が「Criteria1」のみですので、23~24行目「T.Range.AutoFilter Field:=T.ListColumns(col).Index, Criteria1:=C1」です。
組み合わせ値が「6」の時(25行目「Case 6」)は、引数が「Criteria1」と「Operator」ですので、26~27行目「T.Range.AutoFilter Field:=T.ListColumns(col).Index, Criteria1:=C1, Operator:=Ope」です。
組み合わせ値が「7」の時(28行目「Case 7」)は、引数が「Criteria1」と「Operator」と「Criteria2」の全部ですので、29~30行目「T.Range.AutoFilter Field:=T.ListColumns(col).Index, Criteria1:=C1, Operator:=Ope, Criteria2:=C2」となります。
どの組み合わせにも当てはまらなかった場合(31行目「Case Else」)には、32行目「MsgBox "引数の指定が間違っています"」でコメントを出します。
また、各AutoFilterメソッドに誤ったパラメータ値を設定したりすると、実行時エラーでマクロ停止してしまいます。ですので15行目「On Error Resume Next」でエラーをスルーさせ、35行目「If Not Err.Number = 0 Then MsgBox Err.Description」でエラーが発生(Not Err.Number = 0)している時は、エラー内容(Err.Description)のコメントを出します。
2-6.実行プロシージャの呼び出し側
絞り込みを行うテーブルは「ActiveSheet.ListObjects(1)」とし、その中の1列目が数値列、2列目が文字列の列、3列目が日付列と仮定をして、以下の呼び出しコードを組み立てています。2-6ー1.対象が文字列の場合
文字列を対象にして、図23の絞り込み実行プロシージャを呼び出すコードが図25です。図8、図9の各Noごとに並べました。
- '========== ⇩(2) プロシージャへの指示(文字列) ============
- Sub AutoFilter_exec_String()
- 'No.1 単一文字列を絞込み
- Call TableFilter(ActiveSheet.ListObjects(1), 2, "=道")
- 'No.2 単一文字列を含む絞込み
- Call TableFilter(ActiveSheet.ListObjects(1), 2, "=*?道")
- 'No.3 複数文字列をORで絞込み
- Call TableFilter(ActiveSheet.ListObjects(1), 2, Array("東海道", "東北道"), xlFilterValues)
- 'No.4 2つの文字列を絞り込み
- Call TableFilter(ActiveSheet.ListObjects(1), 2, "東海道", xlOr, "東北道")
- 'No.5 空白以外を絞り込み
- Call TableFilter(ActiveSheet.ListObjects(1), 2, "<>")
- 'No.6 空白を絞り込み
- Call TableFilter(ActiveSheet.ListObjects(1), 2, "=")
- ' 絞り込み解除
- Call TableFilter(ActiveSheet.ListObjects(1), 2)
- End Sub
図25
54行目「Call TableFilter(ActiveSheet.ListObjects(1), 2, "=道")」は、図8のNo.1に対応するコードです。
ActiveSheet上に最初に作ったListObjectオブジェクトの「2」列目に対し、「"道"」というデータで絞り込みを行っています。
第二引数の「2」は、文字列の列名を指定してもOKです。また第三引数の「"=道"」は、イコールを省略して「"道"」としてもOKです。
56行目「Call TableFilter(ActiveSheet.ListObjects(1), 2, "=*?道")」は、図8のNo.2に対応します。
第三引数を「"=*?道"」としていますので、「道」という文字で終わり、且つ「?(クエスチョンマーク)」が前に1つ入っていますので、道を含めて2文字以上の文字列で絞り込むことになります。
58行目「Call TableFilter(ActiveSheet.ListObjects(1), 2, Array("東海道", "東北道"), xlFilterValues)」は、図8のNo.3に対応します。
「東海道」または「東北道」で絞り込んでいます。
60行目「Call TableFilter(ActiveSheet.ListObjects(1), 2, "東海道", xlOr, "東北道")」は、図8のNo.4に対応します。
58行目と同じく「東海道」または「東北道」で絞り込んでいます。
62行目「Call TableFilter(ActiveSheet.ListObjects(1), 2, "<>")」は、図9のNo.5に対応します。
空白以外のデータで絞り込んでいます。
64行目「Call TableFilter(ActiveSheet.ListObjects(1), 2, "=")」は、図9のNo.6に対応します。
62行目とは逆で、空白のデータで絞り込んでいます。
66行目「Call TableFilter(ActiveSheet.ListObjects(1), 2)」は、第三引数以降を省略していますので、第二引数で指定した「2列目」の絞り込み解除をしています。
2-6ー2.対象が数値列の場合
数値の列を対象にして、図23の絞り込み実行プロシージャを呼び出すコードが図26です。図10の各Noごとに並べました。
- '========== ⇩(3) プロシージャへの指示(数値列) ============
- Sub AutoFilter_exec_Numeric()
- 'No.7 数値の1条件の絞込み
- Call TableFilter(ActiveSheet.ListObjects(1), 1, ">5")
- 'No.8 数値の複数値をORで絞込み
- Call TableFilter(ActiveSheet.ListObjects(1), 1, Array("3", "5"), 7)
- 'No.9 数値の2条件の絞り込み
- Call TableFilter(ActiveSheet.ListObjects(1), 1, ">5", xlAnd, "<8")
- 'No.10 数値の上位Top10(項目)
- Call TableFilter(ActiveSheet.ListObjects(1), 1, "3", xlTop10Items)
- 'No.11 数値の下位Top10(項目)
- Call TableFilter(ActiveSheet.ListObjects(1), 1, "3", xlBottom10Items)
- 'No.12 数値の上位Top10(%)
- Call TableFilter(ActiveSheet.ListObjects(1), 1, "20", xlTop10Percent)
- 'No.13 数値の下位Top10(%)
- Call TableFilter(ActiveSheet.ListObjects(1), 1, "20", xlBottom10Percent)
- 'No.14 数値の平均より上
- Call TableFilter(ActiveSheet.ListObjects(1), 1, xlFilterAboveAverage, xlFilterDynamic)
- 'No.15 数値の平均より下
- Call TableFilter(ActiveSheet.ListObjects(1), 1, xlFilterBelowAverage, xlFilterDynamic)
- ' 絞り込み解除
- Call TableFilter(ActiveSheet.ListObjects(1), 1)
- End Sub
図26
74行目「Call TableFilter(ActiveSheet.ListObjects(1), 1, ">5")」は、図10のNo.7に対応します。
第三引数を「">5"」としていますので、5を超えるデータで絞り込んでいます。
76行目「Call TableFilter(ActiveSheet.ListObjects(1), 1, Array("3", "5"), 7)」は、図10のNo.8に対応します。
「3 または 5」で絞り込んでいます。
78行目「Call TableFilter(ActiveSheet.ListObjects(1), 1, ">5", xlAnd, "<8")」は、図10のNo.9に対応します。
「5を超え、8未満の値」に絞り込んでいますので、整数が並んでいるとすれば、6と7が抽出されます。
80行目「Call TableFilter(ActiveSheet.ListObjects(1), 1, "3", xlTop10Items)」は、図10のNo.10に対応します。
大きい方から3個を抽出しますので、1~10が並んでいれば、10・9・8が抽出されます。
82行目「Call TableFilter(ActiveSheet.ListObjects(1), 1, "3", xlBottom10Items)」は、図10のNo.11に対応します。
小さい方から3個を抽出しますので、1~10が並んでいれば、1・2・3が抽出されます。
84行目「Call TableFilter(ActiveSheet.ListObjects(1), 1, "20", xlTop10Percent)」は、図10のNo.12に対応します。
大きい方から20%を抽出しますので、1~10が並んでいれば、10・9が抽出されます。
86行目「Call TableFilter(ActiveSheet.ListObjects(1), 1, "20", xlBottom10Percent)」は、図10のNo.13に対応します。
小さい方から20%を抽出しますので、1~10が並んでいれば、1・2が抽出されます。
88行目「Call TableFilter(ActiveSheet.ListObjects(1), 1, xlFilterAboveAverage, xlFilterDynamic)」は、図10のNo.14に対応します。
列の値の平均値より大きな値を抽出します。1~10が並んでいれば平均値は5.5ですので、6~10が抽出されます。
90行目「Call TableFilter(ActiveSheet.ListObjects(1), 1, xlFilterBelowAverage, xlFilterDynamic)」は、図10のNo.15に対応します。
列の値の平均値より小さな値を抽出します。1~10が並んでいれば平均値は5.5ですので、1~5が抽出されます。
92行目「Call TableFilter(ActiveSheet.ListObjects(1), 1)」は、第三引数以降を省略していますので、第二引数で指定した「1列目」の絞り込み解除をしています。
2-6ー3.対象が日付列の場合
日付の列を対象にして、図23の絞り込み実行プロシージャを呼び出すコードが図27です。図16の各Noごとに並べました。
- '========== ⇩(4) プロシージャへの指示(日付列) ============
- Sub AutoFilter_exec_Date()
- 'No.16 日付の1条件の絞込み
- Call TableFilter(ActiveSheet.ListObjects(1), 3, ">2022/8/20")
- 'No.17 日付の1条件の絞込み
- Call TableFilter(ActiveSheet.ListObjects(1), 3, ">" & Format(CDate("2022/8/20"), ActiveSheet.ListObjects(1)
.ListColumns(3).DataBodyRange(1).NumberFormatLocal))
- 'No.18 日付の1条件の絞込み
- Call TableFilter(ActiveSheet.ListObjects(1), 3, ">" & CLng(CDate("2022/8/20")))
- 'No.19 複数日付をORで絞込み
- Call TableFilter(ActiveSheet.ListObjects(1), 3, Array("2022/8/20", "2022/8/22"), xlFilterValues)
- 'No.20 複数日付をORで絞込み
- Call TableFilter(ActiveSheet.ListObjects(1), 3, , xlFilterValues, Array(2, "2022/8/20", 2, "2022/8/22"))
- 'No.21 日付の2条件の絞込み
- Call TableFilter(ActiveSheet.ListObjects(1), 3, ">2022/8/20", xlAnd, "<2022/8/22")
- 'No.22 日付の2条件の絞込み
- Call TableFilter(ActiveSheet.ListObjects(1), 3, ">" & Format(CDate("2022/8/20"), ActiveSheet.ListObjects(1)
.ListColumns(3).DataBodyRange(1).NumberFormatLocal), xlAnd, "<" & Format(CDate("2022/8/22"), ActiveSheet.ListObjects(1).ListColumns(3).DataBodyRange(1).NumberFormatLocal))
- 'No.23 日付の2条件の絞込み
- Call TableFilter(ActiveSheet.ListObjects(1), 3, ">" & CLng(CDate("2022/8/20")), xlAnd, "<" & CLng(CDate("2022/8/22")))
- 'No.24 既定の日付(今日を絞り込み)
- Call TableFilter(ActiveSheet.ListObjects(1), 3, xlFilterToday, xlFilterDynamic)
- ' 絞り込み解除
- Call TableFilter(ActiveSheet.ListObjects(1), 3)
- End Sub
図27
104行目「Call TableFilter(ActiveSheet.ListObjects(1), 3, ">2022/8/20")」は、図16のNo.16に対応します。
2022/8/20以降のデータを抽出します。104行目の場合は比較演算子がイコールでは無いため、シート側のセル書式とマクロ側の書式が異なっていても正常に抽出されますが、もしイコールを使う場合はシート側のセル書式と合っていないと抽出されません。
106行目「Call TableFilter(ActiveSheet.ListObjects(1), 3, ">" & Format(CDate("2022/8/20"), ActiveSheet.ListObjects(1).ListColumns(3).DataBodyRange(1).NumberFormatLocal))」は、図16のNo.17に対応します。
104行目と同じく2022/8/20以降のデータを抽出します。シート側のセル書式に合わせて日付書式を修正してから、第三引数として実行プロシージャTableFilter側に渡しています。
108行目「Call TableFilter(ActiveSheet.ListObjects(1), 3, ">" & CLng(CDate("2022/8/20")))」は、図16のNo.18に対応します。
104・106行目と同じく2022/8/20以降のデータを抽出します。絞り込む日付をLong型に変更してから、第三引数として実行プロシージャTableFilter側に渡しています。
110行目「Call TableFilter(ActiveSheet.ListObjects(1), 3, Array("2022/8/20", "2022/8/22"), xlFilterValues)」は、図16のNo.19に対応します。
2022/8/20、2022/8/22の2つの日付を抽出しますが、Array内の日付は「イコール相当」で抽出しますので、シート側の書式と合っていることが必要です。
112行目「Call TableFilter(ActiveSheet.ListObjects(1), 3, , xlFilterValues, Array(2, "2022/8/20", 2, "2022/8/22"))」は、図16のNo.20に対応します。
配列内のレベルに「2(=日にち)」を指定していますので、110行目と同じく、2022/8/20、2022/8/22の2つの日付を抽出します。Criteria2にレベル付で日付を配列指定する場合は、書式を合わせる必要なく目的の日付を抽出してくれます。
なお、第三引数(Criteria1)には何も指定しないため「,(カンマ)」で間を開けています。
114行目「Call TableFilter(ActiveSheet.ListObjects(1), 3, ">2022/8/20", xlAnd, "<2022/8/22")」は、図16のNo.21に対応します。
2022/8/20以降で且つ2022/8/22以前の日付を抽出します。日付が連続していれば、2022/8/21が抽出されることになります。114行目では比較演算子としてイコール以外を使用しているので正しく抽出されますが、イコールを使う場合はシート側のセル書式と合わせないと抽出されません。
116行目「Call TableFilter(ActiveSheet.ListObjects(1), 3, ">" & Format(CDate("2022/8/20"), ActiveSheet.ListObjects(1).ListColumns(3).DataBodyRange(1).NumberFormatLocal), xlAnd, "<" & Format(CDate("2022/8/22"), ActiveSheet.ListObjects(1).ListColumns(3).DataBodyRange(1).NumberFormatLocal))」は、図16のNo.22に対応します。
114行目と同じく2022/8/20以降で且つ2022/8/22以前の日付を抽出します。TableFilterプロシージャに渡す前に、日付文字列の書式をシート側書式に修正をしています。TableFilterを呼び出す前に文字列を揃える処理をしておけば、もう少しコードを短く出来ると思います。
118行目「Call TableFilter(ActiveSheet.ListObjects(1), 3, ">" & CLng(CDate("2022/8/20")), xlAnd, "<" & CLng(CDate("2022/8/22")))」は、図16のNo.23に対応します。
114・116行目と同じく2022/8/20以降で且つ2022/8/22以前の日付を抽出します。TableFilterプロシージャに渡す前に、日付をLong型に変更しています。
120行目「Call TableFilter(ActiveSheet.ListObjects(1), 3, xlFilterToday, xlFilterDynamic)」は、図16のNo.24に対応します。
今日(定数xlFilterToday)の日付を抽出しています。図21の定数が使える範囲ならば、積極的に使った方が確実と思います。
122行目「Call TableFilter(ActiveSheet.ListObjects(1), 3)」は、第三引数以降を省略していますので、第二引数で指定した「3列目」の絞り込み解除をしています。
アプリ実例
「DVD等の内容・保管場所等管理システム」
「先行予約可能な備品予約・貸出システム」
「ToDoリストで個人タスク管理」
「会社番号検索システム」
- '========== ⇩(3) プロシージャへの指示(数値列) ============
- Sub AutoFilter_exec_Numeric()
- 'No.7 数値の1条件の絞込み
- Call TableFilter(ActiveSheet.ListObjects(1), 1, ">5")
- 'No.8 数値の複数値をORで絞込み
- Call TableFilter(ActiveSheet.ListObjects(1), 1, Array("3", "5"), 7)
- 'No.9 数値の2条件の絞り込み
- Call TableFilter(ActiveSheet.ListObjects(1), 1, ">5", xlAnd, "<8")
- 'No.10 数値の上位Top10(項目)
- Call TableFilter(ActiveSheet.ListObjects(1), 1, "3", xlTop10Items)
- 'No.11 数値の下位Top10(項目)
- Call TableFilter(ActiveSheet.ListObjects(1), 1, "3", xlBottom10Items)
- 'No.12 数値の上位Top10(%)
- Call TableFilter(ActiveSheet.ListObjects(1), 1, "20", xlTop10Percent)
- 'No.13 数値の下位Top10(%)
- Call TableFilter(ActiveSheet.ListObjects(1), 1, "20", xlBottom10Percent)
- 'No.14 数値の平均より上
- Call TableFilter(ActiveSheet.ListObjects(1), 1, xlFilterAboveAverage, xlFilterDynamic)
- 'No.15 数値の平均より下
- Call TableFilter(ActiveSheet.ListObjects(1), 1, xlFilterBelowAverage, xlFilterDynamic)
- ' 絞り込み解除
- Call TableFilter(ActiveSheet.ListObjects(1), 1)
- End Sub
74行目「Call TableFilter(ActiveSheet.ListObjects(1), 1, ">5")」は、図10のNo.7に対応します。
第三引数を「">5"」としていますので、5を超えるデータで絞り込んでいます。
76行目「Call TableFilter(ActiveSheet.ListObjects(1), 1, Array("3", "5"), 7)」は、図10のNo.8に対応します。
「3 または 5」で絞り込んでいます。
78行目「Call TableFilter(ActiveSheet.ListObjects(1), 1, ">5", xlAnd, "<8")」は、図10のNo.9に対応します。
「5を超え、8未満の値」に絞り込んでいますので、整数が並んでいるとすれば、6と7が抽出されます。
80行目「Call TableFilter(ActiveSheet.ListObjects(1), 1, "3", xlTop10Items)」は、図10のNo.10に対応します。
大きい方から3個を抽出しますので、1~10が並んでいれば、10・9・8が抽出されます。
82行目「Call TableFilter(ActiveSheet.ListObjects(1), 1, "3", xlBottom10Items)」は、図10のNo.11に対応します。
小さい方から3個を抽出しますので、1~10が並んでいれば、1・2・3が抽出されます。
84行目「Call TableFilter(ActiveSheet.ListObjects(1), 1, "20", xlTop10Percent)」は、図10のNo.12に対応します。
大きい方から20%を抽出しますので、1~10が並んでいれば、10・9が抽出されます。
86行目「Call TableFilter(ActiveSheet.ListObjects(1), 1, "20", xlBottom10Percent)」は、図10のNo.13に対応します。
小さい方から20%を抽出しますので、1~10が並んでいれば、1・2が抽出されます。
88行目「Call TableFilter(ActiveSheet.ListObjects(1), 1, xlFilterAboveAverage, xlFilterDynamic)」は、図10のNo.14に対応します。
列の値の平均値より大きな値を抽出します。1~10が並んでいれば平均値は5.5ですので、6~10が抽出されます。
90行目「Call TableFilter(ActiveSheet.ListObjects(1), 1, xlFilterBelowAverage, xlFilterDynamic)」は、図10のNo.15に対応します。
列の値の平均値より小さな値を抽出します。1~10が並んでいれば平均値は5.5ですので、1~5が抽出されます。
92行目「Call TableFilter(ActiveSheet.ListObjects(1), 1)」は、第三引数以降を省略していますので、第二引数で指定した「1列目」の絞り込み解除をしています。
2-6ー3.対象が日付列の場合
日付の列を対象にして、図23の絞り込み実行プロシージャを呼び出すコードが図27です。図16の各Noごとに並べました。
- '========== ⇩(4) プロシージャへの指示(日付列) ============
- Sub AutoFilter_exec_Date()
- 'No.16 日付の1条件の絞込み
- Call TableFilter(ActiveSheet.ListObjects(1), 3, ">2022/8/20")
- 'No.17 日付の1条件の絞込み
- Call TableFilter(ActiveSheet.ListObjects(1), 3, ">" & Format(CDate("2022/8/20"), ActiveSheet.ListObjects(1)
.ListColumns(3).DataBodyRange(1).NumberFormatLocal))
- 'No.18 日付の1条件の絞込み
- Call TableFilter(ActiveSheet.ListObjects(1), 3, ">" & CLng(CDate("2022/8/20")))
- 'No.19 複数日付をORで絞込み
- Call TableFilter(ActiveSheet.ListObjects(1), 3, Array("2022/8/20", "2022/8/22"), xlFilterValues)
- 'No.20 複数日付をORで絞込み
- Call TableFilter(ActiveSheet.ListObjects(1), 3, , xlFilterValues, Array(2, "2022/8/20", 2, "2022/8/22"))
- 'No.21 日付の2条件の絞込み
- Call TableFilter(ActiveSheet.ListObjects(1), 3, ">2022/8/20", xlAnd, "<2022/8/22")
- 'No.22 日付の2条件の絞込み
- Call TableFilter(ActiveSheet.ListObjects(1), 3, ">" & Format(CDate("2022/8/20"), ActiveSheet.ListObjects(1)
.ListColumns(3).DataBodyRange(1).NumberFormatLocal), xlAnd, "<" & Format(CDate("2022/8/22"), ActiveSheet.ListObjects(1).ListColumns(3).DataBodyRange(1).NumberFormatLocal))
- 'No.23 日付の2条件の絞込み
- Call TableFilter(ActiveSheet.ListObjects(1), 3, ">" & CLng(CDate("2022/8/20")), xlAnd, "<" & CLng(CDate("2022/8/22")))
- 'No.24 既定の日付(今日を絞り込み)
- Call TableFilter(ActiveSheet.ListObjects(1), 3, xlFilterToday, xlFilterDynamic)
- ' 絞り込み解除
- Call TableFilter(ActiveSheet.ListObjects(1), 3)
- End Sub
図27
104行目「Call TableFilter(ActiveSheet.ListObjects(1), 3, ">2022/8/20")」は、図16のNo.16に対応します。
2022/8/20以降のデータを抽出します。104行目の場合は比較演算子がイコールでは無いため、シート側のセル書式とマクロ側の書式が異なっていても正常に抽出されますが、もしイコールを使う場合はシート側のセル書式と合っていないと抽出されません。
106行目「Call TableFilter(ActiveSheet.ListObjects(1), 3, ">" & Format(CDate("2022/8/20"), ActiveSheet.ListObjects(1).ListColumns(3).DataBodyRange(1).NumberFormatLocal))」は、図16のNo.17に対応します。
104行目と同じく2022/8/20以降のデータを抽出します。シート側のセル書式に合わせて日付書式を修正してから、第三引数として実行プロシージャTableFilter側に渡しています。
108行目「Call TableFilter(ActiveSheet.ListObjects(1), 3, ">" & CLng(CDate("2022/8/20")))」は、図16のNo.18に対応します。
104・106行目と同じく2022/8/20以降のデータを抽出します。絞り込む日付をLong型に変更してから、第三引数として実行プロシージャTableFilter側に渡しています。
110行目「Call TableFilter(ActiveSheet.ListObjects(1), 3, Array("2022/8/20", "2022/8/22"), xlFilterValues)」は、図16のNo.19に対応します。
2022/8/20、2022/8/22の2つの日付を抽出しますが、Array内の日付は「イコール相当」で抽出しますので、シート側の書式と合っていることが必要です。
112行目「Call TableFilter(ActiveSheet.ListObjects(1), 3, , xlFilterValues, Array(2, "2022/8/20", 2, "2022/8/22"))」は、図16のNo.20に対応します。
配列内のレベルに「2(=日にち)」を指定していますので、110行目と同じく、2022/8/20、2022/8/22の2つの日付を抽出します。Criteria2にレベル付で日付を配列指定する場合は、書式を合わせる必要なく目的の日付を抽出してくれます。
なお、第三引数(Criteria1)には何も指定しないため「,(カンマ)」で間を開けています。
114行目「Call TableFilter(ActiveSheet.ListObjects(1), 3, ">2022/8/20", xlAnd, "<2022/8/22")」は、図16のNo.21に対応します。
2022/8/20以降で且つ2022/8/22以前の日付を抽出します。日付が連続していれば、2022/8/21が抽出されることになります。114行目では比較演算子としてイコール以外を使用しているので正しく抽出されますが、イコールを使う場合はシート側のセル書式と合わせないと抽出されません。
116行目「Call TableFilter(ActiveSheet.ListObjects(1), 3, ">" & Format(CDate("2022/8/20"), ActiveSheet.ListObjects(1).ListColumns(3).DataBodyRange(1).NumberFormatLocal), xlAnd, "<" & Format(CDate("2022/8/22"), ActiveSheet.ListObjects(1).ListColumns(3).DataBodyRange(1).NumberFormatLocal))」は、図16のNo.22に対応します。
114行目と同じく2022/8/20以降で且つ2022/8/22以前の日付を抽出します。TableFilterプロシージャに渡す前に、日付文字列の書式をシート側書式に修正をしています。TableFilterを呼び出す前に文字列を揃える処理をしておけば、もう少しコードを短く出来ると思います。
118行目「Call TableFilter(ActiveSheet.ListObjects(1), 3, ">" & CLng(CDate("2022/8/20")), xlAnd, "<" & CLng(CDate("2022/8/22")))」は、図16のNo.23に対応します。
114・116行目と同じく2022/8/20以降で且つ2022/8/22以前の日付を抽出します。TableFilterプロシージャに渡す前に、日付をLong型に変更しています。
120行目「Call TableFilter(ActiveSheet.ListObjects(1), 3, xlFilterToday, xlFilterDynamic)」は、図16のNo.24に対応します。
今日(定数xlFilterToday)の日付を抽出しています。図21の定数が使える範囲ならば、積極的に使った方が確実と思います。
122行目「Call TableFilter(ActiveSheet.ListObjects(1), 3)」は、第三引数以降を省略していますので、第二引数で指定した「3列目」の絞り込み解除をしています。
アプリ実例
「DVD等の内容・保管場所等管理システム」
「先行予約可能な備品予約・貸出システム」
「ToDoリストで個人タスク管理」
「会社番号検索システム」
104行目と同じく2022/8/20以降のデータを抽出します。シート側のセル書式に合わせて日付書式を修正してから、第三引数として実行プロシージャTableFilter側に渡しています。
108行目「Call TableFilter(ActiveSheet.ListObjects(1), 3, ">" & CLng(CDate("2022/8/20")))」は、図16のNo.18に対応します。
104・106行目と同じく2022/8/20以降のデータを抽出します。絞り込む日付をLong型に変更してから、第三引数として実行プロシージャTableFilter側に渡しています。
110行目「Call TableFilter(ActiveSheet.ListObjects(1), 3, Array("2022/8/20", "2022/8/22"), xlFilterValues)」は、図16のNo.19に対応します。
2022/8/20、2022/8/22の2つの日付を抽出しますが、Array内の日付は「イコール相当」で抽出しますので、シート側の書式と合っていることが必要です。
112行目「Call TableFilter(ActiveSheet.ListObjects(1), 3, , xlFilterValues, Array(2, "2022/8/20", 2, "2022/8/22"))」は、図16のNo.20に対応します。
配列内のレベルに「2(=日にち)」を指定していますので、110行目と同じく、2022/8/20、2022/8/22の2つの日付を抽出します。Criteria2にレベル付で日付を配列指定する場合は、書式を合わせる必要なく目的の日付を抽出してくれます。
なお、第三引数(Criteria1)には何も指定しないため「,(カンマ)」で間を開けています。
114行目「Call TableFilter(ActiveSheet.ListObjects(1), 3, ">2022/8/20", xlAnd, "<2022/8/22")」は、図16のNo.21に対応します。
2022/8/20以降で且つ2022/8/22以前の日付を抽出します。日付が連続していれば、2022/8/21が抽出されることになります。114行目では比較演算子としてイコール以外を使用しているので正しく抽出されますが、イコールを使う場合はシート側のセル書式と合わせないと抽出されません。
116行目「Call TableFilter(ActiveSheet.ListObjects(1), 3, ">" & Format(CDate("2022/8/20"), ActiveSheet
114行目と同じく2022/8/20以降で且つ2022/8/22以前の日付を抽出します。TableFilterプロシージャに渡す前に、日付文字列の書式をシート側書式に修正をしています。TableFilterを呼び出す前に文字列を揃える処理をしておけば、もう少しコードを短く出来ると思います。
118行目「Call TableFilter(ActiveSheet.ListObjects(1), 3, ">" & CLng(CDate("2022/8/20")), xlAnd, "<" & CLng(CDate("2022/8/22")))」は、図16のNo.23に対応します。
114・116行目と同じく2022/8/20以降で且つ2022/8/22以前の日付を抽出します。TableFilterプロシージャに渡す前に、日付をLong型に変更しています。
120行目「Call TableFilter(ActiveSheet.ListObjects(1), 3, xlFilterToday, xlFilterDynamic)」は、図16のNo.24に対応します。
今日(定数xlFilterToday)の日付を抽出しています。図21の定数が使える範囲ならば、積極的に使った方が確実と思います。
122行目「Call TableFilter(ActiveSheet.ListObjects(1), 3)」は、第三引数以降を省略していますので、第二引数で指定した「3列目」の絞り込み解除をしています。
アプリ実例
「DVD等の内容・保管場所等管理システム」「先行予約可能な備品予約・貸出システム」
「ToDoリストで個人タスク管理」
「会社番号検索システム」