PhotoshopのExtendScript(.jsx)で、文書の有無、レイヤーの階層、名前の一致、テキスト型、ファイルの取消を確認する短いコード例です。コピーして全部を連結するコード集ではありません。各例を別ファイルへ保存し、変更する例は自作文書のコピーで確認します。
旧25コードは後半の参照資料へ保持しました。
2026年10月17日に、新しい例のうち5本を、Adobe Photoshop 2026(27.11.0)とWindows 11 Pro(10.0.26200)で、[ファイル]→[スクリプト]→[参照]から実行して確かめました。
確かめたのは、文書の有無、グループ内を再帰して名前を読む、名前が1件だけ一致したレイヤーを選ぶ、テキストレイヤーの色、実行中のファイルのパスの5本です。
最上位の名前、背景の解除、ファイルを選んで開く、文字列の長さの4本は、構文と模擬条件の検査だけで、Photoshopでは実行していません。
練習用の文書(テキストレイヤー1つと、2段に入れ子にしたグループ)はスクリプトで作ったため、その作り方は確認に含めていません。
UXPの.psjsとはAPIが異なるため、JSXとPSJSの違いも確認してください。
短いコードを選ぶ前の確認
| 操作 | 条件と文書への変更 |
|---|---|
| 文書名/レイヤー一覧 | 読取のみ。背景解除・ラスタライズ・保存は不要。 |
| レイヤー選択 | 同じ名前が複数ある場合は停止。選択状態は変わるが保存はしない。 |
| 背景解除・文字色 | レイヤー情報を変更する。コピーで試し、確認後は元に戻すか保存せず閉じる。 |
| ファイルを開く | 取消・存在・読込失敗を区別。文書が増えるため対象を再確認。 |
| 削除・統合・書き出し | 原本で試さず、出力・上書き・取消を扱う完成例を使う。 |
AdobeのJavaScript Scripting Reference 2020のDocument/ArtLayer/LayerSetと、JavaScript Tools GuideのFile/Folder・エラー・文字列を確認しています。公式の旧版仕様と、このPCの現行版での操作成功は分けて扱います。
文書の有無とエラーを確認する
即時関数は変数を関数内にまとめる書き方です。ドラッグ実行を有効にする必須の条件ではありません。try/catchは失敗を通知する仕組みで、途中の編集を取り消す機能ではありません。
#target photoshop
(function () {
if (app.documents.length === 0) { alert("文書を開いてください。"); return; }
try {
var doc = app.activeDocument;
alert("対象: " + doc.name);
} catch (error) {
alert("エラー: " + error.message + " / 行: " + error.line);
}
}());
画像を開いていないホーム画面のまま[参照]から実行すると、「スクリプト警告」の窓に「文書を開いてください。」と表示されました。

練習用の文書を開いた状態で実行すると、同じ窓に「対象:」と文書名が表示されました。
どちらの場合もエラーの窓は出ず、文書は変わりませんでした。
最上位レイヤーの名前を読む
doc.layersは最上位のArtLayerとLayerSetを含みます。グループ内はこの例では読んでいません。旧例には末尾reと閉じ括弧の不足があり、構文・実行エラーにつながるため、新例に含めません。名前を読むための背景解除も不要です。
(function () {
if (app.documents.length === 0) { return; }
var layers = app.activeDocument.layers;
var names = [];
for (var i = 0; i < layers.length; i++) { names.push(layers[i].name); }
alert(names.join("\n"));
}());
グループ内を再帰して名前を読む
グループ名も先に記録し、子レイヤーへ進みます。出力順はこの走査順です。階層パスに同名があれば同じ文字列になるため、固有IDや選択順を表す値には使いません。速度比較は測定していません。
(function () {
if (app.documents.length === 0) { return; }
var names = [];
function visit(parent, prefix) {
for (var i = 0; i < parent.layers.length; i++) {
var layer = parent.layers[i];
var path = prefix + layer.name;
names.push(path);
if (layer.typename === "LayerSet") { visit(layer, path + "/"); }
}
}
visit(app.activeDocument, "");
alert(names.join("\n"));
}());
下の画像は、グループAの中にグループBを入れた練習用の文書で実行した結果です。

