現在の選択を基準に、Action Managerへ下方向の相対選択を要求するPhotoshop JSXです。Bckwを指定します。選択IDの一覧を先に取得し、1つだけ選ばれている場合に実行します。画面で隣に見える行と、Photoshopが相対選択で返す対象を同一と決めつけないでください。
今回確認したのは標準JavaScriptの構文と模擬条件です。Photoshopでの選択・表示・実画面の撮影は未検証です。コードはレイヤーの移動・名前変更・保存を呼びませんが、選択状態は変わります。非表示、ロック、複数選択、アートボードの実際の挙動は自作の文書で確認してください。
相対選択・非表示を含む隣接選択・追加選択の違い
| 目的 | 方法と範囲 |
|---|---|
| Photoshopに下方向の相対選択を要求 | この記事のBckw。グループや非表示の扱いは実機で比較する。 |
| 同じ親の下で、非表示を含む1つ下を明示 | DOMのparent.layersで隣を探し、ID指定で置き換える。非表示を含む隣接選択 |
| 元の選択へ1つ上を追加 | 選択を先に解除せず、IDとaddToSelectionで1回要求する。上への追加選択 |
| 文書直下の端を選ぶ | 最上位/最下位。相対選択とは別の対象指定。 |
旧記事の「表示レイヤー」という説明を、全階層・すべての文書で非表示を必ず飛ばす保証にはしません。このコード自身はvisibleを走査して候補を絞っていません。MkVs=falseは選択要求に付ける設定で、表示レイヤーだけを抽出する条件でも、ロックを解除する指示でもありません。
下方向の相対選択を要求する全体コード
新しい全体コードをUTF-8の.jsxとして保存し、ファイル→スクリプト→参照から実行します。旧コードへ追記せず、別ファイルとして1回実行してください。メニューへの登録は動作を確認した後に行います。
#target photoshop
(function () {
if (app.documents.length === 0) { alert("文書を開いてください。"); return; }
function validId(value) {
return typeof value === "number" && isFinite(value) && value >= 0 && Math.floor(value) === value;
}
function selectedIds() {
var key = stringIDToTypeID("targetLayersIDs");
var ref = new ActionReference();
ref.putProperty(charIDToTypeID("Prpr"), key);
ref.putEnumerated(charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
var result = executeActionGet(ref);
if (!result.hasKey(key)) { throw new Error("選択IDの一覧を取得できません。"); }
var list = result.getList(key);
var ids = [];
for (var i = 0; i < list.count; i++) {
var id = list.getReference(i).getIdentifier();
if (!validId(id)) { throw new Error("選択IDが数値の整数ではありません。"); }
ids.push(id);
}
return ids;
}
function contains(ids, id) {
for (var i = 0; i < ids.length; i++) { if (ids[i] === id) { return true; } }
return false;
}
try {
var ids = selectedIds();
if (ids.length !== 1) { alert("レイヤーを1つだけ選択してから実行してください。"); return; }
var ref = new ActionReference();
ref.putEnumerated(charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Bckw"));
var desc = new ActionDescriptor();
desc.putReference(charIDToTypeID("null"), ref);
desc.putBoolean(charIDToTypeID("MkVs"), false);
executeAction(charIDToTypeID("slct"), desc, DialogModes.NO);
} catch (error) {
alert("読取または選択で中断: " + error.message + "\n行: " + error.line);
}
}());
文書・複数選択・選択IDの事前検査
文書なしなら文書の取得やAction Managerの読取を行いません。targetLayersIDsの一覧が取得できない版・状態では中断します。取得失敗を「1つだけ選択」と推測して続行せず、一覧0件・複数件も停止します。複数選択を受け付ける追加操作は、別記事の追加選択を使ってください。
端のレイヤーとエラーを区別する
この例は下端に到達したことを実行前に判定していません。executeActionが失敗した場合はerror.messageと行番号を表示します。例外は端への到達だけでなく、文書の状態やAPIの読取・選択失敗でも起こり得るため、「これ以上下のレイヤーはない」と一律に言い換えません。失敗時の選択状態も実機で確認してください。
自作PSDで確認する条件
| 条件 | 確認するもの |
|---|---|
| 3つの表示レイヤーで中央だけ選択 | 要求の方向と、選択後の行・選択ID。 |
| 隣が非表示・ロック・グループ | 相対選択が対象にした行。MkVs=falseでも表示状態の前後を比較。 |
| グループの子・折り畳んだグループ・アートボード | 親の境界と画面の見た目が異なる場合の選択結果。 |
| 下端にいる | 実行結果または例外の全文。別のエラーと区別。 |
| 文書なし・選択0件・複数選択 | 選択実行前の停止。自動で1件へ絞らない。 |
上表は実機で得た成功結果ではなく、確認する条件です。新コードの構文と模擬条件は検査しましたが、Frwr/Bckwが現在の文書でどの行を選ぶかはPhotoshopで確認する必要があります。前後の行・ID・表示・レイヤー数と順序を記録し、保存・削除などの処理をつなぐ前に対象を確認してください。
旧コードと過去の画面(参照用)
旧例には文書数・選択件数の検査がなく、すべての例外を端に到達したものとして表示します。新しい例は事前条件と例外の原文を分けています。旧画像のundefinedは戻り値の表示で、選択成功の証拠ではありません。
// 一つ下の表示レイヤーを選択
function selectLayerBelow() {
try {
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putEnumerated(
charIDToTypeID("Lyr "),
charIDToTypeID("Ordn"),
charIDToTypeID("Bckw") // 1つ下のレイヤーへ移動
);
desc.putReference(charIDToTypeID("null"), ref);
desc.putBoolean(charIDToTypeID("MkVs"), false); // 可視状態を変更しない
executeAction(charIDToTypeID("slct"), desc, DialogModes.NO);
} catch (e) {
alert("これ以上下のレイヤーはありません。");
}
}
// スクリプトを実行
selectLayerBelow();

参照資料と確認範囲
Adobe Photoshop Scripting Guide 2020の38〜39ページ(レイヤーの並び順・グループ)、JavaScript Scripting Reference 2020のActionDescriptor、ActionList、ActionReference、Document、Layers、LayerSetを参照しています。2020年版のExtendScript資料で、今回のPhotoshop実機の検証記録ではありません。
Cutterman作者のレイヤー操作コードのtargetLayersIDsとID指定、Adobe CommunityのJJMack氏による選択追加の記録のselectionModifierを比較しました。作者の掲載例は公式の全条件保証ではなく、今回の実機成功や速度測定にも数えていません。Adobeのレイヤー選択手順で説明する行の選択と、サムネールからのピクセル選択は別です。
旧配布と関連する手順
旧配布はGitHubの元コードに残しています。公開フォルダーの01.jsは今回の新しい例へ更新していません。実行する場合は、このページの新しい全体コードを別の.jsxとして保存してください。





