Select part of point text objects matching a regex expression
Copy link to clipboard
Copied
Hello! I'm looking for a way to run through a bunch of point text objects and select part of the string in each text object based on a regex expression. I found this awesome script that can do a regex find/replace, but my end goal is not to replace, but to apply a given character style to part of the string.
For example, I have two point text objects:
first / second / third
one / two / three
And I want to be able to select "/ second /" and "/ two /" to be able to apply a different character style to that part of each point text object. Also, i'm not sure that you can have parts of two different point text objects selected at the same time, so the script might need to apply the active text style to the matched string parts as it passes through them.
Is this impossible?
Thanks!
Explore related tutorials & articles
Copy link to clipboard
Copied
Hi jamierob98757643​,
for the beginning:
Trouble applying paragraph and character styles to text in Illustrator with a script
Have fun
Copy link to clipboard
Copied
Wow! I think that might be the ticket. I'm not having luck making it work though. I think it must be that my regex is incorrect. I'm wondering if you could shed any light on what I'm doing wrong.
#target illustrator
function test(){
// regex_changeContentsOfWordOrString_RemainFormatting.jsx
// regards pixxxel schubser
var doc = app.activeDocument;
var s = new RegExp("[0-9]*$","gi");
var myStyle = doc.characterStyles.getByName("MyStyle");
var atf = activeDocument.textFrames[0];
while (result = s.exec(atf.contents)) {
try {
aCon = atf.characters[result.index];
aCon.length = result[0].length;
myStyle.applyTo(aCon);
} catch (e) {};
}
};
test();
assuming
-I have a character Style setup named "MyStyle"
-I have two point text objects:
"one / 334 / three"
"first / 563 / third"
-I have the point text objects selected (or un-selected?)
when I run the script it should set "334" and "563" from whatever the style was to 'MyStyle', correct? The script appears to run correctly without any errors, but does not make the character style change. If I don't have 'MyStyle' setup, i get an error reporting that.
Thank you!
Copy link to clipboard
Copied
Use this site to test your Regex:Regex Tester - Javascript, PCRE, PHP
You will see that your expression "matches 0 characters and therefore matches infinity".
If you only want 3 numbers in a row, you can try this: \d{3}
Copy link to clipboard
Copied
Thank you! I'm new to regular expressions and am just getting the hang of them. I replaced that bit with the one you provided, and it works in the Regex Tester, but still isn't changing the character style in Illustrator:
#target illustrator
function test(){
// regex_changeContentsOfWordOrString_RemainFormatting.jsx
// regards pixxxel schubser
var doc = app.activeDocument;
var s = new RegExp("\d{3}","gi");
var myStyle = doc.characterStyles.getByName("MyStyle");
var atf = activeDocument.textFrames[0];
while (result = s.exec(atf.contents)) {
try {
aCon = atf.characters[result.index];
aCon.length = result[0].length;
myStyle.applyTo(aCon);
} catch (e) {};
}
};
test();
Doesn't work to change the character style on point text objects containing the following strings:
first / 563 / third
one / 334 / three
334
563
Maybe, i'm messing up with how I have them selected, or organized in layers?
Copy link to clipboard
Copied
Oh yea, when you have backslashes (\), they escape things right in front of them when used inside of strings, so if you are making your regexp with the syntax above, you have to put double backslashes so as to escape the 2nd backslash so that you get your digit character fed into the string properly.
Also, you don't have key word var for a few of your variables, which causes them to leak into the global scope and would mess up your tests later on.
I also had to restart my AI because after running the script as you posted, it caused it act goofy and not succeed with the edited script right afterwards.
Try this edited script:
#target illustrator
function test(){
// regex_changeContentsOfWordOrString_RemainFormatting.jsx
// regards pixxxel schubser
var doc = app.activeDocument;
var s = new RegExp("\\d{3}","gi");
var myStyle = doc.characterStyles.getByName("MyStyle");
var atf = activeDocument.textFrames[0];
var result, aCon;
while ( result = s.exec(atf.contents)) {
try {
aCon = atf.characters[result.index];
aCon.length = result[0].length;
myStyle.applyTo(aCon);
} catch (e) {};
}
};
test();
Copy link to clipboard
Copied
Thanks, Silly-V. I so appreciate your help. I'm still not able to make it happen with that most recent version. I restarted illustrator as well. I make a quick screen recording..maybe you can spot what i'm doing wrong? illustrator regex char style - YouTube
Copy link to clipboard
Copied
var atf = activeDocument.textFrames[0]; means that you are targeting the very first text frame in your document.
If your very first text frame doesn't have the 3 digits, it will work by not finding any matches and not performing any work therefore.
To help you get an insight into what's happening - as you're starting to script, it is essential to use the Extendscript Toolkit and to use the breakpoints along with its Data Browser panel. This way you can step through your code and see exactly what's happening.
For example, you'd be able to see the contents of the atf variable.
Without this you're flying blind, so it's real useful.
Copy link to clipboard
Copied
That was it! It now works on the first text frame in the document. It's not looping through any other textframes though. Thank you for that description--I'll get this working in Extendscript so I can troubleshoot the loop. Thank you!
Copy link to clipboard
Copied
So, I've been struggling with this script for a long time. The code above works great to target a single text frame. I'm trying to get it to loop through all of the textframes in a document. The code below works for more than one textframe, so the loop is sort of working, but it only works for a few and many identical textframes are not getting the character style change. Any ideas why this loop might not be working for all textframes?
The .ai doc (CS6) i've been using is here: Dropbox - regex-test.ai
Thank you!
#target illustrator
function test(){
// regex_changeContentsOfWordOrString_RemainFormatting.jsx
// regards pixxxel schubser
var doc = app.activeDocument;
var s = new RegExp("\\d{3}","gi");
var myStyle = doc.characterStyles.getByName("MyStyle");
for ( i = 0; i < app.activeDocument.textFrames.length; i++ ) {
var atf = activeDocument.textFrames;
var result, aCon;
while ( result = s.exec(atf.contents)) {
try {
aCon = atf.characters[result.index];
aCon.length = result[0].length;
myStyle.applyTo(aCon);
} catch (e) {};
}
}
};
test();
Copy link to clipboard
Copied
In your loop try running it backwards. ie: for ( i = app.activeDocument.textFrames.length; i =>0; i-- )
Copy link to clipboard
Copied
Thanks for looking at this, Larry! When I tried the loop backward, Extendscript didn't like the '=>' and said the '>' does not have a value.
i tried:
for ( i = app.activeDocument.textFrames.length; i >0; i-- )
and then the script ran, but then it's telling me that the 'atf' variable has no value.
If I set 'i' explicitly to the number of text frames in the doc, (For example 7 total textframes in the document) I can get the loop (i--) to apply the style to TF 6 and TF 5, and then with (i++) I can get it to apply the style to TF 0, TF 1, and TF 6, but can't figure out why it's not just going through all of them. If that makes any sense.
Copy link to clipboard
Copied
OK, try switching the equals and greater than in the second statement. ( i >= 0 )
Copy link to clipboard
Copied
Hmm, that one is still coming up with 'atf' as 'no such element'
#target illustrator
function test(){
// regex_changeContentsOfWordOrString_RemainFormatting.jsx
// regards pixxxel schubser
var doc = app.activeDocument;
var s = new RegExp("\\d{3}","gi");
var myStyle = doc.characterStyles.getByName("MyStyle");
for ( i = app.activeDocument.textFrames.length; i >=0; i-- ) {
var atf = activeDocument.textFrames;
var result, aCon;
while ( result = s.exec(atf.contents)) {
try {
aCon = atf.characters[result.index];
aCon.length = result[0].length;
myStyle.applyTo(aCon);
} catch (e) {};
}
}
};
test();
Any help is so appreciated! I'm thinking that maybe i'm going about this loop in the wrong way all together..
Copy link to clipboard
Copied
Ah, it's got to be in your for-loop. When counting backwards, make sure to subtract 1 from the .length of the array. For example if you had an array of 5 items, it's length would be 5. But the very last item is going to be at index [4].

