2021年8月7日土曜日

ネットにあるVBAのサンプルコードは、実用からほど遠くて、使えるようになりたければ授業料を払えっていうサイトが多いのかもしれん - Scripting.Dictionary(VBA・連想配列)

コード記述は、最後部で紹介
      
表のように、重複する項目が記載された表(左側)の在庫量をまとめてみます。
右側に集計結果が表示されますが、大きなデータは役に立つコードと思います。

ネットでも検索すると、複数のサンプルコードが見つかりますが、問題がある。
それは、動かないコードを紹介していて、できれば記事を削除してもらいたい。

役に立たないコードを探しても意味がありませんから、忘備録的に纏めました。
このコードは、連想配列の記述を使っていますが、範囲を配列で扱うのがミソ。

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 件のコメント:

コメントを投稿