[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『Dictionaryオブジェクトの重複エラーについて』(まじっく)
DictionaryオブジェクトのAddメソッドを実行した際に、以下のKeyの重複エラーが出てしまうのですが、原因がわからずに困っております。
実行時エラー’457′:
このキーは既にこのコレクションの要素に割り当てられています。
やりたいこと:KeyとItemを入力したリストファイルから、ADO接続でKeyとItemを取得してDictionaryに登録する。
リストファイルは以下のパスと内容でSheet1のワークシートに保存されているものとします。
"C:\list.xlsx"
Sub listからDictionaryに登録()
Dim CN As New ADODB.Connection Dim RS As New ADODB.Recordset Dim SQL As String Dim Dic As New Dictionary
With CN .Provider = "Microsoft.ACE.OLEDB.12.0" .Properties("Extended Properties") = "Excel 12.0;HDR=Yes" .Open "C:\list.xlsx" End With
SQL = "SELECT * FROM [Sheet1$]" RS.Open SQL, CN, adOpenKeyset, adLockReadOnly Do Until RS.EOF 'Debug.Print RS.Fields("Key") & " " & RS.Fields("Item") Dic.Add RS.Fields("Key"), RS.Fields("Item") RS.MoveNext Loop
RS.Close Set RS = Nothing CN.Close Set CN = Nothing
End Sub
原因がわかりましたら、ご教示いただけると幸いです。
よろしくお願いいたします。
< 使用 Excel:Excel2019、使用 OS:Windows10 >
(とおりすがり) 2022/03/01(火) 11:04
なお、キーが重複していると、その書き方ではエラーになりますよ。
事前に Existsを使った存在確認が必要です。
もしくは、下記の書き方ならエラーにならず上書きされます。
Dic(RS.Fields("Key").Value) = RS.Fields("Item").Value
#かぶりましたが、そのまま。
(γ) 2022/03/01(火) 11:14
解決いたしました!!
レコードの値の取得にvalueが必要という認識がなく、いままでやってきておりました。
大変勉強になりました。
ご教示いただきありがとうございました。
(まじっく) 2022/03/01(火) 11:21
余談です。(関連性はあります)
(1) よくある話で、似た話があります。
Sub test2() Dim dic As Object Set dic = CreateObject("Scripting.Dictionary") For k = 2 To 3 dic.Add Cells(k, 1), Cells(k, 2) Next End Sub を、下記のデータを使って動作させると、どうなると思いますか? A B 1 Key Item 2 AAA あああ 3 AAA いいい
AAAが重複しているので、エラーになる、と思いきや、エラーにはなりません。
なぜなら、dictionaryに与えたキーは、 値ではなく、Rangeオブジェクトなので、 Addressなども違うし、同一ではないのでエラーにならず、 結果として二つのキーを持った辞書ができてしまうわけです。 また、dic("AAA")などとしても結果は返って来ないのです。
したがって、この場合もきちんと.Value(または.Text)を付ける必要があります。 これは比較的よく出てくる話ですね、というTipsのご紹介。
(2) で、質問にあったケースで、 Dic.Add RS.Fields("Key"), RS.Fields("Item") についても同じようにオブジェクトとして認識されるなら 問題ないのではと、一見すると思います。
しかし、最初に登録したkey,itemは、 RS.MoveNext でカーソルを変えたときに、それに伴って動いてしまうわけです。 そして、再度、 Dic.Add RS.Fields("Key"), RS.Fields("Item") とやると、まさにキーが一致してしまって同じオブジェクトと判定されてしまうわけです。
(γ) 2022/03/01(火) 12:24
Dictionaryを使う際に、セルから値を取得する時は.Valueをつけておりましたが、
ADOで取得したレコードの取り扱いに慣れていなかったもので、.Value を付ける認識がありませんでした。
おかげさまで、ループの2回目でエラーになった原因がよくわかりました。
追加コメントありがとうございました。
(まじっく) 2022/03/01(火) 12:49
RS.Fields("Key")にアクセスしたときに、
カーソルの位置によって返ってくる値は変わるものの、
もともとRS.Fields("Key")というインスタンスは一つしかないので、
普通に「重複してしまう」ということでよかったと思います。
(Range("A2")とRange("A3")は元々違うインスタンスでした。これはまた違う話。)
>カーソルを変えたときに、それに伴って動いてしまうわけです。
というのも変で、即時的に変わるのではなく、値を取りに行ったときに変わるものでした。
妙なことを申し上げて失礼しました。
(γ) 2022/03/01(火) 14:40
[ 一覧(最新更新順) ]
YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki.
Modified by kazu.