ショボ短歌会

idDicというオブジェクト(連想配列)を作成しました。
keyには既に重複しないIDリストが作成されています。
itemには、niListという配列を設定してあり、初期値としてarray(0,0,0,0,0,0,0)が設定されています。

"日計"シートのデータを1行ずつ調べ、条件に応じてidDicのアイテム(niList)を変更したいです。
下記のような感じの処理をしたいのですが、日計シートの該当ID(keyID)と同一のIdDicのkeyの取得や、そのアイテム(niList)の指定方法がわかりません。
(書き方、指定の仕方がわからないので雰囲気で書いてみました)
(コチラの意図するところがご理解頂けると幸いです・・・)
そもそも、Dictionaryの使い方として不適切であれば、その様にご指導下さい。

日計シートの確認中に該当IDが出現する都度、各IDのniList(0)に1づつ加算、
日計10列目の値が4以下ならば、各IDのniList(4)に1づつ加算、
日計10列目の値が6より大きければ、各IDのniList(6)に1づつ加算したいです。
(実際にはもう少し条件が多いですが、例として上記のような感じです)

for n = 2 to lg '日計シートの2行目から最終行(lg)まで繰り返し処理

  keyID as string
  keyID = worksheets("日計").cells(n,5).value '日計シートには5列目にIDが有ります。
   
  ↓(こんなイメージの事をしたいのですが書き方がわかりません)
  idDic.key(keyID).item(niList(0)).value = niList(0) + 1

if worksheets("日計").cells(n,10).value > 6 then
idDic.key(keyID).item(niList(6)).value = niList(6) + 1

↑↓(こんなイメージの事をしたいのですが書き方がわかりません)

else if worksheets("日計").cells(n,10).value <= 4 then
idDic.key(keyID).item(niList(4)).value = niList(4) + 1
end if

next n

A 回答 (2件)

No.1です。



>idDic.Item(keyID)(6)を試しましたが、思うように動作しません。
ここは自分も憶測で回答してしまった点で、期待させてしまい申し訳ないです。

先の回答にあった
>これってkeyが違ってもItemに変数を与えていたら、他も書き換えないかな?
については、サブPCで検証した結果問題なかったですね。

ただ値を入れる時は一度別のValiant型変数に代入し、必要なインデックスで加算を行い
再度Dictionaryに戻すやり方の方が良いのかもです。

Sub try()

Dim myDic As Object
Dim key As Variant
Dim iList As Variant
Dim v As Variant

Set myDic = CreateObject("Scripting.Dictionary")

iList = Array(0, 0, 0)

myDic.Add "A", iList
myDic.Add "B", iList
myDic.Add "C", iList

v = myDic.Item("A"): v(0) = v(0) + 1: myDic.Item("A") = v
v = myDic.Item("B"): v(1) = v(1) + 1: myDic.Item("B") = v
v = myDic.Item("C"): v(2) = v(2) + 1: myDic.Item("C") = v

For Each key In myDic.Keys
Debug.Print key, Join(myDic.Item(key), "==")
Next

Set myDic = Nothing

End Sub

ーーー結果ーーー
A 1==0==0
B 0==1==0
C 0==0==1
ーーーーーーーー

これを踏まえると、
・加算に使用する別のValiant型変数を宣言する。(仮にvとする)
・Dim keyID As Stringの宣言はFor~Next内で行う必要はなく、コードの最初で行うべし。

Dim v As Variant '★
Dim keyID As String '★

niList = Array(0, 0, 0, 0, 0, 0, 0)

Set idDic = CreateObject("Scripting.Dictionary") '★

With Worksheets("日計") '★

ld = .Cells(Rows.Count, 2).End(xlUp).Row '★

For i = 2 To ld '日計に日付入力の有る最終行まで確認

keyID = .Cells(i, 5).Value '重複確認をするID '★

If Not idDic.exists(keyID) Then 'IDの重複を確認 ★
idDic.Add keyID, niList '重複しないIDを配列に格納
End If

'日計シートの確認中に該当IDが出現する都度、各IDのniList(0)に1づつ加算、★
v = idDic.Item(keyID):v(0) = v(0) + 1:idDic(keyID) = v '★

Select Case .Cells(i,10).value '★

'日計10列目の値が4以下ならば、各IDのniList(4)に1づつ加算、★
Case Is <= 4 '★
v = idDic.Item(keyID):v(4) = v(4) + 1:idDic(keyID) = v '★

