DocumentオブジェクトとDocumentsオブジェクトは別物

某印刷会社で自動組版を教えている関係上、InDesign JavaScriptの基礎的なところの資料を確認することがあります。教える立場になって改めて見返してみると、Adobeの資料「ADOBE INDESIGN CS6 スクリプティングチュートリアル(InDesign_ScriptingTutorial_JP.pdf)」は、誤植もあって理解しにくいけれど、現状では一番の教科書だなあと再認識しています。

これとは反対に困っているのが、中途半端な理解のままソースコードを公開しているサイト。先日も課題を出したら、Webで見たと言って次のようなコードを書いてきた。

var doc=app.open("xxxxxx.indd");
var myDocu=app.activeDocument;

あのう、変docと変myDocuは同じものを指しているんですけど。これだと変数1個分余計にメモリを消費しているだけなんだが……

ということで確認のためいくつかサイトを見てみると

myDoc = app.documents.add();
app.activeDocument.pages[0](以下省略)
app.documents[0].paragraphStyleGroups(以下省略)

これ、変myDocとapp.activeDocumentとapp.documents[0]はすべて同じものを指しているではないですか。それなら

myDoc = app.documents.add();
myDoc.pages[0](以下省略)
myDoc.paragraphStyleGroups(以下省略)

って書きましょうよ。変数の意味ちゃんと分かってる?

みたいなところが散見されて、さあ困った。どうしたもんかね。(それでも作れてるのは逆にすごい。効率の悪さなんてものともしないパワーがあるんでしょうね)


そんなこんなでいろいろ見ていると、あれ、もしかしてこの人、コンテナという概念知らないんじゃない? ということでここから本題。

コンテナ(ウィキペディア)

コンテナVBではコレクションオブジェクトと言います。「ADOBE スクリプティング入門(Adobe Intro to Scripting.pdf)」ではコレクションオブジェクト(p13、p20)またはコレクション(p14)って書いてあります。

図示して一番わかるのPDFExportPresetsオブジェクトかしら。

このパネル自体PDFExportPresetsオブジェクト(コレクションオブジェクト)、表示されている[プレス品質]などのプリセットPDFExportPresetオブジェクト、とみることができます)

つまり、コレクションオブジェクトとは、同じ種類のオブジェクトのリストである、という理解でいいと思います。

InDesign JavaScriptで「新しいドキュメントを作成する」という命令があります。

var doc = app.documents.add();

この文は非常によく使われますが、実は次の2つの文に分けることができます。

var docCo = app.documents;
var doc = docCo.add();

docCoはDocumentsオブジェクトです。Documentオブジェクトのリストを保持しているコレクションオブジェクトになります。このオブジェクトadd()メソッド(新しくメンバーを追加する)を実行することにより、新しいドキュメントが作成され、メソッドの結果として追加されたオブジェクト(Documentオブジェクト)が返されます。返されたオブジェクトを変docに代入しているというわけですね。

ここで非常に申し訳ないのですが、私のオブジェクトモデル(ツリー図)ではコレクションオブジェクトを省略しています。ただでさInDesignはオブジェクトの数が多い上、コレクションオブジェクトはプロパティ・メソッドがほとんど変わらない、parentプロパティを辿ってツリー図を作成したためコレクションオブジェクトは飛ばされた、などの理由があるのですが、これが理解不足に繋がってしまったのかも知れません。(次回作成するときはもう少し分かりやすくします)


JavaScriptを始めるまでは主VBScriptを書いていたので、コレクションオブジェクトは当たり前のこととして捉えていたのですが、JavaScriptおよHTML DOMには、コレクションオブジェクトという概念が存在しません。そのため、JavaScriptしか知らない、まHTMLから流れてきた人にとっては理解し難い概念なのかも知れません。

InDesignに限らず、IllustratorMicrosoft Officeでもコレクションオブジェクトを使用しています。Excelが比較的単純で身近な存在なので、そのオブジェクトモデルを例にします。

Application(Excel Application)
┗Workbooks(ブックのコレクション)
 ┗Workbook(ブック)
  ┗Worksheets(ワークシートのコレクション)
   ┗Worksheet(個々のワークシート)
    ┗Cells(セルのコレクション)
     ┗Cell(個々のセル)

アプリケーションの下に開いているドキュメント(ブック)のリストがあります。そのリストにある特定のブックを指定する場合

Workbooks.item(1)

のように番号で指定することができます。itemは既定のプロパティなので省略することができ、その場合に

Workbooks[1]

と記述します。以下同様にシート、セルと辿って目的のオブジェクトにたどり着くことができます。その道を図式化したものがオブジェクトモデル図になります。

ですので、「追加する場合やインデックスを使う場合はsをつけて書く」「配列の場合にsをつける(または複数形にする)」などというのは誤った理解です。全く別のオブジェクトである、というのが正しい理解です。

本当はスクリプトを書くのなら、複数の異なった概念のプログラム言語も学習すると理解が深まるのですが、さすがにそれは酷ですね。