Practice makes Perfect !

ExtendedScript素人です。同じ境遇の方、一緒に脱素人を目指しましょう!

入力された数値を使った計算

とても簡単なことなんでしょうけど、
やっぱり独学ってつまづくことがいろいろありまして。
「入力された数値に10を足して答えを表示する」
これだけのことなんですけど全然わかりませんでした。

最初に書いたスクリプトはこちら。

var rt = prompt("数値を入力","");
alert(rt+10);


これで5を入力したときに15と表示してほしかったんです。
でも表示されたのは「510」

おかしいですね、なんででしょう。

で、調べたらpromptから返されるデータは、数値ではなく文字列とのこと。
Number(),parseInt(),parseFloat()を使って数値型にしなければならないとのこと。
これらを調べたらどうやらNumber()を使うのがいいのかなと思い、上記スクリプトを書き換え。

var rt = prompt("数値を入力","");
var num=Number(rt);
alert(num+10);

これで意図する計算が出来ました。

いやー奥が深いですね
え?基本中の基本?
そうですか…

Bounds! Bounds! Bounds!

ページの上下左右4辺の座標はBoundsで取得できるんですね。
知りませんでした。

A4のドキュメントを作成して

var doc = app.activeDocument.pages[0];
$.writeln(doc.bounds[0]); // 上
$.writeln(doc.bounds[1]); // 左
$.writeln(doc.bounds[2]); // 下
$.writeln(doc.bounds[3]); // 右

と入力すると
0
0
296.999999999461
209.999999999936
という結果が得られます。細かいことは気にせずに。

今までは作業中のページサイズの長方形フレームを作成するときは以下のスクリプトを実行していました。

var doc = app.activeWindow.activePage; // 作業中のページ
var rct = doc.rectangles.add();
rct.contentType = ContentType.graphicType;
w = app.activeDocument.documentPreferences.pageWidth;
h = app.activeDocument.documentPreferences.pageHeight;
rct.visibleBounds = ["0mm","0mm",h,w];

なにも考えてなかったのですが、これだと問題がありました。
例えばドキュメント設定でサイズをA4にしていた場合、どのページもA4であるなら問題がないのですが、途中で違うサイズのページが出てきた場合、上記スクリプトを実行すると、そのページにはページサイズのフレームではなくA4サイズのフレームが出来てしまうんですね。

なのでこういう場合も考慮してBoundsを使えばいいと思いました。

var doc = app.activeWindow.activePage;
var rct = doc.rectangles.add();
rct.geometricBounds = doc.bounds;
rct.contentType = ContentType.graphicType;

見た目もキレイでスッキリとしました。
bounds、最高じゃないですか笑

いや、何事もひとりでやっていくって大変ですね笑
(いいからやれよ)

新規ドキュメントの作成

前回の更新日が昨年の11月…
年末から繁忙期に入ったとはいえ、ずいぶん長い間、ブログ更新してないな、と思います。
そして、繁忙期が終わったあと、せっかく勉強してきたスクリプトをほとんど忘れているという悲しい状況でございました。
リハビリを兼ねてといいますか、しばらくは力を抜いてブログを少しずつ再開していきたいと思っています。

新規ドキュメントの作成

「B4横長のドキュメントを新規で作る」
というスクリプトを書こうと思ったら
var doc = app.documents.add();
で行き詰ってしまいました。こんな状況です。
今までいったい何をやってたのでしょう…
ということでドキュメントの設定について調べてみました。
ドキュメントの設定には〈documentPreferences〉を使用するようですね。

var doc = app.documents.add();
doc.documentPreferences.pageSize = "B4";

これでとりあえずB4のドキュメントが作れます。

"B4"のところはメニューから選べるものであれば何でも行けるようですね。
名刺にしたい場合は"名刺(半スペ)4(半スペ)号"で作成できました。
f:id:YustinBieber:20220412154850p:plain


さて、横長にしたい場合は

var doc = app.documents.add();
doc.documentPreferences.pageSize = "B4";
doc.documentPreferences.pageOrientation = PageOrientation.LANDSCAPE;


天地左右のマージンの設定は

doc.pages[0].marginPreferences.top = 10;
doc.pages[0].marginPreferences.left = 5;
doc.pages[0].marginPreferences.bottom = 10;
doc.pages[0].marginPreferences.right = 5;


マージンはマスターで設定しておきたかったので

