ObjecTips

Swift & Objective-C で iOS とか macOS とか

AppleScript の JavaScript for Automation で Excel から JSON ファイルを作成する

これまでの記事

これらを組み合わせて Excel のシートから JSON ファイルを作成するという事をやってみる。

例として以下の様なシートを用いる。

f:id:Koze:20150825232606p:plain

一応シートのデータも Gist にアップした。
sample data

セルの内容を取得して配列化する

まずアプリケーションの取得を行い、Excel の worksheet の取得を行う。

app = Application('Microsoft Excel');
worksheet = app.worksheets['Sheet1'];


シートの一番上の行は列の内容を表すタイトル部分になっているので、表の内容取得はインデックス1の行(2行目)からループ処理で row を順番に取得してくようにする。

for (rowIndex=1; ; rowIndex++) {
  row = worksheet.rows[rowIndex];
}


上のコードだとループから抜けられないので、A列のセルの値が空であればループを抜けるようにしておく。

for (rowIndex=1; ; rowIndex++) {
  row = worksheet.rows[rowIndex];
  name = row.columns[0].value();
  if (!name) {
    break;
  }
}


そしてA列のセルの値があれば、その行の columns の内容を取得し、オブジェクトを作成する。

for (rowIndex=1; ; rowIndex++) {
  row = worksheet.rows[rowIndex];
  name = row.columns[0].value();
  if (!name) {
    break;
  }

  inch = row.columns[1].value();
  scale = row.columns[2].value();
  colors = row.columns[3].value().split(','); 
  dict = {
    'name': name,
    'inch': inch,
    'scale': scale,
    'colors': colors,
  };
}

この時、A, B, C列は文字列か数値が1つ入力されている想定で、D列はカンマ区切りで複数の値が入力されている想定なので、D列の colors については

split(',');

でカンマ区切りで分割して配列として値を取得している。

最後に作成したオブジェクトをあらかじめ用意しておいた配列に追加して各行の内容を配列化していく。
JavaScript では配列への要素の追加は push() で行う。

array = [];

for (rowIndex=1; ; rowIndex++) {
  row = worksheet.rows[rowIndex];
  name = row.columns[0].value();
  if (!name) {
    break;
  }

  inch = row.columns[1].value();
  scale = row.columns[2].value();
  colors = row.columns[3].value().split(','); 
  dict = {
    'name': name,
    'inch': inch,
    'scale': scale,
    'colors': colors,
  };
  array.push(dict);
}
JSONに変換する

配列やオブジェクトをJSONのテキストに変換するには以下のようにする。

text = JSON.stringify(array);

stringify() のオプションの第3引数には spacer を指定する事ができ、空白、改行、タブ等でインデントを付けてJSONを整形できるので、今回はそれを使って半角空白2文字でインデントを付ける事にする。

text = JSON.stringify(array, null, '  ');
テキストをファイルに保存する

以前の記事と同じ方法を用いる。

filePath = app.chooseFileName({
  defaultName: 'Untitled.json',
  defaultLocation: app.pathTo('desktop')
});
string = $.NSString.stringWithString(text);
string.writeToFileAtomically(filePath.toString(), true);

保存ダイアログの表示には StandardAdditions の機能を使うので

app.includeStandardAdditions = true;

を忘れず指定しておく。
また、Objective-C も使っているので

ObjC.import('Cocoa')

も記述しておく。

まとめ

Excel で管理されているデータをアプリで利用する際にこれまでは
Excel > CSV > parse して plist or JSON
という手順を踏んでいて、CSVへの変換は Excel の機能で行い CSV の parse と plist or JSON への変換は簡単なMacアプリを作って行っていた。
このフローでは Excel ファイルが更新される度に手作業でのCSV変換とMacアプリでの変換を行っていたのが今回の AppleScript での実装によって一発で目的のファイルに変換できるようになった。
変換処理のロジックの変更も JavaScript に手を入れるだけで良いし、Macアプリを再ビルドする必要も無い。
AppleScript なのでアプリケーションやフォルダアクションにしておいたり、指定ファイルを開くスクリプトを追加して Xcode のビルド時に走らせたり自動化にも大いに利用できると思う。

コード全体と出力結果