レイヤーパネルの上から順に読み、グループ名の直後に、その中のレイヤーが「グループA/グループB/子レイヤー」の形で並びました。
背景レイヤーも「背景」として最後に出ました。
実行の前後でヒストリーの数は変わらず、文書は変更されませんでした。
名前が1件だけ一致したレイヤーを選ぶ
CGM_targetを探す名前に変更します。0件または2件以上なら選択しません。layers.getByNameだけで同名やグループ内の対象を一律に選べると扱わず、範囲と一致件数を明示します。
(function () {
if (app.documents.length === 0) { return; }
var doc = app.activeDocument;
var matches = [];
function find(parent, name) {
for (var i = 0; i < parent.layers.length; i++) {
var layer = parent.layers[i];
if (layer.name === name) { matches.push(layer); }
if (layer.typename === "LayerSet") { find(layer, name); }
}
}
find(doc, "CGM_target");
if (matches.length !== 1) { alert("一致数: " + matches.length + "。選択を変えません。"); return; }
doc.activeLayer = matches[0];
}());
グループAの中にだけ CGM_target がある文書で実行すると、グループの中の CGM_target が選択されました。

最上位にも同じ名前のレイヤーを足して実行すると、「一致数: 2。選択を変えません。」と表示され、選択は元の「見出し」レイヤーのままでした。

スクリプトで選択を変えても、ヒストリーの項目は増えませんでした。
背景レイヤーだけを通常レイヤーへ変える
この例は編集操作です。最背面のレイヤーを背景と推定せず、isBackgroundLayerがtrueのArtLayerだけを変更します。背景がない場合は任意の最背面レイヤーを変更しません。
(function () {
if (app.documents.length === 0) { return; }
var doc = app.activeDocument;
for (var i = 0; i < doc.artLayers.length; i++) {
if (doc.artLayers[i].isBackgroundLayer) {
doc.artLayers[i].isBackgroundLayer = false;
return;
}
}
alert("背景レイヤーがないため変更しません。");
}());
選択したテキストレイヤーの色を変える
ArtLayerかつLayerKind.TEXTを確認してから文字色を設定します。通常レイヤーやグループにはtextItemを読ませません。複数の文字色を持つテキストの保持はこの例の目的に含めず、全体の色を変える操作としてコピーで確認します。
(function () {
if (app.documents.length === 0) { return; }
var layer = app.activeDocument.activeLayer;
if (layer.typename !== "ArtLayer" || layer.kind !== LayerKind.TEXT) {
alert("テキストレイヤーを選択してください。"); return;
}
var color = new SolidColor();
color.rgb.red = 0; color.rgb.green = 255; color.rgb.blue = 0;
layer.textItem.color = color;
}());
黒い文字のテキストレイヤーを選んで実行すると、文字色が緑(RGB 0・255・0)に変わりました。
ヒストリーには「テキストレイヤーを編集」が1つ増えました。

通常レイヤーを選んで実行すると、「テキストレイヤーを選択してください。」と表示され、文字色もヒストリーも変わりませんでした。
ファイルを選んで開く
開くファイルを利用者が選び、取消なら終了します。存在しても、形式・権限・破損等で開けない場合があります。エラー表示と実際に開いた文書を照合してください。
(function () {
var file = File.openDialog("Photoshopで開く画像を選択してください");
if (file === null) { return; }
if (!file.exists) { alert("ファイルがありません。"); return; }
try { app.open(file); } catch (error) { alert("開けません: " + error.message); }
}());
実行中のJSXのパスを読む
$.fileNameをFileへ渡し、OS形式のfsNameを読みます。URI表記とOSパスを混ぜたり、すでに復号済みの文字列へdecodeURIを重ねたりしません。コンソール表示とPhotoshopのアラートは異なります。
var scriptFile = new File($.fileName);
$.writeln(scriptFile.fsName);
[参照]から実行すると、Photoshopの画面には何も表示されませんでした。
$.writeln() の出力はPhotoshopの窓には出ないため、画面で確かめたいときは2行目を alert() に変えます。
var scriptFile = new File($.fileName);
alert(scriptFile.fsName);この形で実行すると、「スクリプト警告」の窓に、実行したファイルのフルパスがWindowsの形式で表示されました。

