• ベストアンサー

エクセルVBAでDictionaryオブジェクトについて

エクセル2000です。 教えてください。 http://www.eurus.dti.ne.jp/~yoneyama/Excel/vba/vba_dictionary.html というサイトで  「myDic.Add Cells(i, 1).Value, Cells(i, 2).Value は   myDic(Cells(i, 1).Value) = Cells(i, 2).Value と書くこともできます。 」 という記述を見つけました。 試してみたところ Sub test01() Dim myDic As Object Dim myAr() Set myDic = CreateObject("Scripting.Dictionary") For i = 2 To 7 If Not myDic.exists(Cells(i, 1).Value) Then myDic.Add Cells(i, 1).Value, Cells(i, 2).Value End If Next i myAr() = myDic.Keys MsgBox Join(myAr()) End Sub Sub test02() Dim myDic As Object Dim myAr() Set myDic = CreateObject("Scripting.Dictionary") For i = 2 To 7 myDic(Cells(i, 1).Value) = Cells(i, 2).Value Next i myAr() = myDic.Keys MsgBox Join(myAr()) End Sub 上記2つのマクロは、Keyに関してはまったく同じ働きをするようです。 ところがItemに関しては、Keyが重複した場合、あとから出てきた方に上書きされるようです。 これはtest01では、Keyの重複を排除しているためItemは最初に出たものが残る、test02は重複の場合、無条件でKeyが上書きされ(ても値は変化しないけど)、したがってItemも上書きされるという理解でよろしいのでしょうか? ならば、Itemを気にしない場合、わざわざ If Not myDic.exists(Cells(i, 1).Value) Then myDic.Add Cells(i, 1).Value, Cells(i, 2).Value End If と、3行も費やして重複のチェックをしなくとも myDic(Cells(i, 1).Value) = Cells(i, 2).Value のわずか一行で済むということですよね?

質問者が選んだベストアンサー

  • ベストアンサー
  • n-jun
  • ベストアンサー率33% (959/2873)
回答No.3

#2です。 例えば、 >If Not myDic.exists(Cells(i, 1).Value) Then >myDic.Add Cells(i, 1).Value, Cells(i, 2).Value >End If の使い方としては、 If Not myDic.Exists(Cells(i, 1).Value) Then myDic(Cells(i, 1).Value) = Cells(i, 2).Value Else myDic(Cells(i, 1).Value) = myDic(Cells(i, 1).Value) + Cells(i, 2).Value End If のように ・キーがなければキーに値をセットする。 ・キーがあればそのアイテムに新しい値を加算していく。 と言った場合に、存在しないキーによるエラー回避の意味もあるでしょうか。

merlionXX
質問者

お礼

なんとItenの加算が出来るんですね! 文字列の場合は結合されるんですね!驚きました。 Sub test04() Dim myDic As Object Dim myAr(), myAr2() Set myDic = CreateObject("Scripting.Dictionary") For i = 2 To 7 If Not myDic.Exists(Cells(i, 1).Value) Then myDic(Cells(i, 1).Value) = Cells(i, 2).Value Else myDic(Cells(i, 1).Value) = myDic(Cells(i, 1).Value) + Cells(i, 2).Value 'Itemデータを加算 End If Next i myAr() = myDic.Keys myAr2() = myDic.Items MsgBox Join(myAr()) & vbLf & Join(myAr2()) End Sub

その他の回答 (3)

  • onlyrom
  • ベストアンサー率59% (228/384)
回答No.4

>test02は重複の場合、無条件でKeyが上書きされ(ても値は変化しないけど) >したがってItemも上書きされるという理解でよろしいのでしょうか? ちょこっと、否、だいぶ違うみたい。。。(^^;;; >myDic(Cells(i, 1).Value) = Cells(i, 2).Value これは、一体、何をしているのでしょう。 それは、 myDic.Item(Cells(i, 1).Value) = Cells(i, 2).Value のように、Itemプロパティが省略された形で キーのセットではなくて 既にキーに関連付けされた項目の変更をしていることになります。 キーが無いときはどうするのじゃ、と疑問が生じるでしょうが、 その場合には以下のようにちゃんとキーを作ってくれるのです。 「項目を変更するときに引数 key の値が見つからない場合は 引数 newitem で指定された項目(今回は右辺のCells(i, 2).Value) と関連付けられた新しいキーが作成されます」 ここら辺りはヘルプに詳しく書いてあります。 お暇なときには、ヘルプで遊びませう。。(^^;;;   以上です。  

merlionXX
質問者

お礼

こんばんは、onlyromさま。 いつもありがとうございます。 日本まけちゃいましたね、残念です。 myDic(Cells(i, 1).Value) = Cells(i, 2).Valueは キーがないときには新しいキーが作成され、あるときは既にキーに関連付けされたItemを変更するということですね。 よく分かりました。 ありがとうございます。

  • n-jun
  • ベストアンサー率33% (959/2873)
回答No.2

>Itemを気にしない場合、 >myDic(Cells(i, 1).Value) = Cells(i, 2).Value >のわずか一行で済むということですよね? キーに対して最終アイテムを必要としている場合ならOKでしょうね。 逆に最初のアイテムを必要とするのなら、 >test01では、Keyの重複を排除しているためItemは最初に出たものが残る こちらでしょうね。 それぞれは何を必要とするかで使い分けると思いますよ。 あくまで一例に過ぎないと思いますけど、ご参考になれば。

merlionXX
質問者

お礼

なるほど! 最終Itemか最初のItemのどちらが必要かで書き分けるべきなんですね! 理解しました。 ありがとうございました。

  • KenKen_SP
  • ベストアンサー率62% (785/1258)
回答No.1

> 3行も費やして重複のチェックをしなくとも Dictionary については、その通りです。ただ、好みとなっちゃうのかなぁ If Not dic.Exists(sKey) Then   dic.Add Key:=sKey, Item:=vbEmpty End If の方がソースとしてわかりやすい気がするけど。 Item を無視してよいなら多分、      dic(sKey) = vbEmpty の方が高速でしょう。

merlionXX
質問者

お礼

KenKen_SPさま、いつもありがとうございます。 dic(sKey) = vbEmpty とはItemには何も入れないという意味というように理解してよろしいでしょうか? Sub test03() Dim myDic As Object Dim myAr(), myAr2() Set myDic = CreateObject("Scripting.Dictionary") For i = 2 To 7 myDic(Cells(i, 1).Value) = vbEmpty Next i myAr() = myDic.Keys myAr2() = myDic.Items MsgBox Join(myAr()) & vbLf & Join(myAr2()) End Sub で試したら、Join(myAr2())が0の行列になりましたので。 > ソースとしてわかりやすい気がするけど。 確かにそうですね、myDic(Cells(i, 1).Value) = Cells(i, 2).Value って書いたら、後で見て自分でもわからなくなりそうです。 (^^;;