2011年08月20日
_ [indesign] 【ネタバレ注意】DTPの勉強会 特別編 第2回 課題制作
DTPの勉強会特別編 第2回 の事前課題制作過程は【ネタバレ注意】を付ける以外は考え中のものを公開するのは 絶賛アリとのことなので、自分が作ってみたものを晒してみる。
その後、ちょっとアップデートをかけた。
テキストフレームの中のテキストを上下センターにする
http://kmuto.jp/indesign/scripts/trial/2nd-task1-vcenter.jsx
上下センターはプロパティ名がわかれば一発。プロパティの値にクラス定数を指定するときに、それをヘルプブラウザで調べるのが難しいことがあるのが罠(保存オプション系が「options」としか書いていないのはひどいよね……)。
対象フレームは選択したものを、ということなので、app.activeDocumentで現在開いているドキュメント、app.selection[0]で選択している物を取得。instanceofでテキストフレームであることを確認する。
1つのテキストフレームを右へ10mm移動、2つのテキストフレームの間隔を3mmにする。
http://kmuto.jp/indesign/scripts/trial/2nd-task2-locate.jsx
設問的に別々の作業なのか、これらを一度に行うということなのか、と判断に悩むところはあるが、別々なら単にスクリプトを後で分ければよいし、1つで順に処理するように作った。
選択している2つのテキストフレームをapp.selection[0]、app.selection[1]で取得。フレームオブジェクトの左上座標と右下座標は
geometricBounds
visibleBoundsで調べられる(この座標の差を取れば、幅・高さも導出可能)。設問の補足では、3mm間隔というのは水平間隔で、動かす際には右側のフレームを動かすとのこと。普段はgeometricBoundsばかり使っていたのだが、こちらは囲みケイが「含まれない(exclude)」ため、ケイ入りで作っていた場合には3mmのつもりがケイ幅の分だけずれることになる。visibleBoundsにすると、囲みケイを「含む(include)」ものになる。
左か右かはgeometricBounds値を見てもいいが、selectionの挙動では左側にあるほど若い番号が振られるようなので、とりあえず判定はなしで[0]が左、[1]が右と仮定することにした。
嘘。階層で上にあるものから採番されるっぽい(確かにそうなった)。なので、やはりvisibleBoundsの左X座標を比較する必要がある。
右側フレームを動かしてさらに右側フレームを動かすだと奇妙なので、左側のフレームを右方向に10mm移動、その後に左側フレームから3mm右に離して右側フレームを配置、という処理にしてみる。単位座標系は左上基準からは変更しないものとする。
いずれにしても移動処理となるが、移動にはvisibleBoundsプロパティ値を直接修正する方法と、moveメソッドを使う方法がある、はず。自分はmoveはレイヤーやページを変えたいというとき以外はあまり使っていない(何かのバグにひっかかった覚え…)ので、visibleBoundsを使うようにした。visibleBoundsは4つの値を持つ配列だが、X1, Y1, X2, Y2 ではなくて、Y1, X1, Y2, X2 という構成には注意が必要。版面外に出たときの扱いがいまいち謎だったりもする。
ドキュメント設定で単位をミリにしているなら単にこれらの配列値をいじるだけでよいが、一応念のためにここでは単位をバックアップしておいて、終わった後には戻すようにした。スクリプトは自分だけが使うものではないことがあるし、何か設定をいじるときには処理前にバックアップ・処理後にリカバリをするようにしている。
テキストフレーム内の文字「楽しく」にルビをふる、「作成方法」にルビをふる(グループルビ)
http://kmuto.jp/indesign/scripts/trial/2nd-task3-ruby.jsx
XMLインポートの場合だとXMLタグでルビを指定できてしまうので、スクリプトから操作するというのは初めての体験。この設問も別々のスクリプト作成なような気はするけれども、1つのスクリプトにまとめている(先と同様に分けることは容易)。
モノルビとグループルビはRubyTypes定数が違う以外は挙動としては変わらないので、setRubyメソッドを作って共通化した。一応すでにルビがある場合にはいじらないようにしておく。
「楽しく」の「楽」だけを正規表現で取り出すのはちょっとコツがある。それが後方肯定「(?=STRING)」。これで、文字列としては「楽しく」に一致するけれども「マッチした文字列」として返されるのが「楽」だけ、という挙動を実現できる。テキストフレームから正規表現で探すのはテキストフレームオブジェクトのfindGrep()。
これに比べると「作成方法」のほうは肯定表現を使うまでもないので、単純文字列検索のfindText()を使っている。
find系メソッドはInDesignの検索パネルそのままなので、テキストフレームなどの選択範囲、ストーリー、ドキュメントなどいろいろと対象範囲を絞って実行できるのだけど、スクリプト内ではfindメソッドを呼び出すオブジェクトによってそれが決まる、というのがちょっとわかりにくいところかもしれない。
テキストの中の値段をすべて10円アップする
http://kmuto.jp/indesign/scripts/trial/2nd-task4-plusten.jsx
これは思いを深めるとなかなか難しい。値段ということで、数値の後に「円」または「圓」が後ろについている、あるいは数値の前に「¥」(半角/全角)が付いているという前提条件として、数値はいわゆる半角数字のみ、桁区切り「,」がすでに付いているときにはそれを尊重して桁区切りを行い、付いていなければ区切らないということにした(「90円だけど区切りたいんですが」というときには「9,0円」とでもしておきましょう…)。区切り記号が不正な位置にあっても気にしないことにする。
「,を含み得る数値 + 円|圓」は後方肯定の正規表現で「,を含み得る数値」を取り出せる。 「¥ + ,を含み得る数値」は類似の前方肯定(?<=STRING)の正規表現で「,を含み得る数値」を取り出せる。そういえばWindowsだとここで半角円記号を入れるのが大変なのではという気がしてきた。コピペするか、バックスラッシュとして扱って\\とするか、かな。
後で区切りを行うかどうかのために,があるかどうかを調べてから、,を取り除く。
10円アップ自体は単に+10するだけ、ではあるのだけど、取得した「,を含み得る数値」マッチ文字列はその名のとおり文字列なので、そのまま+10だと型推測で文字列が優先されて10という文字列が後ろに付いてしまう点に注意が必要。
その後に桁区切りを行うが、後ろから1文字ずつ調べていって、最初(つまり末尾)を除く3桁が終わるごとに区切るというもの。forなどでごちゃごちゃ回しているけれども、実は正規表現1発で書けるらしい。奥が深い。
追加課題 については、お題2が元々の課題2と同じなのでキャンセル、お題3は課題3とほぼ同じ(「学ぶ」を「楽しく」と同じように入れる)かな。
お題1が新しいけれども、「ページすべての」という意味解釈と、そこから深追いするとちょっと難しい。
選択したテキストフレームの属するページを取得して、ページ直下にあるテキストフレームを探すだけであれば、PageオブジェクトのtextFramesプロパティで簡単に取れる。 ドキュメントのすべてのページの直下にあるテキストフレーム、でもPageオブジェクトをループで取る以外は基本的に同じ。
Pageオブジェクト内にある「インライン等を含むすべてのテキストフレーム」だと、再帰が必要。テキストフレームはテキストフレームまたはグループに含まれる可能性がある。その中にさらに含まれる可能性もあり……ということで、基本的にはループ+再帰で実装は可能だけど、深追いはこのあたりで。