行列の交差する値をVBAで取得する、の別解②

昨日は料金表の中から、いくつかの条件に合致する料金を抽出する関数を作成してみた。
infoment.hatenablog.com
すると、ことりちゅんさんから、次のようなコメントをいただいた。

DictはStatic変数で良いかな。

・・・すみません、Static変数って、何ですか?
f:id:Infoment:20190312214816p:plain
調べてみると、こちらで紹介されていた。
thom.hateblo.jp
(いつも、ありがとうございます)。

それにしても、何だこれは。何て便利なんだ。今までは、

  1. モジュール変数またはパブリック変数で辞書を宣言しておく。
  2. 辞書の中身が無い時だけ、辞書を作成する。

という手法を採っていた。方式としては変わらないが、Static変数で宣言することにより、作成した辞書の中身は保持されるようだ。

ついでに、料金表の範囲と条件の数も引数にした結果がこちら。

標準モジュール
Option Explicit

' 価格表用の辞書(連想配列)
Function GetPlanDict(target_range As Range, _
                     label_r As Long, _
                     label_c As Long) As Dictionary
    Dim Dict As Dictionary
    Set Dict = New Dictionary
    
    Dim myKey As String
    Dim rSeq As Variant
    Dim cSeq As Variant
    Dim r As Long
    Dim c As Long
    
        ' 各値段に関する条件を、一旦配列に格納する。
        For r = label_c + 1 To target_range.Rows.Count
            For c = label_r + 1 To target_range.Columns.Count
            
                ' 列の条件を配列に格納。
                rSeq = target_range.Cells(r, 1).Resize(, label_c)
                ' 行の条件を配列に格納。
                cSeq = target_range.Cells(1, c).Resize(label_r)
                
                ' 二次元配列を強制的に一次元配列に変換。
                rSeq = WorksheetFunction.Transpose(rSeq)
                rSeq = WorksheetFunction.Transpose(rSeq)
                cSeq = WorksheetFunction.Transpose(cSeq)
                
                ' 配列内の文字を結合し、辞書用のキーとする。
                myKey = Join(rSeq, vbNullString) & Join(cSeq, vbNullString)
                
                ' キーに対し、値段をアイテムとして登録する。
                Dict(myKey) = target_range.Cells(r, c).Value
            Next
        Next
        Set GetPlanDict = Dict
End Function

' 価格取得用ユーザー定義関数
Public Function 料金(支店 As String, _
                     商品 As String, _
                     年度 As String, _
                     プラン As String, _
                     料金表の範囲 As Range, _
                     行の条件数 As Long, _
                     列の条件数 As Long) As Variant

    Static Dict As Dictionary
    If Dict Is Nothing Then
        Set Dict = GetPlanDict(料金表の範囲, 行の条件数, 列の条件数)
    End If
    
    Dim myKey As String
        myKey = 支店 & 商品 & 年度 & プラン
        If Dict.Exists(myKey) Then
            料金 = Dict(myKey)
        Else
            料金 = "指定エラー"
        End If
End Function


汎用性が高まった分に釣り合わぬほどに、分り難さが激増してしまった(反省)。

f:id:Infoment:20190312222705p:plain

参考まで。