オートフィルタをマクロで

データ絞込みの機能として便利なオートフィルタのマクロ化を図る一例。 マクロの記録から、セルに入力した値でのオートフィルタ制御を試みる。

オートフィルタの操作の記録でマクロ作成

次のようなリストを想定する。
ABCD
1
2日付品名数量価格
32005/05/25商品144100
42005/05/26商品225120
52005/05/27商品332130
62005/05/28商品165100
72005/05/25商品265120
82005/05/26商品140100
92005/05/27商品241120
102005/05/28商品38130

マクロの記録

メニューのツール(T)マクロ(M)新しいマクロの記録(R)でマクロの記録を開始。 マクロのコードの「叩き台」を作る過程なので、マクロ名などは適当でよい。 次の操作を記録する。
  1. リスト内の見出し部分、左端セルを選択
  2. ShiftCtrlを押しながら(見出し部分範囲選択)
  3. ShiftCtrlを押しながら(見出しを含むデータ範囲選択)
  4. データ(D)フィルタ(F)オートフィルタ(F)
  5. フィルタをかける列のプルダウンリストから抽出する値を選択。(適当でよい)
  6. 記録終了。
Alt+F11VBEを起動させると、おおむね次のようなマクロが出来ているのがわかる。
Sub Macro1()
' Macro1 Macro
' マクロ記録日 : 2005/5/24  ユーザー名 : miyaho_rinn
    Range("A2").Select
    Range(Selection, Selection.End(xlToRight).End(xlDown)).Select
    Selection.AutoFilter
    Selection.AutoFilter Field:=1, Criteria1:="2005/5/26"
End Sub

記録したマクロを加工する

これを少し整理すると以下。
Sub Macro2()
    With Range(Range("A2"), Range("A2").End(xlToRight).End(xlDown))
        .AutoFilter Field:=1, Criteria1:="2005/05/26"
    End With
End Sub
このMacro2を実行すると、当然のことながら毎回必ずA列が"2005/05/26"であるデータが抽出されるが、 そのような鸚鵡返しの動作ではあまり役に立ちそうにない。 そこで、フィルタ条件をどこかのセルに入力したものを利用するように変更してみる。
Sub Macro3()
    If ActiveSheet.FilterMode Then Cells.AutoFilter
    With Range(Range("A2"), Range("A2").End(xlToRight).End(xlDown))
        .AutoFilter Field:=1, Criteria1:=Range("A1").Text
    End With
End Sub
なお、書き加えた次のステートメントは一旦フィルタを解除するものである。
    If ActiveSheet.FilterMode Then Cells.AutoFilter
これはリストの範囲をRange(Range("A2"), Range("A2").End(xlToRight).End(xlDown))で取得しているため、 前回のフィルタ状況が残っていると対象範囲が変化してしまうためである。もちろん、 Endプロパティに依らず、データ数を確認するなどの方法でリスト範囲を取得する方法をとれば、 このステートメントは不要。が、今回はこのままにしておく。 これで、セルA1に入力した内容でリストにフィルタリングするマクロが出来上がった。

マクロ実行の自動化

イベントマクロ

標準モジュールへ作成したものは、いちいち実行しなければならないので、面倒くさい。 では、もっと自動化できないか、ということで、「イベントマクロ」というものを利用してみる。 「イベント」とは「セルの入力内容が変更された」「選択セルを変更」などのソフトウェア上の変化。 「セルの入力内容が変更された」というイベントを利用してみる。 シートの見出しを右クリックして表示されるショートカットメニューから、 コードの表示(V)を選択してVBEを起動。



上記VBE画面で左側、オブジェクトボックス((General)と表示されている)から、Worksheetを選択、 また、その右側のプロシージャボックスからChangeを選択するとその過程で次のようなコードが 自動的に作成される。
Private Sub Worksheet_Change(ByVal Target As Range)

End Sub

Private Sub Worksheet_SelectionChange(ByVal Target As Range)

