Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
2

Script to find and replace text layers and ignore missing fonts text layers.

Explorer ,
Jan 17, 2024 Jan 17, 2024

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?

 

 

 

Nahidku_0-1705545353400.png

 

TOPICS
Actions and scripting
1.0K
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 2 Correct answers

Engaged , Jan 19, 2024 Jan 19, 2024

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" .

 

 

Translate
Community Expert , Jan 21, 2024 Jan 21, 2024

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 = 
...
Translate
Adobe
Community Expert ,
Jan 18, 2024 Jan 18, 2024

Have you tried wrapping the operation in a try-clause? 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Jan 18, 2024 Jan 18, 2024

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")

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jan 18, 2024 Jan 18, 2024
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")
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Jan 20, 2024 Jan 20, 2024

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?

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jan 21, 2024 Jan 21, 2024

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); 
}
};

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Jan 21, 2024 Jan 21, 2024

Omg i didn't see it, it's working perfect! Thank you and Davide_Barranca so much!

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jan 21, 2024 Jan 21, 2024
LATEST

His code is more »future-safe« to boot as it is written as the »new« kind of Photoshop JavaScript (UXP). 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jan 18, 2024 Jan 18, 2024

If that does not work please provide the Script and the file for testing. 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jan 18, 2024 Jan 18, 2024
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){
            }
        }
    }
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Jan 18, 2024 Jan 18, 2024

thank you, but it's not working 😞

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Jan 19, 2024 Jan 19, 2024

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" .

 

 

Davide Barranca - PS developer and author
www.ps-scripting.com
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jan 19, 2024 Jan 19, 2024

Dang, I suppose it is time to specify jsx or psjs when posting Scripts … 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Jan 19, 2024 Jan 19, 2024

LOL it's about time 😁

Davide Barranca - PS developer and author
www.ps-scripting.com
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines