和風スパゲティのレシピ

日本語でコーディングするExcelVBA

オートフィルターで数値の条件・区間を抽出する

「10以上」や「15以上20以下」など、オートフィルターによる数値の条件・区間での絞り込みを、コピペして使えるユーティリティ関数にしたものを紹介します。

お忙しい方は、ソースコードをコピーして、使い方のように呼び出すだけでOKです。
コードをしっかり読みたい方は、解説をどうぞ。

1つの条件(10以上 や 0以外 など)で抽出する

まずは「10以上」「0以外」など、1つの条件で絞り込む方法です。

実は結構簡単で、↓のようにAutoFilterの引数Criteria1に「>=10」や「<>0」などの条件式を渡すだけでよいです。

Range("A1:C10").AutoFilter field:=1, Criteria1:=">=10"


コードの書き方は、完全一致でフィルターするときとまったく変わらないので、
ユーティリティ関数も「オートフィルターで抽出する」で紹介したものの使いまわしでOK。

Sub みかんを2個以上買った人に絞る()

    Call フィルターを設置する(Range("B2:E2"))
    Call フィルターで抽出する("みかん", くだもの売上表の列.品物, ActiveSheet)
    Call フィルターで抽出する(">=2", くだもの売上表の列.個数, ActiveSheet)

End Sub

このように、同じ関数を引数だけ変えるだけで、完全一致・条件抽出のどちらにも使えます。

この関数は「オートフィルターで抽出する」で解説していますが、コピペ用にコードだけ再掲します。

ソースコード

' フィルター設置
Sub フィルターを設置する(設置エリア As Range)

    ' 既に設置されているフィルターを解除してから設置
    設置エリア.Parent.AutoFilterMode = False
    設置エリア.AutoFilter
    
End Sub

' フィルター抽出
Sub フィルターで抽出する(ByVal 抽出キー As Variant, 抽出列 As Long, 対象シート As Worksheet)
    With 対象シート.AutoFilter.Range
    
        ' 数値が書式の影響を受けるのを回避
        If IsNumeric(抽出キー) Then
            .AutoFilter field:=抽出列 - .Column + 1, Criteria1:=">=" & 抽出キー _
                                         , Operator:=xlAnd, Criteria2:="<=" & 抽出キー
        ' メインの処理
        Else
            .AutoFilter field:=抽出列 - .Column + 1, Criteria1:=抽出キー
        End If
    
    End With
End Sub
  • まずは設置する関数を呼び、そのあとで抽出する関数を呼んでいく。
  • すでにフィルターが設置してある場合は、設置の関数は使わなくてよい。
  • 抽出する列の指定に、列番号をそのまま渡せる。
    ※ 元の仕様である「フィルター範囲で何列目」から変更している

※ くだもの売上表の列:列番号を定数で定義したものです(B列なら2などの数値です)

2つの条件で挟まれた数値の区間(10以上20以下 など)で抽出する

次に、2つの条件に囲まれた範囲を絞り込む方法です。
こちらもそこまで難しくはなく、Criteria2に↑と同じように条件式を渡し、

Range("A1:C10").AutoFilter field:=1 _
    , Criteria1:=">=10", Operator:=xlAnd, Criteria2:="<=20"

↑のように「Operator:=xlAnd」でつなげばOKです。


さてユーティリティ関数を作りましょう。

Call ふたつの条件でフィルターを抽出する(">=10","<=20", CNoくだもの売上表.個数, ActiveSheet)

↑こんなものでも十分かもしれませんが、せっかくなのでもうちょっと便利にします。

ソースコード

' 数値区間でフィルター
Sub フィルターで数値の区間を抽出する(ByVal 下限値 As Double, ByVal 上限値 As Double _
    , 抽出列 As Long, 指定シート As Worksheet _
    , Optional is下限値を抽出に含む As Boolean = True _
    , Optional is上限値を抽出に含む As Boolean = True)
    
    With 指定シート.AutoFilter.Range
        .AutoFilter field:=抽出列 - .Column + 1 _
                      , Criteria1:=">" & IIf(is下限値を抽出に含む, "=", "") & 下限値 _
                      , Operator:=xlAnd _
                      , Criteria2:="<" & IIf(is上限値を抽出に含む, "=", "") & 上限値
    End With

End Sub

使い方

Call フィルターを設置する(Range("B2:E2"))

' 10 <= x <= 20 で絞り込む
Call フィルターで数値の区間を抽出する(10, 20, CNoくだもの売上表.個数, ActiveSheet)
' 10 < x < 20 で絞り込む
Call フィルターで数値の区間を抽出する(10, 20, CNoくだもの売上表.個数, ActiveSheet, False, False)
  • 引数には、「>」などは付けずに数値をそのまま渡せる。
  • 「=」をつけるかどうかは「is上/下限値を含む」にTrue/Falseで指定する。
  • 省略時はTrueなので、指定しない場合は「=」がついた条件になる。

オートフィルターで抽出する関数と同じく、列の指定に列番号をそのまま使います。
  元の仕様である「フィルター範囲で何列目?」から変更している点に注意してください。
※ くだもの売上表の列:列番号を定数で定義したものです(B列なら2などの数値です)

コードの解説

実際に関数を使うときは、値をそのまま書くのでなく、変数やセルの値を関数へ渡す場合が多いです。
そのときに、「">=" & Cells(R1, C1)」のように、いちいち文字列を結合させて引数に渡すのは地味に面倒なので、それも関数にやってもらいましょう。

こうすると、"<"の方向を考える必要もなくなりますし、間違って逆にしてしまうバグもなくなりますね。

ちなみに、Optional ~~ = True という部分は、「省略可能、省略時はTrue」という意味です。

使い方のように、数字をただ渡すと「>=」「<=」で処理され、
Falseを渡すと「>」「<」で処理されます。

IIf関数について

上限値を含むのTrue/Falseで、「<」と一緒に「=」もつけるかどうかは、Ifによる分岐でなく、IIf関数で書きました。

IIf(is下限値を抽出に含む, "=", "")


初めて見る人もいるかもしれませんが、覚えるのはすごく簡単です。

早い話、これは「シート関数のIF」です。

IIf(条件式, Trueの時, Falseの時)

すごくなじみのある記述ですね。
今回の場合は、下限値を含むなら「=」、そうでないなら「」。そのまんまです。


ひとつの引数だけ違うメソッドの実行などは、Ifによる分岐を使ってしまうと、ほとんど同じコードをもう一回書く羽目になります。

IIfを使えば1行のまま分岐でき、コードがかなり短くなりますので積極的に使っていきましょう。

他のプログラミング言語だと、「三項演算子と呼び、云々~」みたいな説明が必要で知名度が低く、読みづらいから使うな、みたいな批判もあるようですが、
VBAユーザーには「シート関数と同じ書き方のIf」で通じるし、見慣れていて読みやすいのでいいですね。