Excel VBAでJSONを自動生成(フラット定義版)

vba

はじめに

  • シートに定義したフィールド名・型や値に基づいてJSONを生成するExcel VBAマクロを紹介します。
  • フィールド名は、”field1:field1-1:field1-1-1″等のように単一値でフラットに定義する想定です。(階層の区切り文字は既定で”:”としています。)
  • 動作確認した環境は次の通りです。
    OSWindows 10(64ビット)
    OfficeMicrosoft Office Professional Plus 2019
    (Microsoft® Excel® 2019 MSO (16.0.14228.20216) 32 ビット )
  • マクロを含むExcelファイルをGitHubで公開しています。
    こちらから直接ダウンロードすることもできます。
  • その他のサンプル

サンプルExcelシートの説明

  • Excelシート上に記載したフィールドや値をJSONに出力できます。
    「配列」(E列)、「型」(F列)を変更することで、JSONへの値の出力仕様を変更できます。JSONにコメントを出力したい場合、「コメント」(H列)欄を指定します。「説明」(D列)、「備考」(I列)は、管理用に設けられた項目で処理に影響しません。
  • JSON出力の例は次の通りです。
  • 詳細仕様
    • フィールドの型として文字列(“string”)、数値(“number”)、真偽(“boolean”)、null(“null”)型を想定しています。
    • 配列の指定がある場合、値をカンマで分割したものを値(指定された型を考慮)として使用します。
      例えば、配列・文字列型の値「123,456」は、「[“123”, “456”]」としてJSONに出力します。配列・数値型だった場合、「[123, 456]」としてJSONに出力します。
    • 文字列や数値型の配列出力は可能ですが、JSONオブジェクトの配列出力は対応していません。
    • 値が空のフィールドはスキップします。(ファイルへの出力対象外)

実現方式の説明

Excelのシートに定義されたフィールドの階層構造の解析(「フィールド定義の解析」)と、解析結果に基づいてJSONデータを作成する処理(「解析結果に基づいたJSONの生成」)に分割して実現しています。ここでは、実現方法の難易度が高めの「フィールド定義の解析」について説明します。

フィールド定義の解析方法

再帰関数を定義して階層構造を解析します。

  • 引数で指定された階層(ベースパス)にあるフィールドとその値等(フィールド定義)を抽出し、それらをリスト(フィールドリスト)として返却する再帰関数を定義します。
  • 下位階層を持つフィールドが現れた場合、下位階層(ベースパス)を指定して同関数を実行します。返却されたフィールドリストを値として、当該フィールドをフィールドリストに追加します。
  • フィールドが下位階層を持つかどうかは、ベースパス以降のパス(処理対象パス)に階層の区切り文字であるコロンが含まれるかどうかで判定できます。

データモデル

  • フィールド定義(フィールド名、型、値等)は、独自に定義したFieldDef型(クラス)に格納します。これらを格納するフィールドリストとしてCollection型を使用します。
  • 前節の階層構造に対応するデータモデルの例(主要プロパティのみ記載)を次に示します。
    フィールドの値が数値や文字列の場合、Valueプロパティにその値を設定します。下位階層があるフィールドの場合、Valueプロパティに下位階層のフィールドリスト、子のフィールドリストがあることを示すためのプロパティIsParentにtrue、を設定しています。

ソースコードの説明

メイン処理、フィールド定義の解析、JSONの生成処理について説明します。
完全なソースコードは、Excelファイルをダウンロードしてご確認ください。

参照設定

  • JSONをUTF-8形式でファイルに保存するために、”Microsoft ActiveX Data Objects 6.1 Library”を使用しています。[ツール] – [参照設定]で当該ライブラリを追加してください。

メイン処理

  • 後述の「フィールド定義の解析」「解析結果に基づいたJSONの生成」を実行します。
  • フィールド定義の解析結果はフィールドリスト(FieldDefs型を要素とするCollectionクラス)に格納しています。

フィールド定義の解析

  • フィールド定義の階層を再帰的に解析する関数を用意し、フィールドリストを生成します。
  • 処理対象となる階層を「ベースパス」、それ以降のフィールドを「処理対象パス」とします。
    例えば、フィールドが”field4:field4-2:field4-2-1″、ベースパスが”field4:”の場合、処理対象パスは”field4-2:field4-2-1″とします。
  • 解析の中核となる再帰関数ParseFields()では、処理対象パスに含まれるフィールド数に基づいて、次のように処理を分岐します。
    • フィールドの値の取得条件
      • 処理対象パスに単一フィールドのみを含む … 通常フィールドのため、「値」(G列)を値とする。
      • 処理対象パスに複数フィールドを含む … 再帰関数で取得したフィールドリストを値とする。
    • 関数の終了条件
      • フィールドがベースパスを含まない … 処理中の階層ではないので現在の関数実行を終了し、生成したフィールドリストを呼出元に返却する。(このフィールドリストが呼出元のフィールドの値になる。)
  • 再帰関数間での各種パラメータの引き渡しを簡略化するために、いくつかの変数はグローバル変数として宣言しています。
  • フィールド名を階層構造でなく1階層(フラット)で出力したい場合、定数IS_FLAT_JSONをTrueにします。(例えば、”field4:field4-2:field4-2-1″というフィールドを、そのまま”field4:field4-2:field4-2-1″というフィールド名としてJSONに出力したい場合。)

解析結果に基づいたJSONの生成

  • CreateJson関数で、フィールドリストを再帰的に辿って、フィールド・値をJSON形式で出力します。
  • このサンプルでは”//”形式のコメントを使用していますが、実行環境によってはエラーになる場合があります。コメントの出力を無効にする場合は定数OUTPUT_COMMENTの値をFalseにします。