finding and replacing fonts in Illustrator

Hi Folks-

We just got CS3 and are transitioning to OpenType fonts, I’m trying to replace these via script. The problem I’m having is that some text frames have various different fonts in them, so a global find-and-replace among text boxes does not discriminate:

tell application "Adobe Illustrator"
	set allframes to count text frames in document 1
	repeat with itemCount from 1 to allframes
		try
			set properties of the text of text frame itemCount of document 1 to {text font:text font "AvenirLTStd-Heavy"}
			
		end try
	end repeat
end tell

so I tried to create a list of text that needs to be replaced:

	tell application "Adobe Illustrator"
	set thelist to (every word of every text frame of document 1 whose properties contains {text font:text font "Avenir-Heavy"})
	set x to 1
	repeat (count of items in thelist) times
		try
			set thetext to (item x of thelist)
			set properties of thetext of document 1 to {text font:text font "AvenirLTStd-Heavy"}
		end try
		set x to x + 1
	end repeat
end tell


this doesn’t generate an error, but it also doesn’t replace the font.

any ideas?

thanks!

Ralph

Hi Ralph,

The problem in your second example seems to lie in Illustrator, as I see it returning an unexpected (faulty?) object reference. I tried a few variations, but the result always began with character 2 and was at least one character in excess of the length of the text. This was my test on an 8 character story:

tell application "Illustrator CS"
	set thelist to every word of every text frame of document 1
	return thelist -->{text from character 2 to character 9 of story 1 of document 1 of application "Illustrator CS"}
end

Hi Ralph

I’ve had so many headaches over scripting text in illustrator, it can be so frustrating.
Don’t get excited i’m not offering a solution, but hopefully a helping hand.

I’ve had similar problems in the past trying to change fonts in text frames which contain several different fonts within illustrator.
My personal choice was to check every word with in the text frame for the font then change it to the new font.
unfortunately i never finished it but made some progress.
Like i say its by no means a solution but a step in the right direction (or not :confused: )

tell application "Adobe Illustrator"
	set m to count every word of text frame 1 of document 1
	repeat with i from 1 to m
		set t to the text font of word i of text frame 1 of document 1
		--display dialog (name of t as string)
		if name of t is "MyriadPro-Regular" then
			set text font of word i of text frame 1 of document 1 to text font "MyriadPro-Bold"
		end if
	end repeat
end tell

Here’s how i tested it:
I had 1 text frame in a document with say 20 words every other word was “MyriadPro-Regular” every version of this font was turned to the bold version when the script was run, and the alternate text was untouched.

let me know how you get on with this and i hope it helps.

Illustrator must be one of the most frustrating of all the Adobe applications to script. Try this:

tell application "Adobe Illustrator"
	tell document 1
		set text font of (every character of every story whose properties contains {text font:text font "HelveticaNeue-CondensedBold"}) to text font "MyriadPro-Regular" of application "Adobe Illustrator"
	end tell
end tell

You must have of application “Adobe Illustrator” after the name of the font for this to work. This should take care of every character of every text frame in the document in one step.

Hi Guys-

thanks for the replies. I’ve been beating my head against the wall with this one, folks. Jerome’s solution is a simple one, and it works -on text. However, it does not work on insertion points, or “mystery fonts” that seem to populate our documents. For instance, I often find a Myriad-Roman in our documents, and this does not work in this case. Additionally, there will be other fonts listed in the Type>Find Font menu that are not replaced. I assume this is because the script is talking to the text in the frame, and if there’s no text in there, it doesn’t work.

Illustrator is indeed an infuriating application to script.

-Ralph

If I understand your dilemma you may have empty text frames in your document and these are holding onto the font that you are attempting to replace. If so then you might just want to clean up the document by deleting the empty text frames:

delete (every text frame whose contents is "")

You could also set up an action, however this does not look like a great solution since in testing the dialog box for the recorded fond font routine comes up even when I have it set not to in the script.

do script "Action 1" from "Set 1" without dialogs

While I agree it may not be the simplest app to script, it logically follows the object model.

Fonts belong to the Application, not the document. So if you’re explicitly in a “tell document n.” block you are trying to access of property of the parent.

@Ralph: You should look at a cleanup script to take care of the “mystery fonts”. Not only for this project but for proper file handling in general. IMHO :smiley:

