
いつもお世話になっております
以前、某氏から頂戴しましたコードです。
下記の部分がイマイチまかりません。
あとはなんとかわかりました。
詳しくおしえてくれませんでしょうか
dicT(key) = pix
ix = pix
pix = pix + 1
Sub 集計()
Dim dicT As Object
Dim maxrow As Long
Dim wrow As Long
Dim wcol As Long
Const max_person As Long = 1000 '最大人数
Dim price(max_person, 12) As Long '金額
Dim count(max_person, 12) As Long '件数
Dim pix As Long 'price&countへのindex
Dim ix As Long 'price&countへのindex
Dim key As Variant
Dim mm As Long
Dim cx As Long
pix = 1
Set dicT = CreateObject("Scripting.Dictionary") ' 連想配列の定義
maxrow = Cells(Rows.count, 1).End(xlUp).Row '1列目の最終行を求める
For wrow = 2 To maxrow
key = Cells(wrow, "D").Value
If dicT.exists(key) = True Then
ix = dicT(key)
Else
dicT(key) = pix
ix = pix
pix = pix + 1
End If
mm = Month(Cells(wrow, "A").Value) '月を算出
price(ix, mm) = price(ix, mm) + Cells(wrow, "E").Value '金額加算
count(ix, mm) = count(ix, mm) + 1 '件数加算
Next
wrow = 3
For Each key In dicT
ix = dicT(key)
Cells(wrow, "G").Value = key '①追加
For mm = 1 To 12
cx = mm - 4
If cx < 0 Then cx = cx + 12
wcol = 8 + 2 * cx
Cells(wrow, wcol).Value = count(ix, mm) '件数設定
Cells(wrow, wcol + 1).Value = price(ix, mm) '金額設定
Next
wrow = wrow + 1
Next
End Sub
No.1ベストアンサー
- 回答日時:
なんか珍しい部分で悩まれているみたいですね。
個人的には、
key = Cells(wrow, "D").Value
If dicT.exists(key) = True Then
ix = dicT(key)
Else
dicT(key) = pix
ix = pix
pix = pix + 1
End If
★(ここは抜いて)mm = Month(Cells(wrow, "A").Value) '月を算出
price(ix, mm) = price(ix, mm) + Cells(wrow, "E").Value '金額加算
count(ix, mm) = count(ix, mm) + 1 '件数加算
これで1固まりとして考えると答えがでる感じですけどね。
変数:ix は2つの二次元配列の行を指していると思って下さい。
それで、
key = Cells(wrow, "D").Value
If dicT.exists(key) = True Then
ix = dicT(key)
によりDictionaryオブジェクトのキーに変数:keyが既に存在していれば、格納しているアイテム(行番号)を ix に代入する。
存在していなければ(今回の質問)
dicT(key) = pix ' 行番号を変数:pixから取得する
ix = pix 'ここは単に ix に pix を代入して次の作業で使用する(別に ix = dicT(key) でも構わないと思いますよ?既に代入済みなので)
pix = pix + 1 '次回の為に行番号を新たに移動させる手段として +1 を加えておく
なんですけどね。
でもでも pix の初期値
pix = 1
が
pix = 0
であれば
pix = pix + 1 '行番号を新たに決定させる手段として +1 を加えておく
dicT(key) = pix ' 行番号を変数:pixから取得する
ix = pix 'ここは単に ix に pix を代入して次の作業で使用する(別に ix = dicT(key) でも構わないと思いますよ?既に代入済みなので)
とも書けたのですが。
No.3
- 回答日時:
'【つづき】
' 確認用データ作成
Public Sub testData()
Dim vA As Variant
Dim dt As Date
Dim sS As String
Dim i As Long, j As Long, n As Long
Randomize
sS = InputBox("何行?", , 10000)
If (sS = "") Then Exit Sub
n = Val(sS)
If (n < 1) Then n = 1
dt = DateSerial(Year(Date), 4, 1)
ReDim vA(1 To n, 1 To 5)
For i = 1 To n
vA(i, 1) = Format(dt + Int(365 * Rnd()), "yyyy/m/d")
vA(i, 2) = "B" & i
vA(i, 3) = "C" & i
sS = ""
For j = 0 To Int(2 * Rnd())
sS = sS & String(3, Chr(Asc("A") + Int(26 * Rnd())))
Next
vA(i, 4) = sS
vA(i, 5) = (Int(999 * Rnd()) + 1) * 10
Next
With ActiveSheet
.Cells.Delete
With .Range("A2").Resize(n, 5)
.Value = vA
.EntireColumn.AutoFit
If (MsgBox("Sort ?", vbYesNo) = vbYes) Then
.Sort .Cells(4), xlAscending _
, .Cells(1), , xlAscending, Header:=xlNo
End If
End With
n = 8
For j = 1 To 12
With .Cells(1, n).Resize(, 2)
.Merge
.Value = IIf(j + 3 > 12, j - 9, j + 3)
.HorizontalAlignment = xlCenter
End With
.Cells(2, n).Value = "件数"
.Cells(2, n + 1).Value = "金額合計"
n = n + 2
Next
.Columns.AutoFit
End With
End Sub
No.2
- 回答日時:
まだ閉じられていなかったので・・・
提示あった記述での Dictionary の使い方は、
配列変数 price count 其々の行、集計用に、誰に何行目を割り当てたか・・・ですね
Dictionary は、どれをキーにして、何を覚えさておく・・・・
自由に発想すれば良いと思います
例えば、
Samp1:提示あった記述と同じ、誰を何行目に割り当てたか
書き出し回数を減らしたいので、最終形のイメージに近い以下変数で
名前用配列 sA(1 To 1000, 1 To 1)
件数・金額合計のペアで 12 ヶ月分 jA(1 To 1000, 1 To 24)
値が出現しない部分を 0 埋めしたいので、jA は Long 型で
どの行に割り当てたかは、k = dic(vK) で入手
覚えていなかったら、キーが登録され、初期値の Empty が得られる
この時、k = 0 で判別できるように、各配列は 1 ~ としておく
集計後、配列 sA, jA を書き出して・・・
※ 配列を 静的に 1 ~ 1000 用意して
無駄だったり、足りなくなったり??
以下のように変更してみる???
Samp2:その人の集計する範囲を配列で覚えて、それを更新していく
配列のひな型 vA(0 To 24) で確保しておいて、集計部分 0 埋めしておく
v = dic(vK) して、覚えていたものを入手する
v が配列でなかったら、初めて出現した人(キー)
なら、v = vA して雛型をコピーして、名前を入れておく
更新したら、覚えなおして・・・・
覚えていた一人の 25 列分の配列を G 列から書き出せば、
ひとり分の書き出しは完了するけど、書き出し回数を減らしたい・・・
書き出す範囲は、With .Range("G3").Resize(dic.count, 25)
覚えていた値全体 dic.Items ・・・Transpose 2回すると、一気に書き出せる
※ 確認用データが必要なら、testData を実行すれば・・・
Dictionary は色々な使い方できるので、しっかり覚えておいた方が良いと思います
以前回答した以下
クロス集計
https://oshiete.goo.ne.jp/qa/10679533.html
この方法も理解しておくと、後々使えるかも?
dic : 行項目がキー ・・・ 値は Dictionary(2段目)
2段目キーは列項目 ・・・ 値は合計処理
dicM:列項目(上記2段目キー全部)
集計後、書き出し表分の配列を定義
ReDim vA(1 To dic.Count + 2, 1 To dicM.Count + 2)
列項目を2列目から展開しつつ、項目を何列目に書き出したか覚えておく
dic から覚えていたキーで
2段目キーから何列目への書き出しか dicM から求めて、その位置に集計値を
配列 vA を一気に書き出して、列・行 で並び替えて・・・
Option Explicit
Public Sub Samp1()
Const CPC As Long = 1000 ' 最大人数
Dim dic As Object
Dim sA(1 To CPC, 1 To 1) As String
Dim jA(1 To CPC, 1 To 24) As Long ' 件数、金額 x 12 組
Dim vK As Variant
Dim i As Long, j As Long, k As Long, n As Long, m As Long
Set dic = CreateObject("Scripting.Dictionary")
n = 0
With ActiveSheet
For i = 2 To .Cells(Rows.count, "A").End(xlUp).Row
vK = .Cells(i, "D").Value
m = Month(.Cells(i, "A").Value) - 4
If (m < 0) Then m = m + 12
j = m * 2 + 1
k = dic(vK)
If (k = 0) Then
n = n + 1
k = n
dic(vK) = k
sA(k, 1) = vK
End If
jA(k, j) = jA(k, j) + 1
jA(k, j + 1) = jA(k, j + 1) + .Cells(i, "E").Value
Next
If (n > 0) Then
Application.ScreenUpdating = False
With .Range("G3").Resize(n, 25)
.Columns(1).Value = sA
.Columns(2).Resize(, 24).Value = jA
.Sort .Cells(1), xlAscending, Header:=xlNo
End With
Application.ScreenUpdating = True
End If
End With
Set dic = Nothing
End Sub
Public Sub Samp2()
Dim dic As Object
Dim wsf As WorksheetFunction
Dim vA(0 To 24) As Variant
Dim vK As Variant, v As Variant
Dim i As Long, j As Long, m As Long
Set dic = CreateObject("Scripting.Dictionary")
Set wsf = WorksheetFunction
For j = 1 To 24
vA(j) = 0
Next
With ActiveSheet
For i = 2 To .Cells(Rows.count, "A").End(xlUp).Row
vK = .Cells(i, "D").Value
m = Month(.Cells(i, "A").Value) - 4
If (m < 0) Then m = m + 12
j = m * 2 + 1
v = dic(vK)
If (Not IsArray(v)) Then
v = vA
v(0) = vK
End If
v(j) = v(j) + 1
v(j + 1) = v(j + 1) + .Cells(i, "E").Value
dic(vK) = v
Next
If (dic.count > 0) Then
Application.ScreenUpdating = False
With .Range("G3").Resize(dic.count, 25)
.Value = wsf.Transpose(wsf.Transpose(dic.Items))
.Sort .Cells(1), xlAscending, Header:=xlNo
End With
Application.ScreenUpdating = True
End If
End With
Set dic = Nothing
Set wsf = Nothing
End Sub
'【つづく】
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
VBA セル間のリンク修正につい...
-
VBAでCOPYを繰り返すと、処理が...
-
複数のExcelファイルをマージす...
-
【マクロ】並び替えの範囲が、...
-
Excelのマクロについて教えてく...
-
VBA 最終行の取得がうまくいか...
-
Vba Array関数について教えてく...
-
【マクロ】シートの変数へ入れ...
-
【マクロ】開いているブックの...
-
【ExcelVBA】値を変更しながら...
-
vba textboxへの入力について教...
-
改行文字「vbCrLf」とは
-
VB.net 文字列から日付型へ変更...
-
WindowsのOutlook を VBA から...
-
【マクロ】売上一覧YYYYMMDDHHS...
-
Excelのマクロについて教えてく...
-
VBAの質問(Msgboxについて)です
-
エクセルのVBAについて教えてく...
-
Vba 型が一致しません(エラー1...
-
VBAで特定の文字が入った行をコ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
VB2008で数字の桁数を調べる...
-
コードの意味 ("Scripting.Dict...
-
[VB6/VBA] Variant型配列リテラ...
-
どんなオブジェクトでも表示で...
-
Excel vba 配列内の最大値を求...
-
六角形のマスの作り方
-
VBA セル範囲をVariant変数に代入
-
delete[]と、delete演算子の明...
-
VBA 多次元配列のクイックソー...
-
PowerPointで時計表示
-
JSPの処理の途中で、JavaScript...
-
VB.NET2003 テキストボックスに...
-
正整数の半角数字かどうか判定する
-
VBAによる第3、4水準文字の判定...
-
以下のコードを実行しても、オ...
-
初心者です。gulpでコンパイル...
-
ブラウザの横幅に応じてとある...
-
if(1){...}とはどういうことで...
-
VBA SORT Applyでエラー
-
エクセルVBA/ Formatで文字列が...
おすすめ情報