文字列lengthが数える単位
lengthはUTF-16コード単位です。絵文字等の見た目1文字と一致するとは限りません。旧例はテキストレイヤーから取得せず固定文字列を処理していたため、レイヤーの文字数を自動取得する説明とは区別します。
var words = "あいうえお";
alert("UTF-16コード単位: " + words.length);
旧例の前面・マスク・削除・GIF・進捗を扱う場合
| 旧処理 | 確認・改善が必要な点 |
|---|---|
| bringToFront / 最前面・上下選択 | アプリ前面とレイヤー選択は別。Action Managerの指定は現在の選択・最上/下端・グループ条件で実機比較する。 |
| hasLayerMask | UsrMによるユーザーマスクの検出はベクトルマスク等と区別。catchでfalseを返す旧例は、対象なしと読取エラーを区別できない。 |
| artLayersの最背面削除 | layers全体の最背面やLayerSetと同じではない。削除対象を明示し、原本で実行しない。 |
| rasterizeAllLayers / blendMode / opacity | テキストやスマートオブジェクト等の編集情報を変える操作。対象型・ロック・文書モードを確認する。 |
| GIF保存 | 旧exportPngという関数名でもformatはGIF。PNG処理と誤認しない。保存先、既存出力、色数/透明/画質を別に確認する。 |
| suspendHistory / progressbar | ヒストリーをまとめても失敗時の自動復元にはならない。進捗は処理済み件数で更新し、例外・取消でもUIを閉じる構成が必要。旧0開始では最後がmaxに届かない。 |
これらの旧コードはそのままの完成例としては扱いません。複製して別名PSD保存やScriptUIの入力・進捗・取消など、対象と失敗後の状態を定めた記事を使ってください。レイヤー削除や書き出しの成功は新例でも実機確認が必要です。
実行入口と旧ドラッグ画面
最初はファイル→スクリプト→参照で実行し、慣れたコードだけメニューへ登録します。下の旧ドラッグ画面は過去の記録で、今回の版でのドラッグ受付や成功を確認したものではありません。

