Excel (VBA)

Excel VBAに関するフォーラムです。
  • 解決済みのトピックにはコメントできません。
このトピックは解決済みです。
質問

 
(Windows 10 Pro : Excel 2016)
VBA-JSONの使い方
投稿日時: 21/11/06 22:11:26
投稿者: ケンタ0241

VBAでUTF-8のJson(Geojson)ファイルをVBA-JSON(JsonConverter)を使ってParseしようとしています。
最上層のカウントとKeyは取得できている様なのですが、2層目は、以下のメッセージが出てKeyの取得でエラーになります。
「実行時エラー '438' オブジェクトは、このプロパティ又はメソッドをサポートしていません。」
Dictionary型について知識がなく、原因と対応について教えていただければ有難いです。
よろしくお願いします。
 
-----------エラーの出るモジュール-----------------
Option Explicit
Public Sub Gejson入力test()
Dim Geojson As String
'Dim Key As Variant
Dim JSON_FILE As String
'JSONファイルの指定
JSON_FILE = "C:\UsersXXXXXXXXXXXXXXXXXXX\テスト用サンプル01.geojson" 'JSONのロード
Geojson = ReadUTF8Text(JSON_FILE)
 
' Dictionaryオブジェクトの宣言
Dim FeatureCollection As Object: Set FeatureCollection = CreateObject("Scripting.Dictionary")
 
Set FeatureCollection = JsonConverter.ParseJson(Geojson)
' 最上層のプリント
    Debug.Print "Count=" & FeatureCollection.Count
    Dim arkeys, vKey
    arkeys = FeatureCollection.Keys
    For Each vKey In arkeys
        Debug.Print "vKey=" & vKey
    Next
' 2層目のプリント
    Debug.Print "Count=" & FeatureCollection("features").Count
    arkeys = FeatureCollection("features").Keys  ' ここでエラーになります。
    For Each vKey In arkeys
        Debug.Print "vKey=" & vKey
    Next
End Sub
 
-----入力Jsonファイル-------------
{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "name": "植栽工事",
        "内容": "車線規制",
        "_color": "#FFFF00",
        "_opacity": 0.5,
        "_weight": 15
      },
      "geometry": {
        "type": "LineString",
        "coordinates": [
          [
            139.748057,
            35.678318
          ],
          [
            139.749148,
            35.677103
          ],
          [
            139.749293,
            35.676877
          ],
          [
            139.749091,
            35.676888
          ],
          [
            139.748819,
            35.676834
          ],
          [
            139.748554,
            35.676803
          ],
          [
            139.748175,
            35.676692
          ],
          [
            139.747667,
            35.676601
          ],
          [
            139.747129,
            35.6765
          ]
        ]
      }
    },
    {
      "type": "Feature",
      "properties": {
        "name": "公園整備工事予定",
        "内容": "剪定",
        "_color": "#3388ff",
        "_opacity": 0.5,
        "_weight": 5,
        "_fillColor": "#FF0000",
        "_fillOpacity": 0.2
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [
              139.749219,
              35.67624
            ],
            [
              139.749091,
              35.676484
            ],
            [
              139.747138,
              35.676118
            ],
            [
              139.747696,
              35.674357
            ],
            [
              139.747846,
              35.67441
            ],
            [
              139.749219,
              35.67624
            ]
          ]
        ]
      }
    }
  ]
}
-----------------------------------------------
 
------イミディエイト・ウィンドウの内容----------
Count=2
vKey=type
vKey=features
Count=2
 

回答
投稿日時: 21/11/07 00:14:39
投稿者: simple

引用:
arkeys = FeatureCollection("features").Keys  ' ここでエラーになります。

FeatureCollection("features")は、
2つのDictionaryを要素に持つCollectionです。
それには、Keysというメソッドもプロパティもありません。
とりあえず、エラーの理由だけ書いておきます。

投稿日時: 21/11/07 04:40:09
投稿者: ケンタ0241

