Excel VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


190 / 13645 ツリー ←次へ | 前へ→

【81600】重複Key毎の合計を求める assya 21/1/20(水) 21:49 質問[未読]
【81601】Re:重複Key毎の合計を求める γ 21/1/21(木) 7:39 発言[未読]
【81602】Re:重複Key毎の合計を求める assya 21/1/21(木) 15:09 回答[未読]
【81604】Re:重複Key毎の合計を求める γ 21/1/21(木) 23:24 発言[未読]
【81605】Re:重複Key毎の合計を求める assya 21/1/22(金) 12:01 お礼[未読]
【81603】Re:重複Key毎の合計を求める マナ 21/1/21(木) 18:42 発言[未読]
【81606】Re:重複Key毎の合計を求める assya 21/1/22(金) 12:03 お礼[未読]

【81600】重複Key毎の合計を求める
質問  assya  - 21/1/20(水) 21:49 -

引用なし
パスワード
   VBA初心者です。表題の件につきまして調べ・試し数日悩みまして、いよいよ解決方法がなくここで質問させてください。

以下のようなデータがあります。
Column1をキーにして、重複を除外、Column2以降(7以降も30~40程データがあります)を合計したいです。

そして我儘ですが勉強のためにdictionaly型で実装したいです。

FOR分をまわして、If Not myDic.exists(myList(i, 1)) Then でキーの重複を除外することまではできたのですが、
下記例でいうところのキー(AAAAA) × Column2 の合計値を13に計算するという部分が理解できていません。

==================
Column1    Column2    Column3    Column4    Column5    Column6    Column7
AAAAA    10.00    0.00    0.00    0.00    0.00    10.00
BBBBB    0.00    2.00    3.00    3.00    0.00    0.00
CCCCC    0.00    0.00    0.00    0.00    0.00    0.00
BBBBB    0.00    5.00    6.00    4.00    0.00    0.00
AAAAA    1.00    4.00    1.50    4.00    0.00    0.00
AAAAA    2.00    0.00    0.00    0.00    0.00    0.00
BBBBB    3.00    1.00    0.50    0.00    0.00    0.00
BBBBB    0.00    0.00    0.00    0.00    0.00    0.00
CCCCC    8.00    0.00    0.00    0.00    0.00    0.00
==================

==================
Column1    Column2    Column3    Column4    Column5    Column6    Column7
AAAAA    13.00    4.00    1.50    4.00    0.00    10.00
BBBBB    3.00    8.00    9.50    7.00    0.00    0.00
CCCCC    8.00    0.00    0.00    0.00    0.00    0.00
==================

全然間違っていると思うのですが、以下に現状のソースを載せます。

Sub sample()

Dim myDic As Object
Dim myKey As Variant
Dim myItem As Variant
Dim Value As Variant
Dim myList As Variant
Dim i, u As Long

  Set myDic = CreateObject("Scripting.Dictionary")

  'A列,AF列のデータ全体DTを変数に格納
  myList = Range("A8:AF18").Value
  
  For i = 1 To UBound(myList, 1) 'DTのRow分くりかえす

    myKey = myList(i, 1)
    
    'Keyが空かチェック
    If Not myList(i, 1) = Empty Then
      
      If Not myDic.exists(myList(i, 1)) Then '重複チェック

        '重複がない場合Itemを登録
        For u = 2 To 32
          myItem = myList(i, u)
          Debug.Print "myItemは" & myItem & "です"
        Next u
        
        'keyを辞書登録
        myDic.Add myList(i, 1), myItem
        
      Else
        '加算
        For u = 2 To 32
          myItem = myList(i, u) + myList(i, u)
          Debug.Print "合算後myItemは" & myItem & "です"
        Next u
      End If
    End If
  Next

  '重複していないリストを格納
  myKey = myDic.Keys
  
  '重複を除いたkeyの一覧を出力
  For i = 0 To myDic.Count - 1
    Debug.Print myKey(i)
  Next

  '合計を格納
  'myItem = myDic.items
  
  For i = 0 To myDic.Count - 1
    Debug.Print "キーの値:" & myKey(i)
  Next

  'リストを出力
  For i = 0 To UBound(myKey)
    Cells(i + 25, 1).Value = myKey(i)
    For u = 2 To 33
      Cells(i + 25, u).Value = myItem(i, u)
    Next u
  Next

  '開放
  Set myDic = Nothing

End Sub

【81601】Re:重複Key毎の合計を求める
発言  γ  - 21/1/21(木) 7:39 -

引用なし
パスワード
   この場合のdictionaryのitemは配列とします。
(1)新たなキーの場合、
・その行の各要素を持つ配列をitemにセットする
(2)既存のキーがある場合、
・dictionaryのitemを変数に取得する
・その行の配列の各要素を、その配列変数に要素ごとに加算する。
・改めて、それをdictionaryのitemにセットする。
ということになります。