旧コード・配布元・関連操作
旧コードの参照資料(実行しない)
旧25コードを原文で保持しています。末尾re、読取の前の背景解除、固定名/保存先、型確認のないtextItem、エラーをfalseに隠すマスク判定などを含みます。新例へ混ぜて実行しないでください。
旧コード 1
//--------------------------------------------------
// 関数
//--------------------------------------------------旧コード 2
#target photoshop
function test(){
try {
//作成したスクリプト
} catch (e){
alert("エラー発生");
}
}
test();旧コード 3
(function(){
alert("テストだよ!");
})() ;旧コード 4
(function(){
alert("テストだよ!");
}()) ;旧コード 5
app.bringToFront();旧コード 6
var doc= activeDocument;
var bg = doc.layers.length;
doc.layers[bg-1].isBackgroundLayer = false;旧コード 7
function selectFront() {
var idslct = charIDToTypeID( "slct" );
var desc250 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref207 = new ActionReference();
var idLyr = charIDToTypeID( "Lyr " );
var idOrdn = charIDToTypeID( "Ordn" );
var idFrnt = charIDToTypeID( "Frnt" );
ref207.putEnumerated( idLyr, idOrdn, idFrnt );
desc250.putReference( idnull, ref207 );
var idMkVs = charIDToTypeID( "MkVs" );
desc250.putBoolean( idMkVs, false );
executeAction( idslct, desc250, DialogModes.NO );
}
selectFront();旧コード 8
// 一つ上のレイヤーに移動
function selectLayerForward() {
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID( "Lyr " ), charIDToTypeID( "Ordn" ), charIDToTypeID( "Frwr" ) );
desc.putReference( charIDToTypeID( "null" ), ref );
desc.putBoolean( charIDToTypeID( "MkVs" ), false );
executeAction( charIDToTypeID( "slct" ), desc, DialogModes.NO );
}
selectLayerForward();旧コード 9
// 一つ下のレイヤーに移動
function selectLayerBelow() {
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID( "Lyr " ), charIDToTypeID( "Ordn" ), charIDToTypeID( "Bckw" ) );
desc.putReference( charIDToTypeID( "null" ), ref );
desc.putBoolean( charIDToTypeID( "MkVs" ), false );
executeAction( charIDToTypeID( "slct" ), desc, DialogModes.NO );
}
selectLayerBelow();旧コード 10
var doc=app.activeDocument;
doc.activeLayer=doc.layers.getByName("背景"); 旧コード 11
var doc = activeDocument;
var lay = doc.layers;
doc.activeLayer = lay[lay.length - 1]旧コード 12
if(activeDocument.activeLayer.typename == "ArtLayer" && hasLayerMask() == true){
alert("マスク有り");
}
else{
alert("マスク無し");
}
// レイヤーマスクがあるかどうかの判定
function hasLayerMask() {
var hasLayerMask = false;
try {
var ref = new ActionReference();
var keyUserMaskEnabled = app.charIDToTypeID( 'UsrM' );
ref.putProperty( app.charIDToTypeID( 'Prpr' ), keyUserMaskEnabled );
ref.putEnumerated( app.charIDToTypeID( 'Lyr ' ), app.charIDToTypeID( 'Ordn' ), app.charIDToTypeID( 'Trgt' ) );
var desc = executeActionGet( ref );
if ( desc.hasKey( keyUserMaskEnabled ) ) {
hasLayerMask = true;
}
}catch(e) {
hasLayerMask = false;
}
return hasLayerMask;
}旧コード 13
var doc=app.activeDocument;
var lay=doc.artLayers.getByName("背景");
lay.visible = false; 旧コード 14
//一番下のレイヤーの削除
var layObj = activeDocument.artLayers;
var bgLayer = layObj[layObj.length-1];
bgLayer.remove();旧コード 15
activeDocument.rasterizeAllLayers();旧コード 16
doc = activeDocument;
doc.activeLayer.blendMode = BlendMode.MULTIPLY;
doc.activeLayer.opacity = 10;旧コード 17
var doc = app.activeDocument;
var docName = doc.name;
var docPath = "~/Desktop";//PSDと同じ階層下に書き出したい時はvar docPath = doc.pathにする
var folder = new Folder(docPath);
if (docName.indexOf(".") != -1) {
var basename = docName.match(/(.*)\.[^\.]+$/)[1];
}
else {
var basename = docName;
}
exportPng(doc, folder, basename+ '.gif');
function exportPng(doc, folder, name) {
var file = new File(folder.fsName + "/" + name);
var options = new ExportOptionsSaveForWeb();
options.format = SaveDocumentType.COMPUSERVEGIF;
options.quality = 0;
doc.exportDocument(file, ExportType.SAVEFORWEB, options);
}旧コード 18
openSpecificFile("~/Desktop/sample.psd");
function openSpecificFile(path){
var filename = new File(path);
open(filename);
}旧コード 19
var filePath = decodeURI(File($.fileName));
$.writeln(filePath);旧コード 20
var str ="あいうえお.jsx"
$.writeln(baseName(str));
function baseName(str) {
var base = new String(str).substring(str.lastIndexOf('/') + 1);
if (base.lastIndexOf(".") != -1)
base = base.substring(0, base.lastIndexOf("."));
return base;
}旧コード 21
var doc = activeDocument;
var layers = doc.layers;
var arr = [];
layers[layers.length - 1].isBackgroundLayer = false;//背景レイヤーの解除
doc.suspendHistory("ヒストリー名", "main()");
function main() {
getLayerName();
var list = arr.join("\n");
alert(list);
}
function getLayerName() {
for (var i = 0; i < layers.length; i++) {
var item = layers[i];
var name = item.name;
arr.push(name);
}
re旧コード 22
var doc = activeDocument;
var layers = doc.layers;
var arr = [];
layers[layers.length - 1].isBackgroundLayer = false; //背景レイヤーの解除
doc.suspendHistory("ヒストリー名", "main()");
function main() {
getLayerName(activeDocument);
var list = arr.join("\n");
alert(list);
}
function getLayerName(parent) {
var childLayers = parent.layers;
for (var i = 0; i < childLayers.length; i++) {
if (childLayers[i].typename == "LayerSet") {
getLayerName(childLayers[i]);
}
arr.push(childLayers[i].name);
}
}旧コード 23
var doc = activeDocument;
var lay = doc.layers;
var arr = [];
doc.suspendHistory("ヒストリー名", "main()");
function main() {
var win = new Window("palette", "loading…");
var max = lay.length;
win.progressbar = win.add("Progressbar", [10, 10, 300, 20], 0, max);
win.center();
win.show();
for (var i = 0; i < max; i++) {
arr.push(lay[i].name);
win.progressbar.value = i;
$.sleep(10);//インクリメントする事に処理を少しだけ止める
win.update();//ダイアログの状況を更新
}
win.close();
var list = arr.join("\n");
alert(list);
}旧コード 24
layer = app.activeDocument.activeLayer;
layer.textItem.color.rgb.red = 0;
layer.textItem.color.rgb.green = 255;
layer.textItem.color.rgb.blue = 0;旧コード 25
var words = "あいうえお";
words = words.replace(/(\r\n|\n|\r)/gm," ");
while (words.indexOf(" ") != -1) {words = words.replace(" ", " ")};
var endSpace = /\s$/;
words = words.replace(endSpace, "");
var charCount = words.split(" ").join(" ").length;
alert ("\n "+ charCount + " Characters");旧GitHubコード集は更新していません。以下は個別の完成例・操作目的へ進む導線です。





よくある質問:PhotoshopのJSXの書き方とコード例
この記事のコードは、何のためのものですか?
PhotoshopのExtendScript(.jsx)で、文書の有無、レイヤーの階層、名前の一致、テキスト型、ファイルの取消を確認する、短いコード例です。コピーして全部を連結するコード集ではありません。各例を別ファイルへ保存し、変更する例は自作文書のコピーで確認します。UXPの.psjsとはAPIが異なるため、JSXとPSJSの違いも確認してください。
コードを使う前に、何を確認しますか?
操作ごとに、文書への変更の有無が違います。文書名・レイヤー一覧の読み取りだけなら、背景解除・ラスタライズ・保存は不要です。レイヤー選択は、同じ名前が複数ある場合は停止し、選択状態は変わりますが保存はしません。背景解除・文字色は、レイヤー情報を変更するため、コピーで試し、確認後は元に戻すか、保存せずに閉じます。ファイルを開く場合は、取消・存在・読込失敗を区別し、文書が増えるため対象を再確認します。削除・統合・書き出しは、原本で実行しないでください。
try/catchは、編集を取り消してくれますか?
いいえ。try/catchは失敗を通知する仕組みで、途中の編集を取り消す機能ではありません。即時関数は、変数を関数内にまとめる書き方で、ドラッグ実行を有効にする必須の条件ではありません。
レイヤー名は、どう読みますか?
doc.layersは、最上位のArtLayerとLayerSetを含みます。グループ内を読む場合は、グループ名も先に記録して、子レイヤーへ進む再帰で読みます。出力順はこの走査順です。階層パスに同名があると同じ文字列になるため、固有IDや選択順を表す値には使いません。名前を読むための背景解除は不要です。旧例には、末尾のreと閉じ括弧の不足があり、構文・実行エラーにつながるため、新例には含めていません。
名前でレイヤーを選ぶときの注意点は?
記事の例では、CGM_targetを探す名前に変更し、0件または2件以上なら選択しません。layers.getByNameだけで、同名やグループ内の対象を一律に選べるとは扱わず、範囲と一致件数を明示します。
背景レイヤーや、テキストレイヤーの色を変えるときは?
背景レイヤーを通常レイヤーに変える例は編集操作で、最背面のレイヤーを背景と推定せず、isBackgroundLayerがtrueのArtLayerだけを変更します。背景がない場合は、任意の最背面レイヤーを変更しません。テキストの色を変える例は、ArtLayerかつLayerKind.TEXTを確認してから、文字色を設定します。通常レイヤーやグループには、textItemを読ませません。複数の文字色を持つテキストの保持は、この例の目的に含めず、全体の色を変える操作としてコピーで確認します。
ファイルを開く、実行中のJSXのパスを読む、文字数を数える例の注意点は?
ファイルを選んで開く例は、利用者がファイルを選び、取消なら終了します。存在しても、形式・権限・破損等で開けない場合があるため、エラー表示と実際に開いた文書を照合してください。実行中のJSXのパスは、$.fileNameをFileへ渡し、OS形式のfsNameを読みます。URI表記とOSパスを混ぜたり、すでに復号済みの文字列へdecodeURIを重ねたりしません。文字数を数えるlengthは、UTF-16コード単位で、絵文字等の見た目1文字と一致するとは限りません。旧例はテキストレイヤーから取得せず、固定文字列を処理していたため、レイヤーの文字数を自動取得する説明とは区別します。
[参照]から実行した場合、$.writeln() の出力はPhotoshopの画面に出ないため、パスを見るには alert() を使います(2026年10月17日に確認)。
旧記事の25コードは、どうなりましたか? 実機で確認されていますか?
旧25コードは、後半の参照資料に原文で保持されています。
末尾のre、読取の前の背景解除、固定名/保存先、型確認のないtextItem、エラーをfalseに隠すマスク判定などを含み、新例へ混ぜて実行しないでください。
旧GitHubコード集は更新していません。
新例のうち5本は、2026年10月17日にPhotoshop 2026(27.11.0)とWindows 11 Pro(10.0.26200)で[参照]から実行し、記事の説明どおりに動くことを確かめました。
最上位の名前、背景の解除、ファイルを選んで開く、文字列の長さの4本と、旧25コードは実行していません。
最新はAdobe公式のScripting Guideなどの資料で確認してください。
