VBA-JSONを使ってる時にエラー「KeyNotFoundError」が発生して解決に結構時間がかかったので備忘半分で原因と解消方法まとめてみました
VBA-JSONは何って話はコチラから
ある日突然エラーが発生した
まずはエラーメッセージから
KeyNotFoundError
Dictionary key not found: <KeyName>
そのまま受け取るとDictionary型の変数にKeyが無いと
ピンと来る理由もないので実際のエラーソースを見てみる
実際のエラー発生箇所
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
実際にエラーになるのは27行目の部分
なにもおかしなソースではないし、そもそも今までエラーにならなかったし同じVBA-JSONを使っているのに急にエラーになってしまう理由がやっぱりわからない・・・
原因は「Dictionary」でした
まず前提としてDictionary型と言われると連想することは参照設定だと「Microsoft Scripting Runtime」のことを指すと思いますし、私も思ってました
が、実は「Selenium Type Library」の中にもDictionary型があったのです
つまり「Selenium Type Library」のDictionaryとして動作していたのでエラーになっていたわけです
解決方法
原因がわかれば対応方法は難しくなくて2パターンありますので状況に応じてお好きな方を
明示的に「Microsoft Scripting Runtime」のDictionaryとして宣言する
※※個人的にはコチラをおススメ※※
「Dictionary」を「Scripting.Dictionary」に置換してあげればOK
ちなみにVBA-JSONの中には別の箇所でも「Dictionary」の単語があってそこは置換すると別のエラーになるので「json_ParseObject」の型とそのソース内の1箇所だけを置換
Private Function json_ParseObject(json_String As String, ByRef json_Index As Long) As Scripting.Dictionary
Dim json_Key As String
Dim json_NextChar As String
Set json_ParseObject = New 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
参照設定の優先順位を変える
半分原因の話にもなりますが「Dictionary」と宣言した時に「Microsoft Scripting Runtime」側になるように優先順位を変えるだけ
あとがき
APIとSeleniumBasicを使ったスクレイピングを併用したツールを作った時にこんな落とし穴があるとは知らず、解決するのに半日かかりました・・・
同じエラーに嵌った人の助けになれば幸いでございます
コメント
Hi, i am a Brazilian guy who wants to thank you so much, thats help me a lot.
自分も同じエラーがかなり時間がかかっていたのですが、
こちらを見て一瞬で解決しました。
ありがとうございました。