プロが教える店舗&オフィスのセキュリティ対策術

いつもお世話になっております。
下記のコードは某サイトから頂戴した
サンプルコードです。
がわたしがやりたいことは
添付ファイルのように
合計をなどを出したとおもいます。
わかる方おしえてくれませんでしょうか
何卒よろしくお願い申し上げます。
 
品物     定価 売上 品物   定価 売上  回数
たまご   1000 10 たまご
牛乳     1200 20 牛乳
食パン   1400 30 食パン
ジャム  1600 40 ジャム
たまご  1800 50
牛乳    2000 60
食パン  2200 70
ジャム  2400 80
食パン  2600 90
ジャム  2800 100
たまご  3000 110


下記のコードは 合計 平均  回数
をだすコードなのです。


品物     定価 売上 品物   合計 平均  回数
たまご   1000 10 たまご
牛乳     1200 20 牛乳
食パン   1400 30 食パン
ジャム  1600 40 ジャム
たまご  1800 50
牛乳    2000 60
食パン  2200 70
ジャム  2400 80
食パン  2600 90
ジャム  2800 100
たまご  3000 110

Sub sample_dc014_01()
Dim dco_Count As Object
Dim dco_Sum As Object
Dim wRow As Long
Dim wKey As String
Dim varKeys As Variant
Dim var As Variant
Dim i As Long
'エクセルの列
Const COL_I_ITEM = 1
Const COL_I_PRICE = 2
Const COL_O_ITEM = 4
Const COL_O_CNT = 5
Const COL_O_SUM = 6
Const COL_O_AVG = 7

'ディクショナリオブジェクトの生成
Set dco_Count = CreateObject("Scripting.Dictionary")
Set dco_Sum = CreateObject("Scripting.Dictionary")

wRow = 3 '入力データ開始行
Do Until Cells(wRow, COL_I_ITEM).Value = ""
wKey = Cells(wRow, COL_I_ITEM).Value
If dco_Count.Exists(wKey) Then
'カウントアップ
dco_Count.Item(wKey) = CLng(dco_Count.Item(wKey)) + 1
'金額加算
dco_Sum.Item(wKey) = CLng(dco_Sum.Item(wKey)) + _
CLng(Cells(wRow, COL_I_PRICE).Value)
Else
'未登録の場合は新規登録
dco_Count.Add wKey, 1
dco_Sum.Add wKey, Cells(wRow, COL_I_PRICE).Value
End If

wRow = wRow + 1
Loop

'キー項目の配列を取得
varKeys = dco_Count.Keys

wRow = 3 '出力データ開始行
'集計項目の表示
For Each var In varKeys
Cells(wRow, COL_O_ITEM).Value = var
Cells(wRow, COL_O_CNT).Value = dco_Count.Item(var)
Cells(wRow, COL_O_SUM).Value = dco_Sum.Item(var)
Cells(wRow, COL_O_AVG).Value = _
dco_Sum.Item(var) / dco_Count.Item(var)
wRow = wRow + 1
Next

'ディクショナリオブジェクトの破棄
Set dco_Count = Nothing
Set dco_Sum = Nothing
End Sub