doc.masterSpreads[0].pages[0].marginPreferences.top = 10;
doc.masterSpreads[0].pages[0].marginPreferences.left = 5;
doc.masterSpreads[0].pages[0].marginPreferences.bottom = 10;
doc.masterSpreads[0].pages[0].marginPreferences.right = 5;

としました。

その他、規格外のサイズのもの、見開き、綴じ方向、ページ数の設定

var doc = app.documents.add();
doc.documentPreferences.pageWidth = "100mm";   //幅
doc.documentPreferences.pageHeight = "200mm";  //高さ
doc.documentPreferences.facingPages = true;  //見開き
doc.documentPreferences.pageBinding = PageBindingOptions.RIGHT_TO_LEFT;  //綴じ方向
doc.documentPreferences.pagesPerDocument = 8;  //ページ数


ブログ、続けられるといいな…
(いや、続けろよ)

実験003_2021.11-1

指定したページに、指定したマスターを当てるスクリプト

ページものを作っていて、各カテゴリや各章ごとにマスターが変わるときに、2・3個のマスターなら手動で割り当ててあげればいいのですが、マスターが10個とか20個とかあると、もうそれだけでうんざり…

f:id:YustinBieber:20211126114824p:plain
マスターが多すぎて嫌になる…
f:id:YustinBieber:20211126111619p:plain
いちいち手動で設定していくのが手間でした

なんとかならないものだろうかと考えていたんです。


それで次の工程で考えてみました。

  1. エクセルを使って、何ページに何番目のマスターが当たるかを設定しておき、テキストファイルに書き出す
  2. 書き出したテキストファイルを1行ずつ読み込んで、各ページに指定されたマスターが当たるようにスクリプトで処理
f:id:YustinBieber:20211126111717p:plain
エクセルで何番目のマスターを当てるか設定しておく

上の図はあくまで例なのですが、1~2ページに1番目のマスター、3~4ページに2番目のマスター…といった感じです。マスターをなしにする場合は空白にしておきます。

それで考えてみたのが以下のスクリプトです。

var docObj = app.activeDocument;
var pageObj = docObj.pages;

var filename = File.openDialog("リストのテキストファイルを選択してください。");
if (filename)
{
var fileObj = new File(filename);
 // 読み込みモード
fileObj.open("r");

//テキストファイルを1行ずつ読み込み最終行まで繰り返し
while(!fileObj.eof) {
	try{
		for (var i=0; i<pageObj.length; i++){
		var line= fileObj.readln();
		if(line!="") {
		pageObj[i].appliedMaster =app.activeDocument.masterSpreads[line-1];
		}else{
		//リストでマスターの指定がない場合はマスター[なし]にする		
		pageObj[i].appliedMaster =null;
		}
	}
		}catch(e){}
}
fileObj.close();
alert("終了しました");
}else{
	exit();
	}

実行結果は図のページパレットをご覧いただけるとわかると思います。
f:id:YustinBieber:20211126114331p:plain
これでマスターの数分だけ、いちいち手動で割り当てていた作業が数秒で終わるようになりました。

蛇足ですがエクセルでは先に範囲選択をしておけば、数値入力後にCtrl+Enterで選択範囲内に同じ数値が一発で入りますよ。

Recommend_002 段落の選択→任意の行数に収める

段落の選択に4回クリック?

1つの段落を選択するのにInDesignでは4回クリックしなければなりません。
4回のクリックなんて楽なようで面倒です。
スクリプト→ショートカットで解決してしまいましょう。

ちなみにシングル、ダブル、トリプルの次って何だ?と思って調べてみたんですが、こうなっているようです。


1 シングル (single )
2 ダブル (double )
3 トリプル (triple )
4 クアドラプル (quadruple )
5 クインタプル (quintuple )
6 セクスタプル (sextuple )
7 セプタプル (septuple )
8 オクタプル (octuple )
9 ノナプル (nonuple )
10 デキャプル (decuple )


4回クリックは「クアドラプルクリック」! なるほど…。


InDesignの段落の選択に関しては、末尾の改行まで選択してしまうということによる弊害がありまして、こちらについてはDTPtransitさんの方で紹介されています。

www.dtp-transit.jp

そちらで紹介されているスクリプトがUske_Sさんのスクリプト

uske-s.hatenablog.com

任意の段落の一部を選択したり、カーソルを点滅させておけば、画像のように1段落を改行を除いて選択してくれます。
f:id:YustinBieber:20211117171138p:plain

