Javascript find and replace text in photoshop

New Here ,
Jan 09, 2020 Jan 09, 2020

Copy link to clipboard

Copied

Hi there,

 

I have been trying to write a script that finds and replaces certain text files in photoshop.

For example: There was a large man called (Name) with a big burly beard.

I have created an action using find and replace text to achieve this, but in the process of trying to automate this process by converting it to javascript using Xtools it no longer works.

Any help pointing me in the right direction would be super useful.

 

Cheers,

 

Marty

 

#target photoshop

//

// Action1.jsx

//

 

//

// Generated Fri Jan 10 2020 12:56:37 GMT+1100

//

 

cTID = function(s) { return app.charIDToTypeID(s); };

sTID = function(s) { return app.stringIDToTypeID(s); };

 

//

//==================== Action 1 ==============

//

function Action1() {

  // Replace All

  function step1(enabled, withDialog) {

    if (enabled != undefined && !enabled)

      return;

    var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);

    var desc1 = new ActionDescriptor();

    var ref1 = new ActionReference();

    ref1.putProperty(cTID('Prpr'), sTID("replace"));

    ref1.putEnumerated(cTID('TxLr'), cTID('Ordn'), cTID('Al  '));

    desc1.putReference(cTID('null'), ref1);

    var desc2 = new ActionDescriptor();

    desc2.putString(cTID('find'), "(Name)");

    desc2.putString(sTID("replace"), "John");

    desc2.putBoolean(sTID("checkAll"), true);

    desc2.putBoolean(cTID('Fwd '), true);

    desc2.putBoolean(sTID("caseSensitive"), false);

    desc2.putBoolean(sTID("wholeWord"), false);

    desc2.putBoolean(sTID("ignoreAccents"), true);

    desc1.putObject(cTID('Usng'), sTID("findReplace"), desc2);

    executeAction(sTID('replace'), desc1, dialogMode);

  };

 

  step1();      // Replace All

};

 

 

 

//=========================================

//                    Action1.main

//=========================================

//

 

Action1.main = function () {

  Action1();

};

 

Action1.main();

 

// EOF

 

"Action1.jsx"

// EOF

 

TOPICS
Actions and scripting, How to

Views

855

Likes

Translate

Translate

Report

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
Most Valuable Participant ,
Jan 09, 2020 Jan 09, 2020

Copy link to clipboard

Copied

Yes the action conversion to Javascript by xtool does not work where the action does. 

The Scriptlistener Code works and the cleaned up code by Clean SL works.  Here is Dog to Cat

 

#target photoshop
//
// DoToCat.jsx
//
// =======================================================
// =======================================================
replace("Dog", "Cat", true, true, false, false, false);
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 );
	descriptor2.putBoolean( stringIDToTypeID( "forward" ), forward );
	descriptor2.putBoolean( stringIDToTypeID( "caseSensitive" ), caseSensitive );
	descriptor2.putBoolean( stringIDToTypeID( "wholeWord" ), wholeWord );
	descriptor2.putBoolean( stringIDToTypeID( "ignoreAccents" ), ignoreAccents );
	descriptor.putObject( stringIDToTypeID( "using" ), stringIDToTypeID( "findReplace" ), descriptor2 );
	executeAction( stringIDToTypeID( "replace" ), descriptor, DialogModes.NO );
}

 

JJMack

Likes

Translate

Translate

Report

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
Adobe Community Professional ,
Jan 10, 2020 Jan 10, 2020

Copy link to clipboard

Copied

Thanks JJMack!

 

In case it was not obvious, the code in the previous post works on an active (text) layer.

 

Adding some extra code, all text layers that contain Dog can be replaced with Cat – this is just a quick hack, I have not used a conditional to only process text layers:

 

 

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

 

 

 

Likes

Translate

Translate

Report

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
Adobe Community Professional ,
Jan 10, 2020 Jan 10, 2020

Copy link to clipboard

Copied

Here is the DOM code instead of AM code:

 

 