Have fun!

Jim Neumann
BLUEFROG

thanks Bluefrog et al-

I agree I need a cleanup script, or to add a cleaning function to other oft-run scripts. This code strips out ‘insertion points’:

tell application "Adobe Illustrator"
	tell document 1
		repeat with eachframe from (count of text frames) to 1 by -1
			if (length of text range of text frame eachframe) = 0 then
				delete text frame eachframe
			end if
		end repeat
	end tell
end tell

the reason I step through backwards is that it appears that Illustrator dynamically renumbers frames, so if you count the frames, and then delete one as you’re stepping through, the script fails on the last loop because there is no last frame.

-RL

Ok Folks-

here’s a working script. First it deletes “insertion points”, then steps through each character of each frame, backwards (backwards because Illy seems to dynamically renumber text frames) :smiley:

set swaplist to {{"Avenir-Roman", "AvenirLTStd-Roman"}, {"Avenir-Heavy", "AvenirLTStd-Heavy"}, {"Avenir-Medium", "AvenirLTStd-Medium"}, {"Myriad-Roman", "AvenirLTStd-Medium"}, {"Avenir-Book", "AvenirLTStd-Book"}}
tell application "Adobe Illustrator"
	repeat with eachframe from (count of text frames of document 1) to 1 by -1
		if (length of text range of text frame eachframe of document 1) = 0 then
			delete text frame eachframe of document 1
		else
			repeat with eachcharacter from 1 to (count of characters of text frame eachframe of document 1)
				set oldfont to name of text font of character eachcharacter of text frame eachframe of document 1
				repeat with eachpair from 1 to (count of items of swaplist)
					set thepair to item eachpair of swaplist
					if oldfont = (item 1 of thepair) then
						set properties of character eachcharacter of text frame eachframe of document 1 to {text font:text font (item 2 of thepair)}
						exit repeat
					end if
				end repeat
			end repeat
		end if
	end repeat
end tell

ralph,

If you look at the code I posted earlier and delete the blank text frames first you should eliminate some extra code and the problem with references since there is no repeating through the text frames, I used stories in my code which are the text flow which is in a text frame but independent from a physical frame sine a story may be contained in many linked text frames. Also it should be faster as well as easier to undo if there is an unexpected result, one undo for the entire replace versus how ever many characters you repeated through.

So you end up with something like this:

set swaplist to {{"Myriad-Roman", "MyriadPro-Bold"}}
tell application "Adobe Illustrator"
	activate
	tell document 1
		delete (every text frame whose contents is "")
		repeat with i from 1 to count of swaplist
			set text font of (every character of every story whose properties contains {text font:text font (item 1 of item i of swaplist)}) to text font (item 2 of item i of swaplist) of application "Adobe Illustrator"
		end repeat
	end tell
end tell

In fact a simple test with font key pair, a number of blank text frames, two linked, a few others your’s errors out at character 76 after about 3 seconds while mine is done less than a second from launch, and part of that is activating illustrator. My code also has 2 undo’s to get back to the starting point versus 75. This should be much faster, especially in documents with a lot of text and or empty text frames, since all the empty text frames are deleted in one step and each font replacement key/pair replaces the font in all matching characters in one step instead of iterating through each character individually.

Jerome-

That is indeed a lot faster. I had originally dismissed your earlier script because it errored out. Turns out the replace command just needs to be wrapped in a “try” block, because not all fonts are always present.

set swaplist to {{"Avenir-Roman", "AvenirLTStd-Roman"}, {"Avenir-Heavy", "AvenirLTStd-Heavy"}, {"Avenir-Medium", "AvenirLTStd-Medium"}, {"Myriad-Roman", "AvenirLTStd-Medium"}, {"Avenir-Book", "AvenirLTStd-Book"}}
tell application "Adobe Illustrator"
	activate
	tell document 1
		delete (every text frame whose contents is "")
		repeat with i from 1 to count of swaplist
			try
				set text font of (every character of every story whose properties contains {text font:text font (item 1 of item i of swaplist)}) to text font (item 2 of item i of swaplist) of application "Adobe Illustrator"
			end try
		end repeat
	end tell
end tell

thanks Jerome!

-RL