末尾の改行を除いて段落を選択するスクリプトはDTPtransitさんのサイトでダウンロードできるようになっていますので、すぐにダウンロードし、ショートカットを設定されることをお勧めします。


見出しを1行に収めたい

2行にわたってしまっている見出しを1行に収めたかったり、E-mailアドレスを1行に収めたかったり…
そういったことに出くわすことはよくあることだと思います。

そんな時、まずは上のスクリプトで段落を選択。
そして、選択した段落を1行に収めるには市川せうぞーさんのサイトにある「shorten_line_selection」を使用します。

www.seuzo.jp

こちらのスクリプトはデフォルトで選択範囲を1行に収める設定になっています。
私はこちらのスクリプトをカスタマイズさせていただいて、「長体のみ」で1行に追い込むように設定しています。


というわけで、2行にわたる見出しを1行にするといった処理は、上記2つのスクリプトを使えば、キーボードを2回叩くだけでストレスなく終わってしまいます。
名刺の長~いE-mailアドレスなんかにも大活躍!テキストフレームから文字が溢れていても選択できます。

f:id:YustinBieber:20211117171144p:plain
ここまでの処理がキーボード2回叩くと出来てしまう

さらにこの2つのスクリプトを組み合わせてしまえば、1回のショートカットで処理出来てしまいます!
なのでわたしは組み合わせちゃってます。
いままでドラッグして範囲を指定して、文字パレットで1行に収まるまでカチカチクリックして長体かけて…、とやっていたのがアホらしくなってきます。


意外と知られていない? 長体のショートカット

最後に余談ですが、InDesignで文字に長体をかけるショートカットは[編集]メニューの[キーボードショートカット]から[テキストと表]→[水平比率を減少]で設定できます。
こちらも良く使う機能だと思いますのでショートカットの設定をおすすめします。
f:id:YustinBieber:20211117171125p:plain

好きな仕事をしていても、やっぱり「面倒くさい」と思うことはあるわけで、じゃあどれだけストレスなく作業をこなすかって考えたら、「楽に処理できる方法を知る」これにつきますね。

Recommend_001 基準点の変更

InDesignでオブジェクトを選択して、基準点を選択して、位置と大きさを指定して…という作業がいつも面倒くさいと思っていました。これだけでマウスを3回クリックしなくてはいけない…。

オブジェクトを選択して「Crtl+6」でX座標に入れることは知ってはいましたが、その横にある基準点の移動がスクリプトで制御できると知ってからは、格段に作業効率があがりましたし、ストレスもなくなりました。

それで、スクリプト&ショートカットを割り当ててやるのが便利ですよ!って紹介しようかと思っていたのですが、これはすでにDTP Transitさんの方で紹介されていました。

www.dtp-transit.jp

上ページにある「スクリプトを使う」というところで紹介されているスクリプトをダウンロードすれば全て解決です。

ここでは一応その中身のご紹介をさせていただきます。

ダウンロードしたスクリプトのうち基準点を中心に持ってくるスクリプトは次のようになっています。

app.layoutWindows[0].transformReferencePoint = AnchorPoint.CENTER_ANCHOR;

たったこれだけです。

app.layoutWindows[0].transformReferencePoint = AnchorPoint.●●●●●

この●●●●●の部分を変えるだけで基準点を制御できるようになっています。
以下の図にまとめてみました。

f:id:YustinBieber:20211118154444p:plain


あとはいつものようにショートカットを設定してあげるだけです。
それで、さすがに9個もショートカットは覚えられないと思ったので、基準点の位置に合うようにテンキーの1~9を割り当てました。
割り当てたのですが、これだと何故かテキストを入力するときに「1」だけ入力できなくなってしまったので「1」だけショートカットを変えてます…。

f:id:YustinBieber:20211118164404p:plain

f:id:YustinBieber:20211119084607p:plain

これでオブジェクトを選択した後はこのショートカットで基準点を設定した後に「Ctrl+6」でX座標に入ってしまえば、あとはキーボードのみで処理できるので大分ストレスが減るのではないかと思います。
(数値の入力を始めると上のショートカットは使えなくなるのでそこは難点ですが…)

こんな細かいことでもスクリプトを知ってるか知らないかで作業効率が変わってきます。
別に大きなことをやろうとする必要はなく、ちょっとした工夫で大きな効果を得られることはどんどん取り入れていくべきですね!

