Excel VBA VLOOKUPの複数条件を高速で処理する方法

高速化

今回はVLOOKUP関数の検索条件を複数指定する方法をご説明します。

作業列が不要な方法と、②作業列を追加してVLOOKUPの数式を使用した方法、さらに③WorksheetFunction.VLookupを使用した方法の3つご説明します。

①と②については高速で処理します。

Excelのみで処理する場合は、作業列を追加して「&」で結合してから、通常のVLOOKUP関数を使用するかと思います。

VBAで処理する場合も考え方自体は同様です。
結合した文字列をKeyとして「Dictionary」を使用する事で、高速に処理する事が出来ます。

Excel2016の場合はVLOOKUP関数が速くなっているので、処理速度は速いと思いますが、Excel2016前のバージョンや、処理が遅いと思う方はこちらの方法を使用してみてください。

VLOOKUPやCOUNTIFの高速化は次の記事をご覧ください。

1.複数条件のVLOOKUPを高速で処理する方法

まず、検索用のデータと、参照先のデータを配列に格納します。

次に参照先の配列から、複数条件の文字列を「&」で結合しDictionaryのKeyに追加します。

Dictionary」の使い方は「Excel VBA Dictionaryの使い方」をご覧ください。

リストを作成したら、検索用の配列をループで検索文字列をKeyとして、DictionaryのItemを抽出します。

サンプルデータとサンプルコードです。

検索用にA列に店舗名、B列に商品名と、参照先用にE列に店舗名、F列に商品名、G列に各商品の価格が、それぞれ10万行あるデータを用意しました。

Option Explicit

    Sub Sample1()

        Dim SearchArray As Variant
        Dim RefArray    As Variant
        Dim Keyval      As String
        Dim ItemVal     As Long
        Dim MaxRow      As Long
        Dim i           As Long
        Dim n           As Long
        Dim myDic       As Object
            
        MaxRow = Cells(Rows.Count, 1).End(xlUp).Row '最終行を取得
        SearchArray= Range(Cells(2, 1), Cells(MaxRow, 3)) '①AとB列と出力用にC列も配列格納
        RefArray = Range(Cells(2, 5), Cells(MaxRow, 7)) '②参照データとしてE~G列を格納
        
        Set myDic = CreateObject("Scripting.Dictionary")
        
        For n = 1 To UBound(RefArray) '参照用の配列を要素数分ループ
                            
            Keyval = RefArray(n, 1) & RefArray(n, 2)  '③条件を結合してKeyを格納
            ItemVal = RefArray(n, 3) '④Itemを格納
            
            '登録されていなければ登録
            '※Dictionaryは重複登録出来ない
            '今回のサンプルデータは初めから重複はありません。
            If Not myDic.Exists(Keyval) Then
            
                myDic.Add Keyval, ItemVal
                
            End If
            
        Next n
        
        For n = 1 To UBound(SearchArray) '検索用配列の要素数分ループ
        
            Keyval = SearchArray(n, 1) & SearchArray(n, 2) '検索値の条件を結合
            
            SearchArray(n, 3) = myDic(Keyval) '検索値のKeyでItemを抽出
        
        Next n
        
        Range(Cells(2, 1), Cells(MaxRow, 3)) = SearchArray'結果出力
        
        Set myDic = Nothing
    
    End Sub

測定結果としては約4秒でした。

さすがに単体の条件の2秒とまではいきませんが、通常のVLOOKUP関数よりは速いと思います。

2.VLOOKUP関数の数式埋め込みで複数条件の処理

直接セルにVLOOKUP関数の数式を埋め込む方法です。

こちらはExcel2016以降であれば、高速で処理されます。

約5秒くらいでした。

それ以前のバージョンだと約10分くらいかかります。

数式を直接入力する形のため、作業列としてD列に一度検索文字列を結合して出力しています

また、注意点として「“=VLOOKUP(“”” & myStr & “””,」部分の「”」ですが、こちらは「”」を文字列として扱うために、「“””」をしています。

Sub Sample2()

        Dim SearchArray As Variant
        Dim RefArray()  As Variant
        Dim MaxRow      As Long
        Dim i           As Long
        Dim myStr       As String
        
        MaxRow = Cells(Rows.Count, 1).End(xlUp).Row '最終行を取得
        SearchArray= Range(Cells(2, 1), Cells(MaxRow, 3)) 'A列と出力用にB列も配列格納
        
        ReDim RefArray(0 To MaxRow - 1, 0 To 0) '結合するためセル範囲を一括で格納できません。
        
        For i = 0 To MaxRow - 1
        
            RefArray(i, 0) = Cells(i + 1, 5) & Cells(i + 1, 6)
        
        Next i
        
        Range(Cells(1, 4), Cells(MaxRow, 4)) = RefArray '作業列に格納
        
        For i = 1 To UBound(SearchArray) 'A列要素数分ループ
        
            myStr = SearchArray(i, 1) & SearchArray(i, 2) '配列の値を格納
        
            SearchArray(i, 3) = "=VLOOKUP(""" & myStr & """,$D$2:$G$100001,4,0)" '「”」を文字列として扱う
        Next i
        
        Range(Cells(2, 1), Cells(MaxRow, 3)) = SearchArray'結果出力
        
    End Sub

3.WorksheetFunction.VLookupで複数条件の処理

Application.WorksheetFunction.VLookup」を使用した方法で、複数条件のVLOOKUPのコードも記載します。

処理速度は約20分でした。

こちらも作業列が必要となるため、D列に検索用の文字列を結合したデータを出力しています。

Sub Sample3()

        Dim SearchArray As Variant
        Dim RefArray()  As Variant
        Dim MaxRow      As Long
        Dim i           As Long
        Dim myStr       As String
        
        MaxRow = Cells(Rows.Count, 1).End(xlUp).Row '最終行を取得
        SearchArray= Range(Cells(2, 1), Cells(MaxRow, 3)) 'A列と出力用にB列も配列格納
        
        ReDim RefArray(0 To MaxRow - 1, 0 To 0) '結合するためセル範囲を一括で格納できません。
        
        For i = 0 To MaxRow - 1
        
            RefArray(i, 0) = Cells(i + 1, 5) & Cells(i + 1, 6)
        
        Next i
        
        Range(Cells(1, 4), Cells(MaxRow, 4)) = RefArray '作業列に格納
        
        For i = 1 To UBound(SearchArray) 'A列要素数分ループ
        
            myStr = SearchArray(i, 1) & SearchArray(i, 2) '配列の値を格納
        
            SearchArray(i, 3) = _
Application.WorksheetFunction.VLookup(myStr, Range(Cells(2, 4), Cells(MaxRow, 7)), 4, 0)
        Next i
        
        Range(Cells(2, 1), Cells(MaxRow, 2)) = SearchArray'結果出力
        
    End Sub

4.サンプルファイルのダウンロード

今回使用したサンプルデータとコード Sample1~3をダウンロードできます。

ご自身の環境に合わせて使用してみてください。

5.まとめ

複数条件の処理は、条件となる文字列を「&」で結合して、Dictionaryで処理すると、大量のデータであっても非常に高速に処理が可能です。

どちらも配列を使ったり、処理方法が特殊なので慣れるまで難しく感じるかもしれませんが、

慣れてしまえば今まで膨大にかかっていた処理も、たいていの事は高速化できます。

タイトルとURLをコピーしました