「("Scripting.Dictiona」の質問画像

質問者からの補足コメント

  • うーん・・・

    申し訳ございません
    Set myDic1 = CreateObject("Scripting.Dictionary")'-------------------追加
              myDic1.Add myVal(i, 1), myVal(i, 3)'-------------------追加
                myDic1(myVal(i, 1)) = myDic(myVal(i, 1)) + myVal(i, 3)
        For i = 0 To UBound(myKey)
          Cells(i + 2, 4).Value = myKey(i)
          Cells(i + 2, 6).Value = myItem(i)'-------------------追加
    文字数の関係上さ追加したのだけかきました。

      補足日時:2020/03/17 11:58
  • うーん・・・

    最初のコードにではなく、こちらのコードに追加です。Set myDic = CreateObject("Scripting.Dictionary")
      Range("D1:E1").Value = Range("A1:B1").Value
        For i = 1 To UBound(myVal, 1)
          If Not myVal(i, 1) = Empty Then
            If Not myDic.exists(myVal(i, 1)) Then
              '---新たなkeyの時はkeyとitemを追加します
              myDic.Add myVal(i, 1), myVal(i, 2)
            Else
              myDic(myVal(i, 1)) = myDic(myVal(i, 1)) + myVal(i, 2)

      補足日時:2020/03/17 12:00
  • いつもお世話になっております。
    いま、わたしなりに解決しかけてきました。
    ただ、平均がうまく表示されないのがきになるます。
    もう一度挑戦します

    「("Scripting.Dictiona」の補足画像3
    No.2の回答に寄せられた補足コメントです。 補足日時:2020/03/17 13:11
  • うーん・・・

    平均もできてました
    勘違いです。
    だけと゛ できたのはうれしいのですが、

      補足日時:2020/03/17 13:15

A 回答 (3件)

No.2です。


知らぬ間に随分と書かれてたのですね。
メールでは一番最後に投稿された(みたい?)『お礼』だけが入ってきましたが。

取り敢えず私の手段で質問文の内容をやってみました。

Sub megu()
Dim myDic As Object
Dim var As Variant, key As Variant, v As Variant
Dim i As Long

Set myDic = CreateObject("Scripting.Dictionary")

var = Range("A2", Cells(Rows.Count, "A").End(xlUp)).Resize(, 3).Value

For i = LBound(var, 1) To UBound(var, 1)

If Not myDic.Exists(var(i, 1)) Then
myDic.Add var(i, 1), Array(var(i, 2) * var(i, 3), var(i, 2) * var(i, 3), 1)
' Array(合計,平均(=合計),1(=初回なので1))
Else
v = myDic(var(i, 1)) 'ItemをValiant型変数:v に1次元配列として渡す。
'インデックスの最小値は0になる事に注意。

v(0) = v(0) + var(i, 2) * var(i, 3) '今までの合計に定価×売上を加算する
v(2) = v(2) + 1 '回数のカウントを+1する
v(1) = v(0) / v(2) '上記2つで平均を再計算
myDic(var(i, 1)) = v 'Itemとして書き換えた配列を代入する。
End If

Next

Range("E1:H1").Value = Array("品物", "合計", "平均", "回数")

i = 2 '書き出し開始行

For Each key In myDic.Keys
Cells(i, "E").Value = key
Cells(i, "F").Resize(, 3).Value = myDic(key)
i = i + 1
Next

Set myDic = Nothing

End Sub

ご参考になれば幸いです。
「("Scripting.Dictiona」の回答画像3
    • good
    • 0
この回答へのお礼

いつも有難うございます。
やっぱりコードがわかりやすく、スリムです。
ありがとうございました。

お礼日時:2020/03/17 14:24

No.1です。



あ~

> 品物   定価 売上  回数

もしかしてこれを出したいって事ですか?
そこはまず挑戦してみましょうよ。
ほぼ回答は出ているのであってコードもですがそれより『どこの値をどのように扱って計算させるか』なのですから、
応用力(サンプルコードの解析力含む)を鍛え上げないと。

先にも書きましたが質問文の内容をBookで作成して回答(サンプルコード)で検証。
その後やりたい事へ導くためにコードを自身で弄っては失敗し検索して間違いを探す。
10回ほど試してダメなら『このようにコードを作成してみましたが、どこに問題があるのでしょう?』と始めた頃は質問も数回しました。
あとは他の質問者と回答者のやり取りの中での回答をテキストファイル等で溜め込んで、自分のやりたい事への足掛かりにしましたし。

この質問に対しての回答って事になるとサンプルコードとは確実に手段が違うので、結果だけを見るならともかく自身でも組み立てたいと言うのなら
私の回答は上げない方が宜しいかな?
逆に混乱させてしまいますので、まずはサンプルコードの改良版の回答をお待ちください。
この回答への補足あり
    • good
    • 0
この回答へのお礼

いつも有難うございます。
わたしでもできました。だけど
keys3 = dic(keys1(i1))(keys2(i2)).Keys
なんかこういうのでできたならいいなとおもいました。
ありがとうございました。

お礼日時:2020/03/17 13:19

コードを実行はしてませんけど、目的には達してそうな気もしますが何か他の手段を知りたいって事でしょうか?


仮に私が書いてしまうと過去の回答にもあったと思いますが、Itemに配列を使ってしまうのでややこしいと言えばそうかもですね。
私も最初は混乱しましたけど昔の常連回答者さんのコードをひたすら質問文の内容を作成し実行して、何となく扱えるようになりました。

なのでここでよく見かける
・.Keys(~)
・.Items(~)
・Valiant型変数への代入
とかを使うのはまず皆無です。
とにかく書き出す際には一括で Items から吐き出せるよう Key さえも配列に入れて Item に代入させてます。
あとは配列のインデックスを使用することで複数の Dictionary の宣言や別の動的配列変数の作成などを回避するようにしてます。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!