Skip to main content
Participant
March 12, 2020
Question

Find and replace text content including non-visible layers

  • March 12, 2020
  • 2 replies
  • 739 views

Hi Everyone, i am very new to photoshop scripting. I want to find and replace a text content in all layers. So i used Find and Replace Text tool. But it is replacing the text only in visible layers and also taking long time if i have many layers(Ex:more than 1000 layers).

Here i have wrote a script to achieve this requirement.

 

#target photoshop

var textLayersCount = 0;
var AllLayersCount = 0;
FindAndReplaceTextInAllLayers("Wins", "Eins");
alert("There are totally " + AllLayersCount + " layers and the total Text layers count is : " + textLayersCount);

function FindAndReplaceTextInAllLayers(fin, replac)
{
var ref1 = new ActionReference();
var count;
ref1.putEnumerated(charIDToTypeID('Dcmn'), charIDToTypeID('Ordn'), charIDToTypeID('Trgt'));
count = executeActionGet(ref1).getInteger(charIDToTypeID('NmbL'));
AllLayersCount = count;
for (var i = count; i >= 1; i--)
{
var ref2 = new ActionReference();
ref2.putIndex(charIDToTypeID('Lyr '), i);
var desc = executeActionGet(ref2); // Access layer index #i

var layerSection = typeIDToStringID(desc.getEnumerationValue(stringIDToTypeID('layerSection')));
if (layerSection == 'layerSectionStart' || layerSection == 'layerSectionEnd') { // Group start and end
AllLayersCount--;
continue;
}
var layerName = desc.getString(stringIDToTypeID("name"));
//var layerId = desc.getInteger(charIDToTypeID("LyrI"));

//var visible = desc.getBoolean(stringIDToTypeID("visible"));
var isTextLayer =desc.getInteger(stringIDToTypeID("layerKind"));

//AllLayerNames.push(layerName);
//AllLayerVisibleState.push(visible);
if(isTextLayer == 3)
{
textLayersCount++;

var descText = desc.getObjectValue(stringIDToTypeID('textKey'));
var contents = descText.getString(stringIDToTypeID('textKey'));
//var newCon = contents.replace(/Wins/g, 'Eins');
var newCon = contents.replace(fin, replac);

(desc2 = new ActionDescriptor()).putString(stringIDToTypeID( "Txt " ), newCon)
//desc70.putString( charIDToTypeID( "Txt " ), newCon);
desc.putObject(charIDToTypeID( "Usng" ), stringIDToTypeID( "setd" ), desc2 );

executeAction(stringIDToTypeID('setd'), desc, DialogModes.NO );
}
}
}

 

But the above script got some error and  i dont know to how proceed further. Please help!!

    This topic has been closed for replies.

    2 replies

    Stephen Marsh
    Community Expert
    Community Expert
    March 12, 2020

    I encountered this problem with your script:

     

    - The command “<unknown>” is not currently available.

    Line: 38

    ->              executeAction(stringIDToTypeID('setd'), desc, DialogModes.NO);

    rajesh024Author
    Participant
    March 12, 2020

    Stephen_A_Marsh Thank you so much for your great time. Will work on this and let you know asap.

    Stephen Marsh
    Community Expert
    Community Expert
    March 12, 2020

    This code will replace all visible and invisible text layer occurrences of the isolated word "Dog" or "dog" or "DOG" or "dOG" with "Cat":

     

    https://community.adobe.com/t5/photoshop/javascript-find-and-replace-text-in-photoshop/m-p/10847173

     

     

    var doc = app.activeDocument;
    for (var i = 0; i < doc.layers.length; i++) {
       try {
          doc.activeLayer = doc.layers[i];
          // Find = Dog, Replace = Cat
          // g = global, i = case insensitve
          if (app.activeDocument.activeLayer.kind == LayerKind.TEXT) {
             doc.activeLayer.textItem.contents = doc.activeLayer.textItem.contents.replace(/\bDog\b/gi, 'Cat');
           }
       } catch (e) {}
    }

     

     

    The problem is that it will also make invisible layers visible.

    rajesh024Author
    Participant
    March 12, 2020

    Hi Stephen_A_Marsh,

    This script is working. But there are two concerns.

    1) Script is not checking the layers in groups(layersets).

    2) Script is taking long time to replace the content since i want to check more that 1000 layers 😞

     

    That's why I have tried ActionReference(). Kindly help!!

    Stephen Marsh
    Community Expert
    Community Expert
    March 13, 2020

    Is this hybrid DOM+AM code any faster (taken from the linked topic above)?

     

    var doc = app.activeDocument;  
    for(var i=0;i<doc.layers.length;i++){  
         try{  
              doc.activeLayer = doc.layers[i];
              // Find = Dog, Replace = Cat 
              replace("Dog", "Cat", true, true, false, false, false); // Change the 3rd boolean to true for case sensitive match  
         }  
         catch(e){}  
    }  
      
    function replace(find, replace, checkAll, forward, caseSensitive, wholeWord, ignoreAccents) {
    	var descriptor = new ActionDescriptor();
    	var descriptor2 = new ActionDescriptor();
    	var reference = new ActionReference();
    	reference.putProperty( stringIDToTypeID( "property" ), stringIDToTypeID( "replace" ));
    	reference.putEnumerated( stringIDToTypeID( "textLayer" ), stringIDToTypeID( "ordinal" ), stringIDToTypeID( "allEnum" ));
    	descriptor.putReference( charIDToTypeID( "null" ), reference );
    	descriptor2.putString( stringIDToTypeID( "find" ), find );
    	descriptor2.putString( stringIDToTypeID( "replace" ), replace );
    	descriptor2.putBoolean( stringIDToTypeID( "checkAll" ), checkAll ); // Boolean #1
    	descriptor2.putBoolean( stringIDToTypeID( "forward" ), forward ); // Boolean #2
    	descriptor2.putBoolean( stringIDToTypeID( "caseSensitive" ), caseSensitive ); // Boolean #3
    	descriptor2.putBoolean( stringIDToTypeID( "wholeWord" ), wholeWord ); // Boolean #4
    	descriptor2.putBoolean( stringIDToTypeID( "ignoreAccents" ), ignoreAccents ); // Boolean #5
    	descriptor.putObject( stringIDToTypeID( "using" ), stringIDToTypeID( "findReplace" ), descriptor2 );
    	executeAction( stringIDToTypeID( "replace" ), descriptor, DialogModes.NO );
    }

     

    The function with the find/replace bit is AM code, so perhaps faster than DOM on many layers, but the loop code is still DOM code, so if you have another way to iterate this or to use the AM code function in a different manner that could help. I'm just a beginner at scripting, so I'm hoping that somebody else can chime in here...