余談ですが、だったらオブジェクトを選択したら自動で基準点が左上になるようにスタートアップスクリプトで設定しとけばいいじゃん!と思って以下のコードを入れてみましたが、ダメでした。残念…

var selObj= app.activeDocument.selection;
if (selObj.length !== 0) app.layoutWindows[0].transformReferencePoint = AnchorPoint.TOP_LEFT_ANCHOR;

関数と引数

関数の目的

スクリプトの勉強を始めたころは本当にこの関数が分かりづらく、「もうやめようかな…」て何度か考えたものでした。
しかし、特に難しく考える必要はなかったようで、単に「まとまった処理を行う機能」が関数であると考えればよさそうだと思うようになりました。

そもそも関数の目的は、

  • プログラムを短くする
  • 再利用する


ということになるそうです。
プログラムが短くなることの利点は「ミスが減ること」。
再利用することの利点は「プログラムを作成する手間が省けること」。

たしかに、見た目がすっきりしてて、きれいだな~って思うスクリプトって関数が上手に使ってあることが多いのではないかと思います。


さて、実は私、この関数に引数が入ってくるとよくわからなかったのです…。
そして今でも理解が怪しい!


ここはやっぱりJavascriptの基礎から調べるべきかと思ってJavascriptに関するサイトを見てみまして…
www.javadrive.jp

簡単な例なら、なんとなくわかったような気がしました。

例えば、

function ID(name, age){
alert(name+"は"+age+"才です");
}

//関数IDを呼び出して、引数nameにやすちん、ageに42を渡す
ID("やすちん", 42);

こんな感じで、実行結果は「やすちんは42才です」と表示されます。
こんな例でも引数を変えるだけで何度も使えるので、やはり便利です。

return文

関数は処理した結果を返す機能を持っていて、関数内にreturn文を記述することで任意の値を返すことができます。

function multiply(num1, num2){
return num1*num2;
}
alert(multiply(5, 10));

これの実行結果は50と表示されます。

さきほどの名前と年齢の例でreturnを使うと…

function ID(name, age){
return name+"は"+age+"才です";
}

//実行結果を変数に入れてみる
var result =ID("やすちん", 42);
alert(result);

これでも上記とおなじ結果になります。


こうやってゆっくり調べてみるとなんとなくわかったような気がます。
そこでちょっとこの関数と引数を使って「開いているすべてのドキュメントに「背景」という名のレイヤーを最背面に作るスクリプト」を書くとこんな感じでどうかなと思います。

for (counter=0; counter<app.documents.length; counter++){
	addLayer(counter); 
	//下記のaddLayerという関数を呼び出す
	}

//addLayerという関数を定義し、引数に変数Noを設定。
//Noに上記"counter"の値が渡される
function addLayer(No){
var doc = app.documents[No];

//「背景」という名のレイヤーを作成し、最背面へ移動
var layObj = doc.layers.add({name:"背景"});
var lay_B = doc.layers.lastItem();
layObj.move(LocationOptions.AFTER, lay_B);
}


「背景」という名のレイヤーをもともと持つドキュメントが出てきた時の処理は…。いちおう載せてはおきますが、本当は中止するのではなく、「問題のドキュメントをすっ飛ばして処理を続ける」ってやりたかったんです。
でも残念なことに、勉強不足で分かりませんでした。
continueを使えばよさそうな気はするんですが…。
この程度です(涙)

for (counter=0; counter<app.documents.length; counter++){
	addLayer(counter);
	}

function addLayer(No){
var doc = app.documents[No];

//もともと"背景"という名のレイヤーがあったら処理を中止する
for (var i=0; i<doc.layers.length; i++){
	if(doc.layers[i].name=="背景"){
		alert(doc.name+"には\r背景というレイヤーが既に存在します。\r処理を中止します");
		exit();
	}		
}		
var layObj = doc.layers.add({name:"背景"});
var lay_B = doc.layers.lastItem();
layObj.move(LocationOptions.AFTER, lay_B);
}


よく内容を理解していないのにブログを書いてしまう素人ですが、どうぞご容赦くださいませ。


さて、今わたしが、これはいいな!って思っているのはUske_Sさんのサイトにあるmyerrorの使い方。

var myerror = function (mes){
    alert(mes);
    exit();
    }

そしてアラートメッセージを呼び出すには次のように書くだけ。こういうのシンプルで読みやすくて素敵です。

myerror("エラーメッセージ");

uske-s.hatenablog.com