【81602】Re:重複Key毎の合計を求める
回答  assya  - 21/1/21(木) 15:09 -

引用なし
パスワード
   ▼γ さん:
>(2)既存のキーがある場合、
>・dictionaryのitemを変数に取得する
>・その行の配列の各要素を、その配列変数に要素ごとに加算する。

アドバイスいただきありがとうございます。

"・その行の配列の各要素を、その配列変数に要素ごとに加算する。" ここの部分なのですが、既存のdictionaly Keyに対して、加算してitemをaddしなおすには、どういった書き方をするのでしょうか...?
既存のKeyをselectしてそこのitemに入れる、という書き方がわからずでして。
度々申し訳ありませんがわかりましたらご助言いただけないでしょうか。

よろしくお願いいたします。

【81603】Re:重複Key毎の合計を求める
発言  マナ  - 21/1/21(木) 18:42 -

引用なし
パスワード
   ▼assya さん:

γさんの、ここを含む掲示板での回答を見て
わたしも使えるようになった方法です。

空の2次元配列を用意して、
各要素に加算を繰り返すことで集計します。
dictionaryには、配列のindexを登録していす。

Sub test()
  Dim dic As Object
  Dim w()
  Dim r As Long, c As Long
  Dim v
  Dim s As String
  Dim n As Long
  
  Set dic = CreateObject("scripting.dictionary")
  
  v = Range("A1:G9").Value
  
  ReDim w(1 To UBound(v, 1), 1 To UBound(v, 2))
  
  For r = 1 To UBound(v, 1)
    s = v(r, 1)
    If Not dic.exists(s) Then
      dic(s) = dic.Count + 1
      w(dic(s), 1) = s
    End If
    n = dic(s)
    For c = 2 To UBound(v, 2)
      w(n, c) = w(n, c) + v(r, c) '★ここで加算
    Next
  Next
  
  Range("A21").Resize(dic.Count, UBound(w, 2)).Value = w
  
End Sub

【81604】Re:重複Key毎の合計を求める
発言  γ  - 21/1/21(木) 23:24 -

引用なし
パスワード
   遅くなりました。

dictionaryとは、
Key → Item
という対応関係を管理する容れ物です。

・Keyは文字列とか数値などをとることが多いですが、
・Itemも色々なものを保持することができます。
既に提示されたのは、配列の行番号をとったものですが、
(提示された方法のように)配列そのものを持たせることもできます。

こんな感じになるでしょう。参考にしてみて下さい。

Sub test()
  Dim dic As Object
  Dim k As Long, j As Long, r As Long
  Dim s As String
  Dim v As Variant
  Dim itm As Variant
  Dim key As Variant

  Set dic = CreateObject("Scripting.Dictionary")

  For k = 2 To 10
    s = Cells(k, 1).Value
    If Not dic.Exists(s) Then
      v = Cells(k, 2).Resize(1, 6).Value
      dic(s) = v
    Else
      'いったん取り出し
      itm = dic(s)

      '各要素に加算
      v = Cells(k, 2).Resize(1, 6).Value
      For j = 1 To 6
        itm(1, j) = itm(1, j) + v(1, j)
      Next

      '再度 格納
      dic(s) = itm
    End If
  Next
  Sheet2.Range("A2").Resize(dic.Count, 1) = Application.Transpose(dic.keys)

  '結果をシートに書き出す
  r = 1
  For Each key In dic
    itm = dic(key)
    r = r + 1
    Sheet2.Cells(r, 2).Resize(1, 6) = itm
  Next
End Sub

考え方に焦点を当てていますので、元データの行数や列数とか、
転記先の一行目の項目名、などは適当にしています。
そちらで修正して下さい。
また、各配列は、あえて一次元に変換せず、二次元のままにしています。

【81605】Re:重複Key毎の合計を求める
お礼  assya  - 21/1/22(金) 12:01 -

引用なし
パスワード
   ▼γ さん

何度もありがとうございます。
いただいたコードを参考に、手元で作っていたものとマージしたところ、実現したいことができました!!
そしてdictionaly変数に関しても理解が深まりました。(なんとなく理解したつもりでいたのですが全然でした...)

指定したkeyに対して再度格納するには [dic変数]([key名]) = [入れる変数] で入れれるのですね。
自分の作ったコードは色々処理を入れているうちに結局この倍ぐらいの長さになってしまったので見直してみます。。

本当にありがとうございました。

【81606】Re:重複Key毎の合計を求める
お礼  assya  - 21/1/22(金) 12:03 -

引用なし
パスワード
   ▼マナ さん:

アドバイスいただきありがとうございました!
Yさんからもコメントいただき、解決いたしました。

本当にありがとうございました。

190 / 13645 ツリー ←次へ | 前へ→
ページ:  ┃  記事番号:
2610219
(SS)C-BOARD v3.8 is Free