Copy link to clipboard
Copied
I want to search and replace content inside text layers (e.g. X -> x). I found this code but it throws an error if there is a text layer in the file that uses the missing font. Is there any way to skip such layers?
Put the following in a file with a `.psjs` extension.
const { app, constants } = require("photoshop");
const doc = app.activeDocument;
for (const lay of doc.layers) {
if (lay.kind === constants.LayerKind.TEXT) {
lay.textItem.contents = lay.textItem.contents.replace(/x/g, "y");
}
}
It won't work if you have nested text layers; otherwise, it should be OK. It runs a RegExp to replace instances of "x" with "y" .
Did you try the Script @Davide_Barranca posted?
Edit: An ESTK-code-version:
// 2024, use it at your own risk;
if (app.documents.length > 0) {
replaceLetterInTypeLayers ("x", "8");
};
////////////////////////////////////
function replaceLetterInTypeLayers (searchText, replaceWith) {
// get number of layers;
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
var applicationDesc = executeActionGet(ref);
var theNumber =
...
Copy link to clipboard
Copied
Have you tried wrapping the operation in a try-clause?
Copy link to clipboard
Copied
oh... i'm not a programmer so i don't know what you're talking about. Currently the script only works on layers selected before running the script. Here is my script and psd file:
function replaceText (searchText, replaceWith)
{
var actionDes1 = new ActionDescriptor();
var actionRef = new ActionReference();
actionRef.putProperty( charIDToTypeID( "Prpr" ), stringIDToTypeID("replace") );
actionRef.putEnumerated( charIDToTypeID( "TxLr" ), charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ) );
actionDes1.putReference( charIDToTypeID( "null" ), actionRef );
var actionDes2 = new ActionDescriptor();
actionDes2.putString( stringIDToTypeID( "find" ), searchText );
actionDes2.putString( stringIDToTypeID("replace"), replaceWith );
actionDes2.putBoolean( stringIDToTypeID( "checkAll" ), false );
actionDes2.putBoolean( charIDToTypeID( "Fwd " ), true );
actionDes2.putBoolean( stringIDToTypeID( "caseSensitive" ), false );
actionDes2.putBoolean( stringIDToTypeID( "wholeWord" ), false );
actionDes2.putBoolean( stringIDToTypeID( "ignoreAccents" ), true );
actionDes1.putObject( charIDToTypeID( "Usng" ), stringIDToTypeID( "findReplace" ), actionDes2 );
executeAction( stringIDToTypeID("replace"), actionDes1, DialogModes.NO );
};
replaceText ("I", "i")
Copy link to clipboard
Copied
function replaceText (searchText, replaceWith) {
try {
var actionDes1 = new ActionDescriptor();
var actionRef = new ActionReference();
actionRef.putProperty( charIDToTypeID( "Prpr" ), stringIDToTypeID("replace") );
actionRef.putEnumerated( charIDToTypeID( "TxLr" ), charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ) );
actionDes1.putReference( charIDToTypeID( "null" ), actionRef );
var actionDes2 = new ActionDescriptor();
actionDes2.putString( stringIDToTypeID( "find" ), searchText );
actionDes2.putString( stringIDToTypeID("replace"), replaceWith );
actionDes2.putBoolean( stringIDToTypeID( "checkAll" ), false );
actionDes2.putBoolean( charIDToTypeID( "Fwd " ), true );
actionDes2.putBoolean( stringIDToTypeID( "caseSensitive" ), false );
actionDes2.putBoolean( stringIDToTypeID( "wholeWord" ), false );
actionDes2.putBoolean( stringIDToTypeID( "ignoreAccents" ), true );
actionDes1.putObject( charIDToTypeID( "Usng" ), stringIDToTypeID( "findReplace" ), actionDes2 );
executeAction( stringIDToTypeID("replace"), actionDes1, DialogModes.NO );
} catch (e) {
alert ("failed")
}
};
replaceText ("I", "x")
Copy link to clipboard
Copied
Thank you very much for this script. But, it won't work if I don't select the text layers first.
Btw, I'm really interested in these, where can I find tutorials on photoshop scripts?
Copy link to clipboard
Copied
Did you try the Script @Davide_Barranca posted?
Edit: An ESTK-code-version:
// 2024, use it at your own risk;
if (app.documents.length > 0) {
replaceLetterInTypeLayers ("x", "8");
};
////////////////////////////////////
function replaceLetterInTypeLayers (searchText, replaceWith) {
// get number of layers;
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
var applicationDesc = executeActionGet(ref);
var theNumber = applicationDesc.getInteger(stringIDToTypeID("numberOfLayers"));
// process the layers;
var theLayers = new Array;
for (var m = 0; m <= theNumber; m++) {
try {
var ref = new ActionReference();
ref.putIndex( charIDToTypeID( "Lyr " ), m);
var layerDesc = executeActionGet(ref);
var layerSet = typeIDToStringID(layerDesc.getEnumerationValue(stringIDToTypeID("layerSection")));
var isBackground = layerDesc.getBoolean(stringIDToTypeID("background"));
// if not layer group collect values;
if (layerSet != "layerSectionEnd" && layerSet != "layerSectionStart" && isBackground != true && layerDesc.hasKey(stringIDToTypeID("textKey")) == true) {
var theName = layerDesc.getString(stringIDToTypeID('name'));
var theID = layerDesc.getInteger(stringIDToTypeID('layerID'));
try {
var actionDes1 = new ActionDescriptor();
var actionRef = new ActionReference();
selectLayerByID(theID, false);
actionRef.putProperty( charIDToTypeID( "Prpr" ), stringIDToTypeID("replace") );
actionRef.putEnumerated( charIDToTypeID( "TxLr" ), charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ) );
actionDes1.putReference( charIDToTypeID( "null" ), actionRef );
var actionDes2 = new ActionDescriptor();
actionDes2.putString( stringIDToTypeID( "find" ), searchText );
actionDes2.putString( stringIDToTypeID("replace"), replaceWith );
actionDes2.putBoolean( stringIDToTypeID( "checkAll" ), false );
actionDes2.putBoolean( charIDToTypeID( "Fwd " ), true );
actionDes2.putBoolean( stringIDToTypeID( "caseSensitive" ), false );
actionDes2.putBoolean( stringIDToTypeID( "wholeWord" ), false );
actionDes2.putBoolean( stringIDToTypeID( "ignoreAccents" ), true );
actionDes1.putObject( charIDToTypeID( "Usng" ), stringIDToTypeID( "findReplace" ), actionDes2 );
executeAction( stringIDToTypeID("replace"), actionDes1, DialogModes.NO );
theLayers.push([theName, theID])
} catch (e) {};
};
}
catch (e) {};
};
return theLayers
};
////////////////////////////////////
// based on code by mike hale, via paul riggott;
function selectLayerByID(id,add){
add = undefined ? add = false:add
var ref = new ActionReference();
ref.putIdentifier(charIDToTypeID("Lyr "), id);
var desc = new ActionDescriptor();
desc.putReference(charIDToTypeID("null"), ref );
if(add) desc.putEnumerated( stringIDToTypeID( "selectionModifier" ), stringIDToTypeID( "selectionModifierType" ), stringIDToTypeID( "addToSelection" ) );
desc.putBoolean( charIDToTypeID( "MkVs" ), false );
try{
executeAction(charIDToTypeID("slct"), desc, DialogModes.NO );
}catch(e){
alert(e.message);
}
};
Copy link to clipboard
Copied
Omg i didn't see it, it's working perfect! Thank you and Davide_Barranca so much!
Copy link to clipboard
Copied
His code is more »future-safe« to boot as it is written as the »new« kind of Photoshop JavaScript (UXP).
Copy link to clipboard
Copied
If that does not work please provide the Script and the file for testing.
Copy link to clipboard
Copied
layerUpdate();
function layerUpdate(){
if(documents.length > 0){
var originalDialogMode = app.displayDialogs;
app.displayDialogs = DialogModes.ERROR;
var originalRulerUnits = preferences.rulerUnits;
try{
var docRef = activeDocument;
preferences.rulerUnits = Units.POINTS;
for(var i = 0; i < docRef.artLayers.length; i++){
var LayerRef = docRef.artLayers[i];
if(LayerRef.kind == LayerKind.TEXT){
var TextRef = LayerRef.textItem;
var layerText = TextRef.contents;
var newText = layerText.replace('x', 'y');
TextRef.contents= newText;
}
}
preferences.rulerUnits = originalRulerUnits;
app.displayDialogs = originalDialogMode;
}
catch(e){
}
}
}
Copy link to clipboard
Copied
thank you, but it's not working 😞
Copy link to clipboard
Copied
Put the following in a file with a `.psjs` extension.
const { app, constants } = require("photoshop");
const doc = app.activeDocument;
for (const lay of doc.layers) {
if (lay.kind === constants.LayerKind.TEXT) {
lay.textItem.contents = lay.textItem.contents.replace(/x/g, "y");
}
}
It won't work if you have nested text layers; otherwise, it should be OK. It runs a RegExp to replace instances of "x" with "y" .
Copy link to clipboard
Copied
Dang, I suppose it is time to specify jsx or psjs when posting Scripts …
Copy link to clipboard
Copied
LOL it's about time 😁