
Copy link to clipboard
Copied
Hi there,
Can anybody tell me if it's possible to JavaScript Illustrators Find And Replace text function?
I know it's possible in InDesign but I can't find anything for Illustrator.
Many Thanks,
Nik
1 Correct answer
Hi Nik, no need to dig down to words, we can search the whole textFrame.contents. Here's a working sample
...var active_doc = app.activeDocument;
var search_string = /blah/gi; // g for global search, remove i to make a case sensitive search
var replace_string = "lalala";
var text_frames = active_doc.textFrames;
if (text_frames.length > 0)
{
for (var i = 0 ; i < text_frames.length; i++)
{
var this_text_frame = text_frames;
var new_string = this_text_frame.contents.replace(search
Explore related tutorials & articles
Copy link to clipboard
Copied
there's no such feature but it is doable, you have to loop thru all TextFrames and work each of their contents.

Copy link to clipboard
Copied
Hi Carlos,
Thanks again for your swift response even thought it's not the answer I hoped for!!
As you've suggested as a process I suppose I would need to:
Create an array of every text frame of the active doc.
Repeat with every text frame and create an array of every word in that text frame.
Repeat with every word and put and If statement in to catch a search string match.
Replace the matching word with replace string.
Quite straight forward for me in Applescript but another adventure in JavaScript
Thanks,
Nik

Copy link to clipboard
Copied
Hi Carlos,
I'm afraid I'm a little stumped and wander if you or anybody else can help?
I have written the code to search for a matching string:
var active_doc = app.activeDocument
var search_string = "blah"
var text_frames = active_doc.textFrames
if (text_frames.length > 0)
{
for (var i = 0 ; i < text_frames.length; i++)
{
var this_text_frame = text_frames;
var this_text_frame_word_count = this_text_frame.words.length;
//alert(this_text_frame_word_count);
for (var j = 0 ; j < this_text_frame_word_count; j++)
{
var this_word = this_text_frame.words
//alert(this_word);
if ( this_word == search_string)
{
alert(this_word+" matches "+search_string);
}
}
}
}
But I'm afraid I'm stuck with how I now replace the string. Could somebody please point me in the right direction.
Thanks again,
Nik
Copy link to clipboard
Copied
Hi Nik, no need to dig down to words, we can search the whole textFrame.contents. Here's a working sample
var active_doc = app.activeDocument;
var search_string = /blah/gi; // g for global search, remove i to make a case sensitive search
var replace_string = "lalala";
var text_frames = active_doc.textFrames;
if (text_frames.length > 0)
{
for (var i = 0 ; i < text_frames.length; i++)
{
var this_text_frame = text_frames;
var new_string = this_text_frame.contents.replace(search_string, replace_string);
if (new_string != this_text_frame.contents)
{
this_text_frame.contents = new_string;
}
}
}
Copy link to clipboard
Copied
Hello Carlos, It works well... thanks for sharing.
1. Is it possible to make Italics or change font on particular letters of the new string?
2. We can see special characters like "Thin space", "Hair space", etc,. in Find and Replace. Can we utilise these characters in your script?
Praveen
Copy link to clipboard
Copied
Hi Praveen, I couldn't find how to do italics, but if you create a Character Style in the GUI it can be applied to text via Scripting
var italicStyle = active_doc.characterStyles["italics"];
italicStyle.applyTo(this_text_frame.textRange);
the font can be changed with
this_text_frame.textRange.characterAttributes.textFont = app.textFonts.getByName("Aparajita");
Thin Space and Hair Space can be searched with
var search_string = /\s/gi; // \s finds white space characters
Copy link to clipboard
Copied
Hi Carlos,
Can i use Hair space in replace string? I tried, but not working.
var replace_string = "/\s/";
problem with the syntax i think so.
Copy link to clipboard
Copied
no you cannot, /\s/ doesn't find Hair space specifically, it simply finds a space of any kind.
Copy link to clipboard
Copied
Hello CarlosCanto,
as a supplement for your post #8.
It is possible to search for some spaces of special kind – search for the Unicode of the characters e.g. like this:
open a new document and zoom out, then start the script (when the script is running, observe the new textframe; CS3 at left bottom, CS5 at left top of artboard)
// FindSearchReplaceSomeSpecialSpaces.jsx
var aText = app.activeDocument.textFrames.add();
with (aText) {
contents = "Thinspace \u2013\u2013\u003e\u2009\u003c\u2013\u2013 Hairspace \u2013\u2013\u003e\u200A\u003c\u2013\u2013"
}
redraw();
alert(aText.contents);
aTCon = aText.contents;
aText.contents = replaceSpecialSpace(aTCon);
alert("Achtelgeviert ersetzt durch \u0040\r1/24-Geviert ersetzt durch \u00a9")
function replaceSpecialSpace() {
aTCon = aTCon.replace( /\u2009/g, '\u0040' ); // Achtelgeviert --> @
aTCon = aTCon.replace( /\u200A/g, '\u00a9' ); // 1/24-Geviert --> ©
aTCon = aTCon.replace( /[A-Z]+/gi, "replaced:" );
return aTCon;
}
Have fun

Copy link to clipboard
Copied
Hi Carlos,
Many Thanks for your feedback and apologies for not replying sooner but I've been piecing together my code and have finally finished it with your help.
It also looks as though this post has been helpful for others users which is great.
When I first started writing Applescript it was very reassuring to know that on resources like Macscripter there where people willing to offer advice.
Now I'm a noobie at JavaScript it's encouraging to know there're people in other scripting communities that are also willing to help.
Many Thanks agian,
Nik
Copy link to clipboard
Copied
you're welcome, I totally agree, I myself learned most of what I know about JavaScript from the users that contribute to this forum.
Copy link to clipboard
Copied
Carlos, If I needed a script to simply open the "Find and Replace" dialog box in Illustrator CS5 then simply close it or selecte the "Done" botton. Would that be an easy script?
My problem is that when I create "Actions" that will "Find and Replace" what I need it to, it is buggy. I would like to run the action that I have recorded with the dialogs turned off (so they will not pop up) so they will just run what I recorded the first time. But if I do this then quit out of Illustrator & relaunch it the next time I try to run that recorded action Illustrator will bomb out. So, the only fix I could find is to have the first "Find and Replace" action with the dialog set to pop up (see 1st Find And Replace in image) then we simply click the done botton, not have to type anything inside it & then the rest of the "Find adn Replace" "Actions" will run correct, with out their dialog boxes popping up, & will not crash Illustrator. It seems that for the "Actions" to work you simply need to open the "Find and Replace" & close it then the "Actions" will work fine untill you quit out of Illustrator again.
Copy link to clipboard
Copied
why not make a keyboard shortcut to it? would that work?
Copy link to clipboard
Copied
I'm not sure the easiest answer yet but I do have a keyboard short cut to both the "Action" & to open "Find and Replace" but I'm not sure how that will fix the problem because you can not record quick keys in "Actions" I also can not figure out a way to record in "actions" to close the find & replace unless you turn off the option for the dialog box to pop up.
Copy link to clipboard
Copied
Maybe a script that will run every time Illustrator CS5 is launched & it will simply open the "Find and Replace" & then close it. In this case everything will be automatic & the "Action" will not crash Illustrator.
Copy link to clipboard
Copied
I meant a short cut to bring up the Find dialog manually, not to record it in the action. then you dismiss it manually also, then you run your actions. Is that an option?
Copy link to clipboard
Copied
Yes but thats the same difference as having the first "Find and Replace" dialog coming up & manually dismissing that. I'm trying to have it work where we select the above attached script & it just runs every time even if we just relaunched Illustrator.
Copy link to clipboard
Copied
if you're on Windows, there might be hope.
Copy link to clipboard
Copied
Most of the computers here are Mac only a few PC's. But if there is a Java version that can run on both or for the macs I will need to create a separate AppleScript.
Copy link to clipboard
Copied
on Windows I have made a couple of Prototypes using something called SendKeys, a function in VB, it is never recomended to use because it is not reliable. So if I made a VB script and it works in Windows, maybe there's a Applescript version of it? and you can rewrite in AS?
not supported in Javascript.
Copy link to clipboard
Copied
Hi brian, here's a very simple visual basic script, it just opens the find and replace dialog the same way you would do it manually, hitting Alt+E to bring down the Edit menu, then pressing E to open the find dialog, ESC to close,
Set objShell = CreateObject("WScript.Shell")
objShell.SendKeys "%EE{ESC}"
you won't see much so just for kicks to see if it is working add a some delay between calls
Set objShell = CreateObject("WScript.Shell")
objShell.SendKeys "%EE"
For i = 1 To 500
objShell.SendKeys "{TAB}"
Next
objShell.SendKeys "{ESC}"
run it on a pc then play your action, if it works then try putting it on your startup scripts folder so it runs every time Illustrator starts. If it does not work, then add some delay to the beginning of the script while it waits for Illustrator to load.
if all works fine, translate to Applescript, there should be something similar.
Copy link to clipboard
Copied
This will open Illustrator & then open a new page (because you can not open the find & replace if a page is not open) then it will open the Find and Replace dialog & then close it.
activate application "Adobe Illustrator"
tell application "System Events"
tell process "Adobe Illustrator"
keystroke "n" using {command down}
key code 36
--This is my quick key for opening "Find and Replace"
keystroke "l" using {command down, shift down, option down}
delay 1
key code 53
keystroke "w" using {command down}
end tell
end tell
Copy link to clipboard
Copied
Sorry if this does not make sense but here is maybe an even better sulotion. Here is the script we run in our Illustrator files to automatically name certain parts of the file. If in the begining of this script it would open the "Find and Replace" dialog box & then close it then the "Action" can run & not crash Illustrator.
//////////////////////////////////////////////////////////// english //
// ----------------------
// -=> WR-DateAndTime <=-
// ----------------------
//
// A Javascript for Adobe Illustrator
// by Wolfgang Reszel (ai-js@rumborak.de)
//
// Version 0.9 from 22.9.2011
//
// This script inserts the actual date or the actual time to a
// predefined position in the document.
//
// To define the position, you'll have to create an textobject and
// execute this script while the object is selected. The whole object
// has to be selected and not words or letters. You can mark more
// objects, if you select each object separate and execute
// the script on it.
//
// With the placeholders {DATE} and {TIME} you are able to define a
// particular point, where the date or the time should be replaced.
// If there is no placeholder in the textobject
// "{FILENAME}{FILEEXT} ({DATE}, {TIME})" will be used as standard placeholders.
//
// To update the date and time execute this script without any object
// selected.
//
// There are some additional placeholders:
// {FILE} - complete document-filename with path
// {FILEPATH} - only the documents filepath
// {FILENAME} - the filename of the document
// {FILEEXT} - the file extension of the document inclusive dot
//
// On my system this script can't see the path of the document, when
// it was opened directly from windows Explorer (double click).
//
// In Illustrator CS it is now possible to edit a DateAndTime-Object.
//
// To enable the english messages and date-format change the "de"
// into "en" in line 90.
//
// Sorry for my bad english. For any corrections send an email to:
//
//////////////////////////////////////////////////////////// Deutsch //
// ----------------------
// -=> WR-DateAndTime <=-
// ----------------------
//
// Ein Javascript fuer Adobe Illustrator
// von Wolfgang Reszel (ai-js@rumborak.de)
//
// Version 0.9 vom 30.9.2011
//
// Dieses Skript fuegt das aktuelle Datum und die aktuelle Uhrzeit an
// eine vorher bestimmte Stelle im Dokument ein.
//
// Um eine Stelle zu bestimmen, muss man ein Textobjekt erzeugen, es
// markieren und dann dieses Skript aufrufen. Es muss das gesamte Objekt
// ausgewaehlt sein, nicht etwa Buchstaben oder Woerter. Es lassen sich
// nacheinander auch mehrere Objekte als Datum/Uhrzeit markieren.
//
// Mit den Platzhaltern {DATE} und {TIME} (in geschweiften Klammern)
// kann man bestimmen, wo genau im Text das Datum und die Uhrzeit
// erscheinen soll. Sind die Platzhalter nicht vorhanden, wird
// automatisch "{FILENAME}{FILEEXT} ({DATE} - {TIME})" verwendet.
//
// Zum Aktualisieren des Datums/Uhrzeit muss man dieses Skript aufrufen
// wenn kein Objekt ausgewaehlt ist.
//
// Es gibt noch einige zusaetzliche Platzhalter:
// {FILE} - kompletter Dateiname mit Pfad
// {FILEPATH} - nur der Verzeichnispfad des Dokuments
// {FILENAME} - der Dateiname des Dokuments
// {FILEEXT} - die Dateiendung des Dokuments inklusive Punkt
//
// Auf meinem System kann der Pfad nicht ermittelt werden, wenn das
// Dokument vom Windows Explorer geoeffnet wird (Doppel-Klick).
//
// InÿIllustrator CSÿkann man nun ein Datum/Uhrzeit-Objekt bearbeiten.
//
// Um dieses Skript mit deutschen Meldungen und Datumsformat zu
// versehen, muss in Zeile 90 das "en" durch ein "de" ersetzt werden.
//
// Verbesserungsvorschlaege an: ai-js@rumborak.de
//
//$.bp();
// -------------------------------------------------------------------
var language="en"; // "de" fuer Deutsch
// -------------------------------------------------------------------
var WR="WR-DateAndTime v0.9\n\n";
var AIversion=version.slice(0,2);
if (language == "de") {
var format_preset = "{FILENAME}{FILEEXT} ({DATE} - {TIME})";
var MSG_unsetmark = WR+"Dieses Objekt ist als aktuelles Datum/Uhrzeit markiert, soll die Markierung aufgehoben werden?";
var MSG_setmark = WR+"Soll dieses Textobjekt als aktuelles Datum/Uhrzeit markiert werden?";
var MSG_askformat = WR+"Soll das Textobjekt als Datum/Uhrzeit formatiert werden? Formate:\n{DATE}, {TIME}, {FILE}, {FILEPATH}, {FILENAME} und {FILEEXT}:"
var MSG_editformat = WR+"Datums-/Uhrzeitformat bearbeiten (Leer = entfernen). Formate:\n{DATE}, {TIME}, {FILE}, {FILEPATH}, {FILENAME} und {FILEEXT}:"
var MSG_notexto = WR+"Kein Textobjekt!";
var MSG_selectedmany = "Zum Markieren als aktuelles Datum/Uhrzeit darf nur ein Textobjekt ausgew\xE4hlt sein und falls Sie die Daten aktualisieren wollen, darf kein Objekt ausgew\xE4hlt sein.";
var MSG_nodocs = WR+"Kein Dokument ge\xF6ffnet."
var Timeformat = 24;
var TimeSep = ":";
var AM = " am";
var PM = " pm";
var Dateformat = "dd.mm.yyyy";
} else {
var format_preset = "{FILENAME} ({DATE}, {TIME})";
var MSG_unsetmark = WR+"This object is marked as actual date'n'time, do you want to remove the mark?";
var MSG_setmark = WR+"Do you want to mark the selected textobject as actual date'n'time?";
var MSG_askformat = WR+"Do you want to mark the textobject as actual date'n'time? Formats:\n{DATE}, {TIME}, {FILE}, {FILEPATH}, {FILENAME} and {FILEEXT}:"
var MSG_editformat = WR+"Edit date'n'time (empty = remove). Formats:\n{DATE}, {TIME}, {FILE}, {FILEPATH}, {FILENAME} and {FILEEXT}:"
var MSG_notexto = WR+"No textobject!";
var MSG_selectedmany = "To mark as actual date'n'time, you have to select only one textobject. If you want to update the date'n'time-objects, there must be no object selected.";
var MSG_nodocs = WR+"You have no open document."
var Timeformat = 12;
var TimeSep = ":";
var AM = " am";
var PM = " pm";
var Dateformat = "yyyymmdd";
}
var error=0;
if (documents.length<1) {
error++;
alert(MSG_nodocs)
}
if (error < 1) {
date_n_time();
}
function TodayDate()
{
var Today = new Date();
var Day = Today.getDate();
var Month = Today.getMonth() + 1;
var Year = Today.getYear();
var PreMon = ((Month < 10) ? "0" : "");
var PreDay = ((Day < 10) ? "0" : "");
if(Year < 999) Year += 1900;
var theDate = Dateformat.replace(/dd/,PreDay+Day);
theDate = theDate.replace(/mm/,PreMon+Month);
theDate = theDate.replace(/d/,Day);
theDate = theDate.replace(/m/,Month);
theDate = theDate.replace(/yyyy/,Year);
theDate = theDate.replace(/yy/,Year.toString().substr(2,2));
return theDate;
}
function TodayTime()
{
var Today = new Date();
var Hours = Today.getHours();
var Minutes = Today.getMinutes();
var Suffix = "";
if (Timeformat == 12) {
if (Hours >= 12 ) {
Suffix = PM;
} else {
Suffix = AM;
}
if (Hours >= 13) {
Hours = Hours - 12;
}
if (Hours < 1) {
Hours = Hours + 12;
}
}
var PreHour = ((Hours < 10) ? "0" : "");
var PreMin = ((Minutes < 10) ? "0" : "");
return PreHour+Hours+TimeSep+PreMin+Minutes+Suffix;
}
function DateUpdate(Name) {
var docpath = activeDocument.path.fsName;
var docname = activeDocument.name.replace(/(.*?)(?:\.([^.]+))?$/,'$1');
var extension = activeDocument.name.replace(/(.*?)(?:(\.[^.]+))?$/,'$2');
if (docpath.slice(2,3) == "\\") {
docsep = "\\";
} else {
docsep = ":";
}
var content = Name.slice(11);
var content = content.replace(/\{FILE\}/,docpath+docsep+docname);
var content = content.replace(/\{FILEPATH\}/,docpath);
var content = content.replace(/\{FILENAME\}/,docname);
var content = content.replace(/\{FILEEXT\}/,extension);
var content = content.replace(/\{DATE\}/,TodayDate());
var content = content.replace(/\{TIME\}/,TodayTime());
return content;
}
function date_n_time()
{
if (selection.length == 1) {
if (selection[0].typename == "TextArtItem" || selection[0].typename == "TextFrame") {
if (selection[0].name.slice(0,11) == "actualDate:") {
dateformat = selection[0].name.slice(11);
Check = false;
if (AIversion == "10") {
Check = confirm( MSG_unsetmark );
} else {
dateformat = prompt(MSG_editformat, dateformat);
}
if(dateformat != "" && Check) {
selection[0].contents = selection[0].name.slice(11);
selection[0].name="";
selection[0].selected = false;
}
if(dateformat == "" && !Check) {
selection[0].name="";
selection[0].selected = false;
}
if(dateformat && dateformat !="" && !Check) {
selection[0].name="actualDate:"+dateformat;
selection[0].contents = DateUpdate(selection[0].name);
}
} else {
dateformat = selection[0].contents;
if(dateformat.search(/\{DATE\}/) == -1 && dateformat.search(/\{TIME\}/) == -1 && dateformat.search(/\{FILE[A-Z]*\}/) == -1) dateformat = format_preset;
Check = false;
if (AIversion == "10") {
Check = confirm( MSG_setmark );
} else {
dateformat = prompt(MSG_askformat, dateformat);
}
if (dateformat || Check) {
selection[0].name="actualDate:"+dateformat;
selection[0].contents = DateUpdate(selection[0].name);
selection[0].selected = false;
}
}
} else {
alert ( MSG_notexto );
}
} else if (selection.length > 1) {
alert ( MSG_selectedmany );
} else {
if (AIversion == "10") {
var textArtItems = activeDocument.textArtItems;
for (var i = 0 ; i < textArtItems.length; i++)
{
if (textArtItems.name.slice(0,11) == "actualDate:") {
textArtItems.selected = true;
textArtItems.contents = DateUpdate(textArtItems.name);
}
}
} else {
var textFrames = activeDocument.textFrames;
for (var i = 0 ; i < textFrames.length; i++)
{
if (textFrames.name.slice(0,11) == "actualDate:") {
textFrames.selected = true;
textFrames.contents = DateUpdate(textFrames.name);
}
}
}
}
}
Copy link to clipboard
Copied
Hi Carlos,
Thank you for this script!
I'm wondering if there is a way to use your script as a batch action. I'd like to point the find & replace script at a folder of files, and have it search, replace, and save.
Thoughts?
Tom


-
- 1
- 2