返信ありがとうございます。
ご指摘を参考にして、モジュールを以下のように修正したところ、Keyが取得できました。大いに助かりました。
Option Explicit
Public Sub Gejson入力test()
Dim Geojson As String
'Dim Key As Variant
Dim JSON_FILE As String
Dim features数 As Integer
'JSONファイルの指定
JSON_FILE = "C:\XXXXXXXXXXXXXXXXXXX\テスト用サンプル01.geojson" 'JSONのロード
Geojson = ReadUTF8Text(JSON_FILE)
’Debug.Print Geojson
 
' Dictionaryオブジェクトの宣言
Dim FeatureCollection As Object: Set FeatureCollection = CreateObject("Scripting.Dictionary")
 
Set FeatureCollection = JsonConverter.ParseJson(Geojson)
' 最上層のプリント
    Debug.Print "Count=" & FeatureCollection.Count
    Dim arkeys, vKey
    arkeys = FeatureCollection.Keys
    For Each vKey In arkeys
        Debug.Print "vKey=" & vKey
    Next
' 2層目のプリント
 
features数 = FeatureCollection("features").Count
    Debug.Print "Count=" & FeatureCollection("features").Count
    For i = 1 To features数
        arkeys = FeatureCollection("features")(i).Keys
        For Each vKey In arkeys
            Debug.Print "vKey=" & vKey
        Next
    Next

End Sub
 
---------------イミディエイトウィンドウの内容----------------
Count=2
vKey=type
vKey=properties
vKey=geometry
vKey=type
vKey=properties
vKey=geometry
--------------------------------------------------------------

回答
投稿日時: 21/11/07 16:14:56
投稿者: simple

解決されたようで何よりです。
閲覧されているかたに向けたメモを、ついでに追記しておきます。
 
JSONはデータフォーマットの一種です。今やXML以上に使われているようです。
https://developer.mozilla.org/ja/docs/Learn/JavaScript/Objects/JSON
[]で配列、{}でHash(Dictionary)を表すので、人間にとっての可読性も高い。
(下記余談(1)参照)
 
・ReadUTF8Text
https://qiita.com/tokibisuki/items/82e46bf48edd183c91f8
なんだろうか。VBA組み込みのプロシージャでもないので、簡単な紹介が必要。
Microsoft ActiveX Data Objects Libraryの参照設定が必要。(versionは 6.1 が適当)
・VBA-JSON(JsonConverter)
有名なConverterです。VBAでJsonデータを扱うにはこの一択でしょう。
https://github.com/VBA-tools/VBA-JSON
Microsoft Scripting Runtimeの参照設定が必要。
 
昔は、ScriptControlを経由してJScriptを使う方法だった。(下記余談(2)参照)
今では64bitでは動作しないこともあり、VBA-JSONを使うのが定番のようです。
https://qiita.com/emesh/items/0834a5ad373d2ade6a93
あたりに説明があります。
自力で書くには煩雑にすぎるので、このツールを使用するのがいいですね。
 
========
余談(1)
https://www.moug.net/faq/viewtopic.php?t=80987
で紹介されているWebDriverも、データのやり取りをJsonで行っています。
一般ユーザーが日常的に使うものではありませんが、
テキストベースの情報交換手段としてはかなり一般的なもののようです。
  
余談(2)
JavaScriptを念頭に置いたデータフォーマットなので、JScriptとの相性がよい。
2009年1月にGoogle AJAX Search APIで取得したJsonをVBAの配列等に読み込む例を
こちらの掲示板で書いた覚えがある。
ScriptControlを経由してJScriptを使う方法を使用したが、
当時はまだそうした使用例はネットでも見なかった気がします。
JSON VBAで検索してもほとんどヒットする記事はなかった気がする。

投稿日時: 21/11/07 16:48:44
投稿者: ケンタ0241

ご丁寧に有り難うございました。