VBA Filter 関数:配列を絞り込む

はじめに

Excel VBA マクロの Filter 関数から配列を絞り込む方法を紹介します。

Filter 関数は、文字列の配列から指定した文字列を含む配列を返します。

部分一致で絞り込むので あいう, あいえ, かきお に対して あい でフィルタすると、あいう, あいえ の配列を返します。

完全一致で要素を絞り込むにはループします。

完全一致で存在チェックをしたり、二次元配列の存在チェックをするにはループします。

文字列の配列を絞り込み (フィルタリング) したいときに使用します。

配列を作成するには「Array 関数」を使用します。
配列について詳しくは「配列」をご覧ください。
  • 目次
    • Filter 関数
    • 解説
    • 使用例

Filter 関数

Filter(文字列型配列, フィルタ文字)
文字列型配列からフィルタ文字と一致する要素の配列を作成します。

Filter(文字列型配列, フィルタ文字, 含む, 比較モード)
フィルタ文字含む含まないか指定できます。比較モードで大文字と小文字を区別するか指定できます。

引数「文字列型」文字列型 (String) を指定します。
引数「フィルタ文字」フィルタリングする文字列を指定します。
引数「含む」省略できます。
True または省略: 引数「フィルタ文字」を含む配列を返します。
False: 引数「フィルタ文字」を含まない配列を返します。
引数「比較モード」省略できます。フィルタリングに大文字と小文字を区別するか指定します。
戻り値の型文字列型 (String) の配列

引数「比較モード」

単位 説明
vbBinaryCompare (既定)「大文字と小文字」、「半角と全角」、「ひらがなとカタカナ」を区別する。
vbTextCompare区別しない。

解説

戻り値を受け取る変数は、String 型の動的配列か Variant 型である必要があります。Variant 型の動的配列だと「エラー 13 型が一致しません。」が発生します。

作成される配列は動的配列で、最小インデックスは 0 からスタートします。

引数「文字列型配列」の要素の中に引数「フィルタ文字」と一致する部分がある要素で作成された配列を返します。部分一致なので あいうえお に対して あい でフィルタしても、その要素を返します。

引数「フィルタ文字」が空文字 "" なら、すべての要素と一致します。

引数「文字列型配列」に引数「フィルタ文字」が見つからなかったときは、(0 To -1) の要素数 0 の配列を返します。これが String 型の要素数 0 の配列を作成する唯一の方法です。

引数「文字列型配列」には String 型または Variant 型の配列のみ指定できます。それ以外の型の配列を指定すると「エラー 13 型が一致しません。」が発生します。Variant 型の配列に文字列以外の値が入っているときは、文字列に変換してから処理をします。

引数「文字列型配列」には一次元配列のみ指定できます。二次元配列を指定すると「エラー 13 型が一致しません。」が発生します。

完全一致

完全一致する要素だけを返すには、Filter 関数を使わないでループしてできます。

存在チェック

部分一致で存在チェックするには、結果の配列の最大インデックスが 0 以上だと存在します。-1 だと存在しません。

完全一致で存在チェックするには、Filter 関数を使わないでループしてできます。

二次元配列を完全一致で存在チェックするには、Filter 関数を使わないでループしてできます

使用例

配列を絞り込む。

Dim s(3) As String ' 元の配列
s(0) = "ABC DEF"
s(1) = "abc 123"
s(2) = "123 ABC"
s(3) = "あいう 123"

Dim f() As String
f = Filter(s, "ABC")
Debug.Print(f(0)) ' "ABC DEF"
Debug.Print(f(1)) ' "123 ABC"

f = Filter(s, "ABC", False) ' フィルタ文字を含まない
Debug.Print(f(0)) ' "abc 123"
Debug.Print(f(1)) ' "あいう 123"

f = Filter(s, "ABC", True, vbTextCompare) ' 区別しない
Debug.Print(f(0)) ' "ABC DEF"
Debug.Print(f(1)) ' "abc 123"
Debug.Print(f(2)) ' "123 ABC"

f = Filter(s, "Tips") ' 1 つも一致しない
Debug.Print(LBound(f)) ' 0、(0 ~ -1) の要素数 0 の配列
Debug.Print(UBound(f)) ' -1

Dim v As Variant
v = Filter(s, "ABC") ' Variant 型にも代入できる
Debug.Print(v(0)) ' "ABC DEF"
Debug.Print(v(1)) ' "123 ABC"

Dim va() As Variant
va = Filter(s, "ABC") ' エラー、Variant 型の動的配列には代入できない