app.activeDocument.activeLayer.textItem.contents = app.activeDocument.activeLayer.textItem.contents.replace(/Dog/gi, 'Cat'); // g = global, i = case insensitve

 

 

While this version will change all text layers:

 

 

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

 

 

EDIT: I forgot to add, if you wish to isolate the word Dog by itself as a "whole word" and not have it included within another word such as doggedly, then use the following modification, adding a \b either side of the target word:

 

 

 

 

.replace(/\bDog\b/gi, 'Cat');

 

 

 

 

 

Likes

Translate

Translate

Report

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
Adobe Community Professional ,
Jan 10, 2020 Jan 10, 2020

Copy link to clipboard

Copied

Hi, here's a stupid non-coder question: is it hard to create a panel, with input fields that would do this job?

That sort of panels exists in a rich ecosystem for After Effects (Aescripts and others) but I find it rare for Photoshop, is it harder to create a panel? the market is bigger...

Likes

Translate

Translate

Report

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
Adobe Community Professional ,
Jan 10, 2020 Jan 10, 2020

Copy link to clipboard

Copied

It depends on the use/expectation for the script...

 

As part of an automation project, a GUI would get in the way, so either the text strings or a variable would be hard coded into a broader script so that no human interaction was required, so no GUI in this case.

 

However, anything GUI related is harder. It is simple enough to use a couple of built-in prompts to ask for user input, although one  may then need to add error checking. Next level up is to write scriptUI for a "runtime" window and buttons, input fields etc. This takes more work... The code would probably be at least double or greater, here is an example... 49 lines of code without a "simple" scriptUI window and 92 lines of code with the GUI:

 

https://community.adobe.com/t5/photoshop/script-to-rename-file-in-photshop-before-naming/m-p/1048476...

 

Then if you wish to have a constantly "floating panel" just like a native panel/window, then you need to do a whole lot more work with proper "extensions/panels", which is a lot of extra work.

 

But it is not so much the number of lines or amount of code, it is how long does all of this take to build and debug/test. As these scripts are offered freely without any payment for services rendered, they are often built to get the job done with the least amount of time/work. You get more than what you pay for, but payment would perhaps get you more! 

Likes

Translate

Translate

Report

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
Most Valuable Participant ,
Jan 10, 2020 Jan 10, 2020

Copy link to clipboard

Copied

If you want a Panel you do not even need a script. Just record an Action and make the Find and replace interactive. Find and Replace has a dialog. However, An interactive Step is not appropriate for a Batch Script.  A Batch Find and replace Script would be possible. But would require a Script Dialog or and HTML photoshop extension panel. These require a lot more Script coding. And also require coding to make the script a batch process.  I also do not know why the Xtool converted script does not work. The Action I converted does a Global Dog to Cat change.  The Action Works the Xtool conversion does not. If the Xtool conversion changes an  Active Text Layer the conversion does not work like the action that converted all text Layer the have Dog to Cat.  No searching for text layer to make them active should be required.  The Action Manager Code recorder by Adobe Scriptlistener Plug-in for the global Find and Replace step works.

 

An interactive action would shoe this the Text used recording in the action would be displayed in the dialog and would have toe be changed by the user. So record something like A to B not Dog to Cat the options can also be changed.  A script dialog would need to be more complex if you want to support all the Find Replace Text tool options.

image.png

 

 

JJMack

Likes

Translate

Translate

Report

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
New Here ,
Feb 18, 2021 Feb 18, 2021

Copy link to clipboard

Copied

Sorry I'm try  to use this script and this is the message: 

The command "Replace All" is not currently available

Any idea how  to  resolve that?? 😞

Likes

Translate

Translate

Report

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
Adobe Community Professional ,
Feb 18, 2021 Feb 18, 2021

Copy link to clipboard

Copied

LATEST

In order for this to work, any text layer must be active (selected). This is a long-standing bug for this command when used in Actions / Scripts.

Likes

Translate

Translate

Report

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