'日計10列目の値が6より大きければ、各IDのniList(6)に1づつ加算 ★
Case Is > 6 '★
v = idDic.Item(keyID):v(6) = v(6) + 1:idDic(keyID) = v '★

End Select '★

Next i '★

End With '★


ーーーーーー

Select Case については
https://www.sejuku.net/blog/30642#Is

ループは1回で出来ると思いますし、With~End WithやSelect Caseで纏めるのが良いかも。
★の部分は書き換えてみましたが、実際に動作検証は出来てません・・・ごめんなさい。

ところでこれはWorksheets("日計")しか使ってないですよね?
    • good
    • 0
この回答へのお礼

またまた迅速なるご回答、誠に有難うございます!
当方の技術力では理解が難しいですが、なんだか出来そうな気がしてきました。
ご提案頂いたソースを理解するべく努力し、試してみます!
(技術、理解が追いつかないので、すぐに”できました!”ってご回答出来ず申し訳ない)

別の方法として、keysを1次元配列(ids)に格納したりと、試行錯誤しておりました。
ちなみに、idsをReDimで2次元関数ids(key.count,7)などとするとidsの内容が消えたり・・・。更には新たなids2を作ってidの数行×7列の配列を作ったり・・・。
アレコレ挑戦しております。

「ところでこれはWorksheets("日計")しか使ってないですよね?」については、
日計シートの内容をID毎に集計(仕分け?)して、別のデータシートに転記する予定です。
niList(2)はデータシートの15列目、niList(5)はデータシートの36行目・・・とか・・・。

まだ配列とDictionaryの違い(指定の仕方など)があやふやなので精進いたします!
今回の作業テーマ(この質問事項以外にもいくつかの作業予定がある)完了までに、まだまだ壁に当たる予感がビシビシ致します・・・。また質問をあげさせていただくと思いますので、お目にかかりましたらよろしくお願いいたします!

お礼日時:2018/02/02 13:31

検証が出来ないですが。

(メインPC修理中で)

>itemには、niListという配列を設定してあり、初期値としてarray(0,0,0,0,0,0,0)が設定されています

これってkeyが違ってもItemに変数を与えていたら、他も書き換えないかな?

https://oshiete.goo.ne.jp/qa/10020635.html

ここで回答してますが、Itemに直接array(0,0,0,0,0,0,0)を入れた方が良いと思う。

>idDic.key(keyID).item(niList(4)).value

使っているのはDictionaryオブジェクトですよね?
確か.Valueってないはずですよ。
https://msdn.microsoft.com/ja-jp/library/cc42820 …
VB等のDictionaryクラスには.Valuesと言うプロパティがありますけど。

何を参考に作成されたのかきにはなりますけど、キーが存在しているなら
idDic.item(keyID)(6) = idDic.item(keyID)(6) + 1
と書けるか、以前私が回答している
   v = myDic(r.Value)
   v(i) = r.Offset(, 2).Value
   myDic(r.Value) = v
これを
v = idDic(keyID)
v(6) = v(6)+1
idDic(keyID) = v
とするのだと思います。(修理中で試せないので自信はありませんけど)

Dictionaryにキーが存在しているかどうかも.Existsで判定していないみたいですが、
やっぱ参考にした物が気になりますねぇ。
    • good
    • 0
この回答へのお礼

早速のご回答、ありがとうございます。
.Existsでの判定は下記のように行っております。
(記載不十分で失礼いたしました)
なお、 idDic.Item(keyID)(6)を試しましたが、思うように動作しません。
そもそも、Dictionaryのまま処理せず、2次元配列などにした方がよいのでしょうか?

niList = Array(0, 0, 0, 0, 0, 0, 0)

ld = Worksheets("日計").Cells(Worksheets("日計").Rows.Count, 2).End(xlUp).Row

Set idDic = CreateObject("Scripting.Dictionary")

For i = 2 To ld '日計に日付入力の有る最終行まで確認

checkID = Cells(i, 5).Value '重複確認をするID

If Not idDic.exists(checkID) Then 'IDの重複を確認
idDic.Add checkID, niList '重複しないIDを配列に格納
End If

Next i

For nr = 2 To ld '日計表を上から最終行までチェック

'日計各行のIDをkeyID、該当するidDicのniListに数字を加算したい
Dim keyID As String
keyID = Worksheets("日計").Cells(nr, 5).Value
idDic.Item(keyID)(6) = idDic.Item(keyID)(6) + 1
   '↑教えて頂いた表現でniList(6)への加算を試してみました  

Next nr

お礼日時:2018/02/02 10:41

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