完全一致

完全一致する要素だけを返すには、Filter 関数を使わないでループしてできます。関数を作成すると便利です。ついでに文字列以外にも対応するため Variant 型で比較しています。

Sub 実行()
    Dim s(4) As String ' 元の配列
    s(0) = "ABC DEF"
    s(1) = "abc 123"
    s(2) = "ABC"
    s(3) = "123 ABC"
    s(4) = "ABC"
    
    Dim v As Variant
    Dim a As Variant
    
    ' 部分一致
    a = Filter(s, "ABC")
    For Each v In a
        Debug.Print(v)
        ' ABC DEF
        ' ABC
        ' 123 ABC
        ' ABC
    Next

    ' 完全一致
    a = FilterMatch(s, "ABC")
    For Each v In a
        Debug.Print(v)
        ' ABC
        ' ABC
    Next
End Sub

' Filter 関数を完全一致で絞り込む
Function FilterMatch(ByVal list As Variant, ByVal value As Variant) As Variant
    
    Dim s As Variant
    s = Array() ' 見つからないとき用に (0 ~ -1) の要素数 0 の配列
    
    Dim count As Integer
    count = -1
    
    Dim i As Integer
    For i = LBound(list) To UBound(list)
        If list(i) = value Then ' 完全一致で比較
            count = count + 1
            ReDim Preserve s(count)
            s(count) = list(i)  ' 一致した要素を追加
        End If
    Next
    
    FilterMatch = s
End Function

存在チェック

部分一致で存在チェックするには「UBound 関数」を使用して、結果の配列の最大インデックスが 0 以上だと存在します。-1 だと存在しません。

Dim s(3) As String
s(0) = "ABC DEF"
s(1) = "abc 123"
s(2) = "123 ABC"
s(3) = "あいう 123"

Dim f() As String
f = Filter(s, "ABC")
If UBound(f) >= 0 Then ' 部分一致で存在チェック
    Debug.Print ("存在している") ' 存在している
Else
    Debug.Print ("見つからない")
End If

f = Filter(s, "Tips")
If UBound(f) >= 0 Then ' 部分一致で存在チェック
    Debug.Print ("存在している")
Else
    Debug.Print ("見つからない") ' 見つからない
End If

完全一致で存在チェックするには、Filter 関数を使わないでループしてできます。関数を作成すると便利です。ついでに文字列以外にも対応するため Variant 型で比較しています。

Sub 実行()
    Dim s(3) As String ' 元の配列
    s(0) = "ABC DEF"
    s(1) = "abc 123"
    s(2) = "123 ABC"
    s(3) = "ABC"
    
    ' 完全一致
    Dim b As Boolean
    b = ExistsArray(s, "ABC")
    Debug.Print(b) ' True
    
    b = ExistsArray(s, "abc")
    Debug.Print(b) ' False
End Sub

' 配列に完全一致する要素が存在するかどうか
Function ExistsArray(ByVal list As Variant, ByVal item As Variant) As Boolean
        
    Dim i As Integer
    For i = LBound(list) To UBound(list)
        If list(i) = item Then ' 完全一致で比較
            ExistsArray = True
            Exit Function
        End If
    Next
    
    ExistsArray = False
End Function

二次元配列を完全一致で存在チェックするには、Filter 関数を使わないでループしてできます。関数を作成すると便利です。ついでに文字列以外にも対応するため Variant 型で比較しています。

Sub 実行()
    Dim s(1, 2) As String ' 元の配列
    s(0, 0) = "ABC DEF"
    s(0, 1) = "abc 123"
    s(0, 2) = "ABC"
    s(1, 0) = "ABC DEF"
    s(1, 1) = "abc 123"
    s(1, 2) = "ABC"
    
    ' 完全一致
    Dim b As Boolean
    b = ExistsArray2(s, "ABC")
    Debug.Print(b) ' True
    
    b = ExistsArray2(s, "abc")
    Debug.Print(b) ' False
End Sub

' 二次元配列に完全一致する要素が存在するかどうか
Function ExistsArray2(ByVal list As Variant, ByVal item As Variant) As Boolean
        
    Dim i As Integer
    Dim j As Integer
    For i = LBound(list, 1) To UBound(list, 1)
        For j = LBound(list, 2) To UBound(list, 2)
            If list(i, j) = item Then ' 完全一致で比較
                ExistsArray2 = True
                Exit Function
            End If
        Next
    Next
    
    ExistsArray2 = False
End Function