InDesignの表セルで斜線の左右(上下)で塗りを変える

2021年04月27日

久しぶりの投稿ですな。元ネタはこれ。

そう、セルの塗りにグラデーションを使えば希望のことができる。がしかし、好ましい結果を得るにはグラデーションツールで何回もチャレンジしなければならないという、苦行の技なのです。

ちなみにこの図で使用したグラデーションで、グラデーションストップは2か所、49.5%50.5%の位置です。


それではあまりに大変、スクリプトで計算すればいいじゃない」ということで(一晩経って気づいた)作ってみました。

ただし、これは誰でも使えるようにしたものではありません。作ってる過程でいろいろトラップがあったので、それをメモしておくためのものです。そのため誰でも使用できるようなインターフェイスは用意していません。変更したいときは直接コードを触ってください(ですからある程度スクリプトが分かる人でないと使えない代物)。

結果はこんな感じ。


コードと解説です。

if (app.documents.length < 1) {
	alert("ドキュメントを開いてください");
	exit();
}
var doc = app.documents[0];
if (doc.selection.length != 1 && doc.selection[0].constructor.name != "Cell") {
	alert("セルを1つ選択してください");
	exit();
}
//使用するグラデーションスウォッチ。事前に用意しておくこと
var sw = doc.swatches.itemByName("cell_grad");
//以下4行は一時的に定規単位をポイントに変更している
var hm = doc.viewPreferences.horizontalMeasurementUnits;
var vm = doc.viewPreferences.verticalMeasurementUnits;
doc.viewPreferences.horizontalMeasurementUnits = MeasurementUnits.POINTS;
doc.viewPreferences.verticalMeasurementUnits = MeasurementUnits.POINTS;
var sel = doc.selection[0]
//グラフィックセルへ変換するメソッド。プロパテcellTypeでは次の行がエラーになる
sel.convertCellType(CellTypeEnum.GRAPHIC_TYPE_CELL);
var ary = sel.pageItems[0].visibleBounds;
//メニューの[編集]→[取り消し]を実行。app.undo()がエラーになるため
app.menuActions.itemByID(265).invoke();
//cx, cyはセルの中心の座標
var cx = (ary[3] + ary[1]) / 2;
var cy = (ary[2] + ary[0]) / 2;
//dx, dyはグラデーションの開始位置(セル中心からの相対位置)。16は適当
var dx = (ary[2] - ary[0]) / 16;
var dy = (ary[3] - ary[1]) / 16;
var dr = Math.atan2(dy, dx) * 180 / Math.PI;
var lg = Math.sqrt((dx * dx) + (dy * dy)) * 2;
//理由はわからないが変数を再設定しないといけない
sel = doc.selection[0];
sel.fillColor = sw;
sel.gradientFillStart = [cx - dx, cy + dy];
//gradientFillLengthがポイントしか受け付けない
sel.gradientFillLength = lg;
sel.gradientFillAngle = dr;
//定規単位を元に戻している
doc.viewPreferences.horizontalMeasurementUnits = hm;
doc.viewPreferences.verticalMeasurementUnits = vm;

コード中のコメントにあるように、なかなか素直にいかないんだぁよ。

以下解説。

//使用するグラデーションスウォッチ。事前に用意しておくこと

親切なことをいえばダイアログを出してスウォッチを選択してもらうのがいいんだけど面倒なので省略してます。

//以下4行は一時的に定規単位をポイントに変更している

セルに限らず、gradientFillLengthプロパティは数値しか受け付けない。つまりどうしてもポイントに換算しなければなりません。定規単位ごとに変換するのは面倒なので、一旦定規単位をポイントに変更して、最後に戻してます。これの怖いところは、エラーになって異常終了した際に定規単位がポイントになってしまうところ。そうならないためにエラーが出ないように頑張っているのですが、何かあったらごめんなさい。使用者責任でお願いします。

//グラフィックセルへ変換するメソッド。プロパテcellTypeでは次の行がエラーになる

グラフィックセルへ変換するには2つの方法があって、

Cell.cellType = CellTypeEnum.GRAPHIC_TYPE_CELL; //(プロパティを使う)

Cell.convertCellType(CellTypeEnum.GRAPHIC_TYPE_CELL); //(メソッドを使う)

なんですが、プロパティの場合はその次の行

var ary = sel.pageItems[0].visibleBounds;

がエラーになってしまいます。理由は分かりません。

なお、手作業でグラフィックセルに変換するときは、セル中のテキストを削除しないといけないんですが、スクリプトからだと削除しなくていいという不思議なことになってます。

//メニューの[編集]→[取り消し]を実行。app.undo()がエラーになるため

この前の行で、グラフィックセルに含まれる長方形の座標を取得したので、「グラフィックセルに変換」を取り消して元のテキストセルに戻します。

この取り消す命令は、app.undo() なのですが、それがエラーになります。理由は知りません。仕方がないのMenuActionでメニューの取り消しを実行しているわけです。

メニューアクションは多くの場合

app.menuActions.itemByName(”すべてを選択”).invoke();

のように日本語メニュー名を使用した解説が多いですが、これには問題点があります。

それInDesignのバージョンが異なるとメニュー名が違うことがあり、その場合に動かないということです。例えInDesign 2019では「フォント検索」ですInDesign 2020では「フォントを検索して置換」です。

そのためどのバージョンで使用するか分からない場合には、名前ではなIDで指定しなければなりません。特に今回の「取り消し」は直前の操作によってメニュー名が変わるので必須ですね。

メニューIDを知るにはちょうどよいスクリプトがあります。

https://creativepro.com/files/kahrel/indesign/menu_actions.html

こちらのリンクからダウンロードしてください。

//dx, dyはグラデーションの開始位置(セル中心からの相対位置)。16は適当

グラデーションの設定は図の赤い線のようになってます。dx, dyを求めるとき16で割っていますが、これは「こんなもんでどうだろう」という適当な値です。グラデーションスウォッチの作成具合にもよるのですが、グラデーションの長さが長いと、色の境目のグラデーションが分かってしまうことになりかねません。そこでなるべくグラデーションの長さを短くしたいわけですね。ただあまりに短いとその後の計算で誤差が大きくなるので、それも困ります。何か困ったことがあったら「16」を別の数字に変えてください。

//理由はわからないが変数を再設定しないといけない

InDesign oneLinerでもあったんですが、何らかの操作で変数の中身がなくなってしまうということがありまして。今回は「取り消し」のせいだと思うんですが、もう一度変数にセットしてます。よくわからんです。


こんなに短いのにトラップ多すぎだろ、ということで、これにインターフェイスを付けたり、グラデーションの開始位置を左下以外のパターンに対応するというところまでは行けませんでした。必要な人は適宜修正して使用してください。