コモノExtendScript100本ノック

超初心者のDTPオペレーターが週にひとつスクリプトを書くブログ

079.【Id】タブ区切りテキストのテーブルをJSON形式(っぽい配列)にする

タブ区切りの文字列をJSON形式(っぽい配列)にする関数です。
事前にタブ区切りのtxtデータを読み込んでから実行することを想定しています。
生成した配列を使ってInDesignで自動組版したり、JSONファイルを作成して他のアプリケーションに渡したりするために作りました。
指定した行をヘッダーとして扱い、それより上の行はスキップします。

引数

書名:   令和3年度 論文集           
                
ページ番号 氏名  学年  学籍番号    写真ファイル名
14  田中一郎    1   1111    1111.psd
16  田中二郎    2   2222    2222.psd
18  田中三郎    3   3333    3333.psd
32  田中四郎    4   4444    4444.psd

戻り値

[
  { ページ番号: '14', 氏名: '田中一郎', 学年: '1', 学籍番号: '1111', 写真ファイル名: '1111.psd' },
  { ページ番号: '16', 氏名: '田中二郎', 学年: '2', 学籍番号: '2222', 写真ファイル名: '2222.psd' },
  { ページ番号: '18', 氏名: '田中三郎', 学年: '3', 学籍番号: '3333', 写真ファイル名: '3333.psd' },
  { ページ番号: '32', 氏名: '田中四郎', 学年: '4', 学籍番号: '4444', 写真ファイル名: '4444.psd' },
];

コード

メモ

例外処理

throw - JavaScript | MDN

throw 文は、ユーザー定義の例外を発生させます。現在の関数の実行は停止し(throw の後の文は実行されません)、
コールスタック内の最初のcatchブロックに制御を移します。呼び出し元の関数にcatchブロックが存在しない場合は、プログラムが終了します。

→関数内でエラーを投げると以降の処理がなされないので、ファイルを開いたあとclose()する前にエラーを投げないようにする。
→関数でエラーを投げる場合は、必ずtry/catch/finallyとともに呼び出す。

CSV

CSVにも対応したかったのだけど、結構めんどうそう。
フィールド内にカンマやダブルコーテーションが含まれていた場合を考えると、単純にsplit(',')ではうまくいかない。

デフォルト引数

function txt2json(str, separator, header = 0) {...のように記述することで、関数の定義時に引数にデフォルト値を設定することができる。
該当の引数が渡されなかった場合や undefined が渡された場合にこの値が用いられる。
この仕様はES2015(ES6)からサポートされている。
つまりES3準拠であるExtendScriptでは使えない。

代わりに今回は var header = header || 0; という書き方をした。
あとになって、こういった場合の理想の書き方はどないなもんか気になり、デフォルト引数を使用した関数をTypeScriptで書いてコンパイルしてみた。

//default_arg_test.ts
function default_arg_test (a = 0) {
  const res = a;
  return res;
}
const output = default_arg_test()
$.writeln(output); //0

これが

//default_arg_test.js
"use strict";
function default_arg_test(a) {
    if (a === void 0) { a = 0; }
    var res = a;
    return res;
}
var output = default_arg_test();
$.writeln(output); //0

こうなる。
if (a === void 0) { a = 0; } が今回知りたかったところ。
void演算子は必ずundefinedを返す演算子
なぜa === 'undefined'で判定するよりよろしいかというと、undefinedが書き換え可能であるから(少なくともES3においては)。

var a

$.writeln(a) //undefined

$.writeln(a === undefined) //true
$.writeln(a === void 0)    //true

var undefined = "test" //書き換えると…

$.writeln(a === undefined) //false!!
$.writeln(a === void 0)    //true

(ES5.1以降ではグローバルなundefinedは書き換え不可となっているようです)
今後はa === void 0typeof a === 'undefined'を使おうと思います。

その他

  • includeはエイリアスは読みこんでくれない。
  • デスクトップはパスで指定せずともFolder.desktopでOK。
  • 引数の名前をcharとしようとしたら「予約語だからだめ」と怒られた。予約語なんですね。
  • Excelデータをタブ区切りテキストとして保存すると、カンマが入っている場合にダブルコーテーションで囲まれる。カンマ区切りじゃないのに。
  • xlsxデータはFile.read()できない。exclude()で開くことはできる。

参考

追記

ExtendScriptでのjsonファイルの読み込みについて、後日ひとつ学びがあったので追記。

sysys.blog.shinobi.jp

ExtendScriptのオブジェクトとしてそのまま読めるようなjsonファイルであれば、

var hoge=
#include "hoge.json"

とするだけで、変数hogehoge.jsonをパースしたオブジェクトが入ります。」

便利!

さらに追記

dataはMapにした方が安全かもしれない。

(2022/05/09)