コード記述は、最後部で紹介 |
表のように、重複する項目が記載された表(左側)の在庫量をまとめてみます。
右側に集計結果が表示されますが、大きなデータは役に立つコードと思います。
ネットでも検索すると、複数のサンプルコードが見つかりますが、問題がある。
それは、動かないコードを紹介していて、できれば記事を削除してもらいたい。
役に立たないコードを探しても意味がありませんから、忘備録的に纏めました。
このコードは、連想配列の記述を使っていますが、範囲を配列で扱うのがミソ。
Range().Valueの値は、既に二元配列の扱いになり、各要素の取り出しが可能。
この変数を表す”myList”から、例えばmyList(4,2)の値を取得することにします。
これは、4行目と2列目の交差するセル値を示しており、これが役に立ちました。
サンプルコードでは、連想配列のキーと項目を格納するのに、配列位置を指定。
こういう考え方 |
つまり、myList(*,1)では、キーになるのが一列目で、2であれば項目になる。
この配列位置の指定により、キーが重複して出現すれば、2列目の数値を加算。
面白いのは、辞書変数をキーの値で指定して、それに項目値を直接に足します。
式は、myDic(myList(i, 1)) = myDic(myList(i, 1)) + myList(i, 2)、なんだな。
まあ、For Each ~Nextで回す時、i = i + 1 で数値の加算式を入れたりもする。
この考えにも似ているので、これが連想配列の定義としてのルールなのだろう。
VBAの紹介サイトでも、プログラミングの発想として重要と述べていました。
次に、一連の作業が終われば、Set myDic = Nothing のようにメモリー開放だ。
だけど、本当はメモリー内部に、キーと項目の要素が残っている気もするんだ。
実は、複雑なマクロの構文を書いた中、この配列を組み込んでみたが動かない。
埒が明かなくて、Collectionに変更したんだけど、挙動が安定しなくて困った。
色々と探しまくった結果、この要素は変数を解放してもメモリーに残るらしい。
なので、Removeなるコマンドを使って消去するのですが、連想配列もそうだ。
メモリー解放前に、Eraseというコマンドを使ってキーと項目を削除しました。
というわけで、連想配列を使って最も役に立つサンプルコードが完成しました。
これまで、連想配列の記述は分かったようで、分からないのが本当で、ネットで紹介されているサンプルコードは、実務に使えない感じもしていたのですが、実用的でもこれだけ小さくまとめて役立つのですから、初心者の皆さんであっても、ぜひ活用していただきたいと思ったのでした。
<サンプルコード>
Sub Sample() '完動コード
Dim myDic As Object, myKey As Variant, myarray As Variant
Dim myItem As Variant, myList As Variant, i As Long
Set myDic = CreateObject("Scripting.Dictionary")
'セル範囲をVariant型変数で、配列作成
myList = Range(Range("A2"), Range("B" & Cells(Rows.Count, 2).End(xlUp).Row)).Value
For i = 1 To UBound(myList, 1) '連想配列にデータを格納
If Not myList(i, 1) = Empty And (Not myDic.Exists(myList(i, 1))) Then
'キーが空欄かチェック/辞書登録があるかチェック
myDic.Add Key:=myList(i, 1), Item:=myList(i, 2)
'重複しないキー項目を登録
Else
myDic(myList(i, 1)) = myDic(myList(i, 1)) + myList(i, 2)
'重複キーの項目値を加算
End If
Next i
myKey = myDic.Keys '重複していないキーを格納
myItem = myDic.Items '重複項目の合計を格納
For i = 0 To UBound(myKey) 'リストを出力
Cells(i + 2, 5).Value = myKey(i)
Cells(i + 2, 6).Value = myItem(i)
Next
Erase myItem 'キーと項目の削除
Erase myKey
Set myDic = Nothing '開放
End Sub
0 件のコメント:
コメントを投稿