はじめに
超初心者DTPオペレータのExtendScript練習帳です。
主にInDesignで動く小さなものを書いていきます。
勉強中のメモとして書き残しています。
掲載しているスクリプト・情報は、誤った記述を含む可能性があります🙇
ルール📖
- 週に1つつくる
- 未完成のものもそこで区切る
目的🎯
- ExtendScriptに慣れる
- フローチャート作成に慣れる
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
文は、ユーザー定義の例外を発生させます。現在の関数の実行は停止し(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 0
かtypeof a === 'undefined'
を使おうと思います。
その他
- includeはエイリアスは読みこんでくれない。
- デスクトップはパスで指定せずとも
Folder.desktop
でOK。 - 引数の名前を
char
としようとしたら「予約語だからだめ」と怒られた。予約語なんですね。 - Excelデータをタブ区切りテキストとして保存すると、カンマが入っている場合にダブルコーテーションで囲まれる。カンマ区切りじゃないのに。
- xlsxデータは
File.read()
できない。exclude()
で開くことはできる。
参考
- JavaScriptでCSVデータ(項目行あり)をJSON形式に変換する | Try Lifelog
- CSV文字列をJSONオブジェクトに変換 | JavaScript逆引き | Webサイト制作支援 | ShanaBrian Website
- [JavaScript] CSVテキストを配列に分割する。「","」「"改行"」対応 - Qiita
- 【JavaScript】エラー処理 完全ガイド
- delimiter / separator / divider の違い - codic ブログ 変数名の参考にした。
- 「テーブル」「レコード」「カラム」「フィールド」とは? 変数名の参考にした。
追記
ExtendScriptでのjsonファイルの読み込みについて、後日ひとつ学びがあったので追記。
「ExtendScriptのオブジェクトとしてそのまま読めるようなjsonファイルであれば、
var hoge= #include "hoge.json"
とするだけで、変数hogeにhoge.jsonをパースしたオブジェクトが入ります。」
便利!
さらに追記
dataはMapにした方が安全かもしれない。
(2022/05/09)
ExtendScriptにおける三項演算子の不具合(?)
追記(2021/10/26)
var x = 30;
— あるふぁ(仮) (@peprintenpa) 2021年10月25日
var z = (x < 10) ? 'a' :
(x < 50) ? 'b' :
'c';
$.writeln(z); // => b これは問題無し
これが正しいのはたまたまですね。x=5とかだとおかしくなる。
こういうネタ集めて記事にしてるのでぜひ読んでみてくださいhttps://t.co/Hrb1WQO9HY
— あるふぁ(仮) (@peprintenpa) 2021年10月25日
2つ目のツイートでご紹介いただいているのはこちらの記事です。 sysys.blog.shinobi.jp
また、Uske-Sさんが詳しく検証・解説してくださっています!
私が投稿した以下の文章には誤りが含まれますので、正しい情報をお探しの方はこちらの記事をご覧になることをおすすめします。
(2021/10/26)
ExtendScriptでは、三項演算子を入れ子にするとシンタックスエラーになります。
var x = 30; var y = (x > 10) ? (x < 50) ? 'a' : 'b' : 'c'; $.writeln(y); //条件1・2ともtrueなので"a"になるはずだが、Syntax Errorになる
これについてはフォーラムで解説されています。
それとは別に、よく分からない挙動に行きあったので記録しておきます。
簡単に述べると、別の書き方で入れ子にしたときに、エラーを出さずに誤った値が返されることがあるようです(私が何か誤解しているのでなければ…)。
var x = 30; var z = (x < 10) ? 'a' : (x < 50) ? 'b' : 'c'; $.writeln(z); // => b これは問題無し //Google Chrome デベロッパー・ツールでは //console.log(z); => b var zz = (x < 10) ? 'aa' : (x < 50) ? 'bb' : (x < 90) ? 'cc' : 'dd'; $.writeln(zz); // => cc これは誤り //Google Chrome デベロッパー・ツールでは //console.log(zz); => bb var zzz = (x < 10) ? 'aaa' : (x < 50) ? 'bbb' : (x < 90) ? 'ccc' : (x < 120) ? 'ddd' : 'eee'; $.writeln(zzz); // => ddd これは誤り //Google Chrome デベロッパー・ツールでは //console.log(zzz); => bbb
最初にご紹介したフォーラムのスレッドには、
there seems to be some differences in operator precedence in ExtendScript vs. modern JavaScript versions
(ExtendScriptと最新のJavaScriptバージョンでは、演算子の優先順位にいくつかの違いがあるようだ)
とあります。
もしかしたらこのことが関係しているのかもしれません。
個人的には三項演算子を使うことはほとんどありません。
他の方が作成されたスクリプトを読むときのために、心に留めておこうと思います。
参考
078.【Acrobat】注釈の外観・プロパティを統一する
概要
「複数人で校正・校閲してPDFに注釈を入れたため、作成者や色がバラバラになっている。著者に送る前に統一したい」というケースを想定しています。
次の処理を行います。
- 注釈の作成者名を「XXXX」に統一
- ハイライト注釈の色と不透明度を統一
- 図形注釈の線の色と太さを統一
- コメントが「著者問い合わせ」で始まっていたら「【確認】」に置き換える
- コメントが「【確認】」で始まっていなかったら加筆
使い方
- PDFをAcrobatで開く
- AcrobatのJavaScriptデバッガを開く(Windowsの場合Ctrl+J)
- コンソールにスクリプトをペーストする
- 全選択してCtrl+Enterを押す
コード
メモ
分からなかったこと
テキストボックス注釈のstrokeTypeを変更すると、中の文字の色まで変わってしまう。
外枠の色だけ変えたい。
参考
- 解決済み: Acrobat Pro DCの注釈の作成者の一括変更 - Adobe Support Community
注釈の作成者を一括変更したいという投稿。こちらでは「注釈データを書き出して、テキストエディタで検索・置換してから取り込みなおす」という方法が紹介されています。
GitHubやAdobeフォーラムでコード以外の箇所だけ日本語翻訳する方法
Webサイト上で外国語の文章を読む際は、コンテクストメニューからGoogle日本語翻訳を行っています。
素のままのChromeでこれを行うと、コードブロック内も翻訳されてしまうという難点があります。
「ScriptAutoRunner」というChrome拡張で解決できるので手順を記録しておきます。
ScriptAutoRunnerとは
Chromeの拡張機能。
指定したサイトを開くたびに任意のjavascriptを実行します。
設定
①部分をクリックします。
②実行内容のタイトルを入力します。
③実行内容を入力します。
・Adobeフォーラム、GitHub、Indiscriptsの場合
Array.prototype.forEach.call(document.getElementsByTagName('pre'), x => x.classList.add('notranslate'))
・Gistの場合
Array.prototype.forEach.call(document.getElementsByClassName('js-gist-file-update-container js-task-list-container file-box'), x => x.classList.add('notranslate'))
④実行するサイトのホストを入力します。
・Adobeフォーラム、GitHub、Indiscriptsの場合
community.adobe.com, github.com, indiscripts.com
・Gistの場合
gist.github.com
⑤プラグをクリックし、有効にします。
参考
- 【JavaScript】要素の取得方法(getElement、querySelector) - Qiita
コードブロックの部分を特定する処理を書く際に参考にしました。
077.【Id】ドキュメントを開くときに毎回リンクをチェックする
概要
スタートアップスクリプトとして実行することで、ドキュメントを開くたびにリンクの状態とパスをチェックするように設定します。
下記の状態が検出された場合は、ドキュメントがあるフォルダにテキストを書き出します。
- リンク切れ
- パスにアクセスできない
- リンクの更新が必要
- リンク先がドキュメントの同階層の(L|l)inks*フォルダ内でない
使い方
- アプリケーションの📁Scripts内に「Startup Scripts」という名前のフォルダを作成します。
- InDesignが起動していない状態で📁Startup Scriptsに当該jsxを保存します。
- InDesignを起動します。
- 以降は、特に何もせずともドキュメントを開くたびにリンクチェックの処理が実行されます。
結果表示
- リンクが正常の場合
- リンクに不備がある場合
(自動でテキストエディタが立ち上がります)
- indtや別バージョンのinddを開いた場合
コード
参考
- AdobeCCアンソロジー2「作業効率編」 - BOOTH
- 007.【ID】リンク先が同階層のLinkフォルダ内でなかったらアラート - コモノExtendScript100本ノック
- 069.【Id】作業時間を記録する - コモノExtendScript100本ノック
追記(2021/09/16)
リンクファイル名に半角パーレンが含まれていてうまくいかない例に遭遇した。
おそらくメタ文字があることでtest()の結果が意図しないものになったのだと思う。
まだ確認できていないけれど、とりあえずFIXMEを追加した。
076.【Id】別のinddからフォームフィールドを読み込む
挙動
ダイアログに従って、
1. 読み込み元のindd
2. 読み込み先のindd
を選択すると、1のinddに含まれるラジオボタン・チェックボックス・テキストフィールドが、2のinddに読み込まれる。
(タブオーダーは変わってしまう)
コード
メモ
読み込んだ後はタブオーダーがめちゃくちゃになっているので、タブオーダーを並べかえるスクリプトを使用したりする。