End Sub
今回はWorksheet_Changeの方へ記録をもとに作成した前記Macro3のコードの中身を移し替えてみる。
Private Sub Worksheet_Change(ByVal Target As Range)
    If ActiveSheet.FilterMode Then Cells.AutoFilter
    With Range(Range("A2"), Range("A2").End(xlToRight).End(xlDown))
        .AutoFilter Field:=1, Criteria1:=Range("A1").Text
    End With
End Sub
このままではシート内のセルが変更されるたびにオートフィルタを実行してしまうので、多少わずらわしい。 A1セルが変更された時、オートフィルタが実行されれば良いというのがわかっているので、 そのように書き換えてみる。
Private Sub Worksheet_Change(ByVal Target As Range)
    If Target.Address(0, 0) = "A1" Then
    If ActiveSheet.FilterMode Then Cells.AutoFilter
        With Range(Range("A2"), Range("A2").End(xlToRight).End(xlDown))
            .AutoFilter Field:=1, Criteria1:=Range("A1").Text
        End With
    End If
End Sub
この場合、TargetとRange("A1")は同一なので、次のように書き換えることも出来る。
Private Sub Worksheet_Change(ByVal Target As Range)
    If Target.Address(0, 0) = "A1" Then
    If ActiveSheet.FilterMode Then Cells.AutoFilter
        With Range(Range("A2"), Range("A2").End(xlToRight).End(xlDown))
            .AutoFilter Field:=1, Criteria1:=Target.Text
        End With
    End If
End Sub
これで、「セルA1を変更したら、リストのA列でA1の値をもとにフィルタリングする」マクロが出来た。

【応用】リストの全てのフィールドでオートフィルタ自動実行

少し欲を出して、A列だけでなくて、リストの全てのフィールドにも同様の自動フィルタ機能を 持たせてみる。 直前の例ではTargetとなるセルをA1だけに限定したが、フィルタの条件となるセルを 「一行目で、リストの見出しに対応する(同じ列の)セル」に拡張してみる。
Private Sub Worksheet_Change(ByVal Target As Range)
    If Target.Count > 1 Then Exit Sub
    If Target.Row <> 1 Then Exit Sub
    If Target.Column > Range("A2").End(xlToRight).Column Then Exit Sub
    If ActiveSheet.FilterMode Then Cells.AutoFilter
    With Range(Range("A2"), Range("A2").End(xlToRight).End(xlDown))
        .AutoFilter Field:=Target.Column, Criteria1:=Target.Text
    End With
    If WorksheetFunction.CountA(Range("1:1")) = 0 Then
        Cells.AutoFilter
    End If
End Sub
Target.Countは変更したセルの数(セルの数が複数になると都合が悪い)、 Target.Rowは変更したセルの行位置、Target.Columnは変更した列位置を示す。 また、Field:=1 のままでは「リストの一列目」だけをフィルタの対象とするので、  Field:=Target.Column とすることで、「変更したセルと同じ列」という可変性を持たせる。 最後の3行はフィルタ条件が全てクリアされた時にリストを全表示するためのものである。 なお、条件を指定する場合は比較演算子(<,>,=)、およびワイルドカード(*,?)を使用することが出来る。

紹介したオートフィルタマクロの注意点

より確実にフィルタリングするために、下記の設定をお勧めする。

日付

日付を使用したフィールドがある場合はなるべくウィンドウズの「日付と時刻の設定」で設定されている 形式と同じ形式の書式設定としておくことをお勧めする。

表示形式

抽出条件を入力するセルと、リストのフィールドの書式設定の表示形式は同じ形式としておくようにする。 TextプロパティをCriteria1に指定しているため、「1000」と表示されているものと、「1,000」と表示されているものは 「違うもの」として認識される。

一つのフィールドで条件一つ

現状、一つのフィールドで条件一つしか与えることは出来ない。

 ▲PAGETOP


資料室目次へ  

SEO [PR] 爆速!無料ブログ 無料ホームページ開設 無料ライブ放送