[KeyNotFoundError] VBA-JSONのエラー原因と対策(VBA)
実行時エラー '0’:
KeyNotFoundError
Dictionary key not found: a
エラーメッセージ
久しぶりにVBA -JSONを使ったところ、画像のエラーが発生しました。
なお、以前に使ったときにはこのエラーが発生したことはありません。
もし、あなたも画像のエラーが発生しているようでしたら、十中八九同じ原因だと思います。
この記事を読めばエラー理由と解消法が分かりますので、順番に読んでみてください。
ちなみに、使用しているVBA-JSONは最新のVer.2.3.1です。(特にVer.は関係ありません)
[KeyNotFoundError] の発生箇所
Private Function json_ParseObject(json_String As String, ByRef json_Index As Long) As Dictionary
Dim json_Key As String
Dim json_NextChar As String
Set json_ParseObject = New Dictionary
json_SkipSpaces json_String, json_Index
If VBA.Mid$(json_String, json_Index, 1) <> "{" Then
Err.Raise 10001, "JSONConverter", json_ParseErrorMessage(json_String, json_Index, "Expecting '{'")
Else
json_Index = json_Index + 1
Do
json_SkipSpaces json_String, json_Index
If VBA.Mid$(json_String, json_Index, 1) = "}" Then
json_Index = json_Index + 1
Exit Function
ElseIf VBA.Mid$(json_String, json_Index, 1) = "," Then
json_Index = json_Index + 1
json_SkipSpaces json_String, json_Index
End If
json_Key = json_ParseKey(json_String, json_Index)
json_NextChar = json_Peek(json_String, json_Index)
If json_NextChar = "[" Or json_NextChar = "{" Then
Set json_ParseObject.Item(json_Key) = json_ParseValue(json_String, json_Index)
Else
json_ParseObject.Item(json_Key) = json_ParseValue(json_String, json_Index) ' ここでエラーが発生
End If
Loop
End If
End Function
KeyNotFoundErrorが発生しているのは、VBA -JSONのjson_ParseObjectというプロシージャ内です。
json_ParseObject.Item(json_Key) = json_ParseValue(json_String, json_Index) ' ここでエラーが発生
この代入しようとする部分でエラーとなります。
変数json_ParseObjectを確認したところ、エラーメッセージの通りでこのキーはありませんでした。
しかし、これはDictionary型の仕様ではエラーにならないはずです。
Object.Item(キー) = アイテム
Dictionary型でこのようなコードを書いたとき、次のように処理されます。
- キーが存在する: キーに紐づいたアイテムを再代入する
- キーが存在しない: 新たにキーを作成してアイテムを代入する
そのため、キーが存在しなくてもエラーにならないはずです。
よく分からず調べたのですが、原因は全く違う部分にありました。
[KeyNotFoundError]VBA-JSONのエラー原因
エラー原因ですが、これはSeleniumBasicをインストールしたことでした。
以前VBA-JSONを使ったときにはSeleniumBasicはインストールしていません。
実は、SeleniumにもDictionaryという型があります。
このDictionaryという同じ名前の型がエラー原因です。
SeleniumのDictionary型にもitemプロパティがあるのですが、Scripting RuntimeのDictionary型とは違い、キーが存在しないとエラーになります。
(先ほど説明した「新たにキーを作成してアイテムを代入する」の動作とはなりません)
VBA-JSONでは、ScriptingのDictionary型を使ったプログラムを書いているのですが、VBAがSeleniumのDictionary型と処理していたためエラーが発生していたのです。
[KeyNotFoundError]VBA-JSONのエラー対策
エラー対策はとても簡単です。
Dictionaryと書くと、SeleniumかScripting Runtimeか暗黙の指定となってしまうため、明示的に指定するだけです。
Private Function json_ParseObject(json_String As String, ByRef json_Index As Long) As Scripting.Dictionary 'Scripting.Dictionaryに変更
Dim json_Key As String
Dim json_NextChar As String
Set json_ParseObject = New Scripting.Dictionary 'Scripting.Dictionaryに変更
json_SkipSpaces json_String, json_Index
If VBA.Mid$(json_String, json_Index, 1) <> "{" Then
Err.Raise 10001, "JSONConverter", json_ParseErrorMessage(json_String, json_Index, "Expecting '{'")
Else
json_Index = json_Index + 1
Do
json_SkipSpaces json_String, json_Index
If VBA.Mid$(json_String, json_Index, 1) = "}" Then
json_Index = json_Index + 1
Exit Function
ElseIf VBA.Mid$(json_String, json_Index, 1) = "," Then
json_Index = json_Index + 1
json_SkipSpaces json_String, json_Index
End If
json_Key = json_ParseKey(json_String, json_Index)
json_NextChar = json_Peek(json_String, json_Index)
If json_NextChar = "[" Or json_NextChar = "{" Then
Set json_ParseObject.Item(json_Key) = json_ParseValue(json_String, json_Index)
Else
json_ParseObject.Item(json_Key) = json_ParseValue(json_String, json_Index)
End If
Loop
End If
End Function
具体的には、上のコードのようにjson_ParseObjectプロシージャ内の2か所のDictionaryをScripting.Dictionaryに変えるだけです。
これで、エラーは解消します。
ちなみに、参照設定で優先順位を変えることでも解決できます。
(とはいえ、明示的に指定する方がベターだと思います)
[参考]Selenium.Dictionaryのメソッド/プロパティ一覧
参考にSelenium.Dictionaryのメソッド/プロパティ一覧をお見せします。
キーが存在しない時に、アイテムを追加するためにはItemでなく、AddもしくはSetメソッドを使う必要があります。
メソッドorプロパティ | |
---|---|
Add | メソッド |
Clear | メソッド |
ContainsKey | メソッド |
Count | プロパティ |
Get | メソッド |
Item | プロパティ(既定) |
Keys | メソッド |
Set | メソッド |
ToExcel | メソッド |
Values | メソッド |
Scripting RuntimeのDictionaryと似たようなメソッドがありますが、名称がかなり異なっています。
VBA-JSONの使い方
VBA-JSONの使い方はこちらの記事をご覧ください。