Copy link to clipboard
Copied
Hi there,
Let us say I have six Photoshop files: 1.psd, 2.psd, ..., 6.psd. All of these files contain the word “LoremIpsum” in random text layers, within each document. Is there a way I can search for “LoremIpsum” in all documents and replace it with “Dolor Sit Amet”, all in one go? This is just an example, I need to replace various words, not just one.
I have tried "batch find and replace" software (including powerful tools like Power Grep) but they do not work with psd files… Is there a javascript of external plugin for this kind of task?
Thanks!
Copy link to clipboard
Copied
Are the individual Type Layers uniform or do they combine text elements of any variation (size, font, spacing, …)?
Copy link to clipboard
Copied
Thank you for the script! Will try to run it ASAP. The Type Layers are not uniform, font size, color, etc varies... Will the script work in this case?
Copy link to clipboard
Copied
No, it won’t or rather is will destroy those variations.
Copy link to clipboard
Copied
Will let you know what happens... Thank you!!
Copy link to clipboard
Copied
You were right, of course! Your script works perfectly, but it ruins the formatting of documents. Nonetheless, thank you! Maybe I will get to a solution from here.
Copy link to clipboard
Copied
Document Object Model Scripting can not take care of that formatting fur parts of a Type Layer’s contents.
Action Manager code can, but it is not that easy.
Do you know how many factors do vary?
Copy link to clipboard
Copied
There are 5 font variations within the documents. If it helps, I can list the font type, size, color, etc for each variation.
Copy link to clipboard
Copied
What are the other two variable properties (apart from font, size and color)?
Copy link to clipboard
Copied
When it comes to the characters I have these variations:
Font Family
Font Style (Regular, Italic, Bold, etc)
Font Size
Font Color
* Font tracking (?) - when font is justified, Photoshop assigns a value for this (I belive it is the spacing between characters).
These variations are for the characters. There are also a lot of variations when it comes to paragraphs.
I do start to believe that this is too much of a handful.
Copy link to clipboard
Copied
Apod42 wrote:
I do start to believe that this is too much of a handful.
It will be a handful. And how it's done will depend on which version of Photoshop you are using. It will require using Action Manager and adjusting not only the text string but either the text ranges( CS5 of lower ) or the text and paragraph ranges( CS6 or higher ).
The text descriptor is massive and even as experienced as I am with scripting I would do this manually.
Copy link to clipboard
Copied
I think your script might still be the solution. I will just make some changes to the text layers in my photoshop files (break them into multiple text layers) and everything should work fine.
Please, how would the script look if beside replacing "LoremIpsum" with "Dolor Sit Amet" I would also like to replace in the same go the words "Sun" with "Moon" and "Cold" with "Hot" ?
Thank you!
Copy link to clipboard
Copied
var theArray1 = ["LoremIpsum", "Sun", "Cold"];
var theArray2 = ["Dolor Sit Amet", "Moon", "Hot"];
Copy link to clipboard
Copied
Thank you! Wish you all the best!
Copy link to clipboard
Copied
Me again... If I used the script above (or a variant of it) to batch search/replace in just ONE Photoshop document, not multiple documents, would it still ruin font formatting?
Is there any other script for batch search/replace inside one document, using Photoshop's built in tool?
And is there a way to get the words in
var theArray1 = ["LoremIpsum", "Sun", "Cold"];
var theArray2 = ["Dolor Sit Amet", "Moon", "Hot"];
from an external .txt file, encoded in UTF-8? JavaScript just can't handle diacritics....
Thank you!
Copy link to clipboard
Copied
Seems »Find and Replace Text« is actually Scrip-able.
// replace text elements in type layers;
// 2013, use it at your own risk;
#target photoshop
if (app.documents.length > 0) {
for (var n = 0; n < app.documents.length; n++) {
app.activeDocument = app.documents
; app.activeDocument.suspendHistory("replace text", "main()")
}
};
// the opertation;
function main () {
var myDocument = app.activeDocument;
var theArray1 = ["TEST", "test"];
var theArray2 = ["HAHAHA", "LALALA"];
for (var b = 0; b < theArray1.length; b++) {
replaceText (theArray1, theArray2)
}
};
////// reoplace text //////
function replaceText (replaceThis, replaceWith) {
// =======================================================
var idreplace = stringIDToTypeID( "replace" );
var desc22 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref3 = new ActionReference();
var idPrpr = charIDToTypeID( "Prpr" );
var idreplace = stringIDToTypeID( "replace" );
ref3.putProperty( idPrpr, idreplace );
var idTxLr = charIDToTypeID( "TxLr" );
var idOrdn = charIDToTypeID( "Ordn" );
var idAl = charIDToTypeID( "Al " );
ref3.putEnumerated( idTxLr, idOrdn, idAl );
desc22.putReference( idnull, ref3 );
var idUsng = charIDToTypeID( "Usng" );
var desc23 = new ActionDescriptor();
var idfind = stringIDToTypeID( "find" );
desc23.putString( idfind, replaceThis );
var idreplace = stringIDToTypeID( "replace" );
desc23.putString( idreplace, replaceWith );
var idcheckAll = stringIDToTypeID( "checkAll" );
desc23.putBoolean( idcheckAll, true );
var idFwd = charIDToTypeID( "Fwd " );
desc23.putBoolean( idFwd, true );
var idcaseSensitive = stringIDToTypeID( "caseSensitive" );
desc23.putBoolean( idcaseSensitive, false );
var idwholeWord = stringIDToTypeID( "wholeWord" );
desc23.putBoolean( idwholeWord, false );
var idignoreAccents = stringIDToTypeID( "ignoreAccents" );
desc23.putBoolean( idignoreAccents, true );
var idfindReplace = stringIDToTypeID( "findReplace" );
desc22.putObject( idUsng, idfindReplace, desc23 );
executeAction( idreplace, desc22, DialogModes.NO );
};
Copy link to clipboard
Copied
To answer some questions more directly:
Me again... If I used the script above (or a variant of it) to batch search/replace in just ONE Photoshop document, not multiple documents, would it still ruin font formatting?
The handling of all open documents has nothing to do with the difficulties of Scripting Type Layers.
Is there any other script for batch search/replace inside one document, using Photoshop's built in tool?
Above Script uses the feature and it seems to not destroy varying formatting, if you want to run it on only the active document delete the lines
for (var n = 0; n < app.documents.length; n++) {
app.activeDocument = app.documents
;
and the corresponding closing bracket.
Copy link to clipboard
Copied
I think that this conversation (and of course your know-how), has produced an amazing result. I belive that many people can make use of this script, I see that already Google indexed this page I have tested it extensively, and it works flawless, it's fast, and if I encode the .jsx file containing the script in UTF-8 it handles special characters (diacritics in my case) just fne.
There is still one unanswered question (of minimal importance):
Is there a way to get the words in
var theArray1 = ["TEST", "test"];
var theArray2 = ["HAHAHA", "LALALA"];
from an external .txt file? So there is no need to modify the script for each operation, just modify the external file.
Thank you again for all your time!
Copy link to clipboard
Copied
You’re welcome, advice given here is free.
If you want to donate something nonetheless you could do so over at
Many of the same people used to contribute there as here and I for one have benefitted considerably from their generous advice on Scripting issues.
A Script can read (or create) txt files, but I do not have a lot of experience with this.
This might work (amend the line »var theTexts = readPref ("….txt", false);« according to your txt-file’s path):
// replace text elements in type layers;
// 2013, use it at your own risk;
#target photoshop
if (app.documents.length > 0) {
for (var n = 0; n < app.documents.length; n++) {
app.activeDocument = app.documents
; app.activeDocument.suspendHistory("replace text", "main()")
}
};
// the opertation;
function main () {
var myDocument = app.activeDocument;
var theTexts = readPref ("….txt", false);
var theArray1 = theTexts.slice(0, Math.round(theTexts.length/2));
var theArray2 = theTexts.slice(Math.round(theTexts.length/2), theTexts.length);
alert (theArray1.join("\n")+"\n\n\n"+theArray2.join("\n"))
for (var b = 0; b < theArray1.length; b++) {
replaceText (theArray1, theArray2)
};
};
////// reoplace text //////
function replaceText (replaceThis, replaceWith) {
// =======================================================
var idreplace = stringIDToTypeID( "replace" );
var desc22 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref3 = new ActionReference();
var idPrpr = charIDToTypeID( "Prpr" );
var idreplace = stringIDToTypeID( "replace" );
ref3.putProperty( idPrpr, idreplace );
var idTxLr = charIDToTypeID( "TxLr" );
var idOrdn = charIDToTypeID( "Ordn" );
var idAl = charIDToTypeID( "Al " );
ref3.putEnumerated( idTxLr, idOrdn, idAl );
desc22.putReference( idnull, ref3 );
var idUsng = charIDToTypeID( "Usng" );
var desc23 = new ActionDescriptor();
var idfind = stringIDToTypeID( "find" );
desc23.putString( idfind, replaceThis );
var idreplace = stringIDToTypeID( "replace" );
desc23.putString( idreplace, replaceWith );
var idcheckAll = stringIDToTypeID( "checkAll" );
desc23.putBoolean( idcheckAll, true );
var idFwd = charIDToTypeID( "Fwd " );
desc23.putBoolean( idFwd, true );
var idcaseSensitive = stringIDToTypeID( "caseSensitive" );
desc23.putBoolean( idcaseSensitive, false );
var idwholeWord = stringIDToTypeID( "wholeWord" );
desc23.putBoolean( idwholeWord, false );
var idignoreAccents = stringIDToTypeID( "ignoreAccents" );
desc23.putBoolean( idignoreAccents, true );
var idfindReplace = stringIDToTypeID( "findReplace" );
desc22.putObject( idUsng, idfindReplace, desc23 );
executeAction( idreplace, desc22, DialogModes.NO );
};
////// read prefs file //////
function readPref (thePath, binary) {
if (File(thePath).exists == true) {
var file = File(thePath);
file.open("r");
if (binary == true) {file.encoding= 'BINARY'};
var theText = file.read();
file.close();
return String(theText).split(",")
}
};
In this case the comma is used to split the text into Strings in Arrays, if your search/replace texts include commas you could use something else, I guess.
Copy link to clipboard
Copied
Thank you! I will test with this script today, will also make a donation to the forum you indicated!
Copy link to clipboard
Copied
This is the body of the external file:
Sun,Moon
It replaces Sun with Moon. I just don't get how should I format the external text file to add more words to replace. Add for example Cold,Hot and Day,Night...
Copy link to clipboard
Copied
Day,Cold,Night,Hot
Copy link to clipboard
Copied
I get it now, with a blank line (space) makes logical order... Will never think as a programmer
Copy link to clipboard
Copied
Actually my approach may be a bit clumsy (not a programmer, either), listing the pairs might be more elegant; the for-clause
for (var b = 0; b < theArray1.length; b++) {
would have to be changed a bit then, though.
Copy link to clipboard
Copied
More questions, only if you find the time...
By default, Photoshop's search tool searches only visible text layers. If a layer is hidden, no search is performed on that layer. Your script above acts in the same way. Is there a way to make the script bypass Photoshop's default, and also search (and replace) in hidden layers?
For anyone reading this in the future; there is a way to search hidden layers. Go to Window > Layer Comps. Select your hidden text layers, make them visible, and create a new layer comp (think of it as a document within a document). Do a layer comp for your main document also. When you search, select the comp with all the text layers visible. Then you can switch with just a click to your main version of the document. Sounds complicated, it's straightforward. Just remember about "Layer Comps".
Question two. The alert in your last script pops up like this:
You are about to search and replace: (doesn't actually say this, this line is my great addition to your script )
Sun
Day
Hot
Moon
Night
Cold
Is there a way to make the alert like this?
You are about to search and replace:
Sun
Moon
Day
Night
Hot
Cold
I guess this is this snippet of code here:
alert (theArray1.join("\n")+"\n\n\n"+theArray2.join("\n"))
All the best!