【VBA】VBA-JSONで「KeyNotFoundError」エラーが発生する

本ページはプロモーションが含まれています

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型があったのです

「Microsoft Scripting Runtime」のDictionary
「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を使ったスクレイピングを併用したツールを作った時にこんな落とし穴があるとは知らず、解決するのに半日かかりました・・・

同じエラーに嵌った人の助けになれば幸いでございます

コメント

  1. Ricardo より:

    Hi, i am a Brazilian guy who wants to thank you so much, thats help me a lot.

  2. はまちゃn より:

    自分も同じエラーがかなり時間がかかっていたのですが、
    こちらを見て一瞬で解決しました。
    ありがとうございました。

タイトルとURLをコピーしました