空腹おやじのログと備忘録

VBA(主にExcel)でいろいろな実験的な事とか、Linuxのコマンドとか設定とかについて忘れないように、あれこれと・・・

【VBA】Excelで、製品の販売価格の更新情報を持つマスタから、いろいろな販売日の価格を取得する

難しく書いたけど、要するに
ある製品の販売価格が、不定期に変わっていて、その履歴が残っている。
じゃあ、「任意のタイミングでの販売価格はいくらか?」を取得するというもの。

元ネタはこちら
https://twitter.com/ia02003812/status/1122857099669598209

 ワークシート関数だけでも出来そうだけど、データ件数が多いとなるとレスポンスが悪そう。
 VLookUpでは、複数条件で絞り込めなさそうなので多分NG.
 MAXIFS を使えば出来そうだけど、うちのExcelは 2013 なので使えない。
 他にも方法はあるのだろうけど、今回は(今回も?)VBAで・・・



データは下に載せたような感じ。
いつもの如く、乱数使いまくって・・・
データ作成のコードも下の方に載せてあるので、興味のある方はどうぞ。
同じデータは作れませんけど、近いものは作れるはずなので・・・


価格履歴:各製品の販売価格の更新情報を持つマスタ(製品名、販売価格、適用開始年月日)
f:id:Z1000S:20190508213737j:plain
重要:価格履歴データは適用開始日が昇順でソートされていないと、掲載したコードは正しく動きません。


販売トラン:各製品の販売実績データ(販売日、製品名、販売数)
f:id:Z1000S:20190508213750j:plain
「データの名称が、下記のコード中の名称と違う」とか突っ込まないで下さい。

問題点としては、販売トランにある販売日が、価格履歴の価格適用開始日と一致する保証がないので、通常の完全一致の検索が出来ない。
これを解決する手段が必要。



これについては、Dictionary を使用して、以下のようにデータを格納し、その中から該当データを取得出来るようにした。
Key:製品名
Item:「販売価格」、「適用開始年月日」をペアにした物の配列

Dictionary への動的配列の格納は、以前やっているので特に問題はない。
z1000s.hatenablog.com




テスト用データ生成コードで使っている定数とかは、上の「販売価格 更新処理コード」に記載されているので、上のコードと同じモジュールに貼り付けて使って下さい。

実行結果

f:id:Z1000S:20190509222234j:plain
製品種類数:200
価格履歴件数:8,072
販売データ件数:10,000

所要時間:0.8 ~ 0.9 秒

でした。

遅くはないと思うけど、比べる物が無いので・・・


おまけ

「(0)(0)って何?」という方向けの、"よくわからないかもしれない" 解説のようなもの。

dicItemInfo_.Item(sItemName)(0)(0)
vaItemInfo(0)(0)

配列の要素が配列なので、こういう記述になります。ハイ。

例えば
a(2)
という配列があるとして、
a(0)の要素が、b という配列の場合、b(0)を参照するには
a(0)(0)
という指定をします。

Public Sub foo()

    Dim a(2)
    Dim b(1)

    b(0) = "B00"
    b(1) = "B01"

    a(0) = b

    b(0) = "B10"
    b(1) = "B11"

    a(1) = b

    Debug.Print "A00 : " & a(0)(0)
    Debug.Print "A01 : " & a(0)(1)

    Debug.Print "A10 : " & a(1)(0)
    Debug.Print "A11 : " & a(1)(1)

End Sub

実行結果

call foo
A00 : B00
A01 : B01
A10 : B10
A11 : B11


本当は、Dictionary の Item には、構造体(ユーザー定義型)を入れたかったんですよ。
でも、出来ないみたいだったので、やむなく配列で代用しました。
その結果がこれです。