Sunday, August 28, 2005


Script of the Day -- Style in Use?

I was wondering which script to present today (I have quite a backlog), when the need for a new script dropped out of the clear blue sky. I'm doing some administrative clean up of some documents that are nearing readiness for printing. I like to do four things as part of my preflight:"Cleaning up" text styles consists of first eliminating all unused styles and then checking the remaining styles to make sure that in particular all the styles are gone that were imported with the original Word document.

While I suppose I could write a script for much of this activity, the UI serves me very well for most of it, and there are judgment calls to be made here that would be hard to encapsulate into a script. I worked through the first six chapters of a book (small "b" -- I rarely, if ever, make use of InDesign's Book feature), but the seventh has thrown up a new challenge: one of the paragraph styles is apparently "in use." It is called "DTP" and is used by my client to give me instructions. By the end of setting one of these chapters, that style should no longer be in use.

Turning to Find/Change to see where it is being used, I am dismayed to discover that no text actually uses the style. So, what does "in use" mean in this situation? It means, that the style is either used for Based-on or Next Style in one of the styles that actually is in use. Next Style is unlikely, but Based-on is possible if I needed to create a new style for some special element in this chapter and I accidentally did so while some text in the DTP style was selected.

Feature Change Raises Head

There has been a major change in the behavior of Based-on in InDesign CS2. Whereas before, if you changed the nominated Based-on paragraph style in a style, that other style was not changed in any way -- just the description changed to reflect the new base -- now the style changes. It sounds quite logical: if a characteristic of the style in question was identical to the previous based-on style's corresponding then changing the based-on for the style will cause that characteristic to change to that of the new based-on style.

This actually sounds like a very logical behavior, but it flies in the face of 20 years of using PageMaker and InDesign and has been driving me nuts. The saving grace is that if you switch the style in question to be based-on No Paragraph Style then you get the old behavior.

Image of bugSad to say, there's a bug in the CS2 original release (build 421) scripting system whereby if by script you change the based-on style of a paragraph style to No Paragraph Style, you do not get the exceptional behavior that the UI provides. This makes it a bit harder (to say the least) to use a script to change the based-on of a paragraph style without changing the specification of the style.

Back to the Script

Let's start out with a "quick and dirty" script. The first issue with this script is: which paragraph style should the script look for? The easiest way to communicate this, you would think, would be to select the style in the palette and have the script look there.

There are two problems with this: a script can't interrogate the palette and because a use of this style can't be found, I can't click in a paragraph to select it that way. I suppose I could have the user type a paragraph using the style in a gash text frame, but that is surely very clumsy. For our immediate needs, we know the name of the style, so we can just build it directly into the script. Let's do that for now (a better solution would be to use a drop-down menu in a user dialog and a feature request to the scripting team would be to allow for scripts to interrogate palettes to find out what is selected). So, let's get started on the script.

//DESCRIPTION: Locate any paragraph Styles that use a particular style as based-on

// Later: add a drop-down. For now, we'll hard-wire the style

myDoc = app.activeDocument; // Note: global variable
var myStyle = myDoc.paragraphStyles.item("DTP");
I've adopted a convention in my scripts that myDoc is always a global variable set to the active document. It saves a lot of messing around passing an extra parameter to functions. Generally speaking it is better to mark variables as local (by labeling them with "var" as I've done for "myStyle"

Notice also that I have included a note to myself to remind me at some future date to make the script more flexible.

The "item" method provides a way of creating a reference to a particular item in a collection. In this case, we know that every paragraph style has a unique name so we do not have to worry about myStyle returning more than one element (as it might for other kinds of named objects).

Armed with this reference, all we need to do is walk through all the paragraph styles looking for any use of myStyle as either based-on or next style. Thinks: we don't care about next style because changing that does no harm to the document. Well that makes it easier.
var myStyles = myDoc.paragraphStyles;
var mySlen = myStyles.length;
for (var j=0; mySlen > j; j++) {
if (myStyles[j].basedOn == myStyle) {
alert("Paragraph style " + myStyles[j].name + " uses DTP for based-on");
Combine the two snippets above, and that's the whole script.

In this second part of the script (the "meat" of the script) we first set local variable "myStyles" to reference a collection of all the paragraph styles in the document. Then, we set another local variable to the length of this collection to be used to control how many times we execute the upcoming loop -- this speeds the script up a tad because this is a fixed value that is not changed by the loop, so we use it to control the loop rather than calculate the value each time around the loop.

Now, all we need to do is compare the basedOn property of each style with myStyle. If they're the same, then for now, all we're going to do is alert the user that the style has been found and exit so that the user can deal with the situation. Perhaps later, I'll extend this script to handle the change in based-on automatically, but for now, I've solved my problem (subject to testing the script, which I am about to do right now).

Debugging the Script

Well, what do you know, the script has an error! JavaScript counts from zero, but in InDesign's object model the first paragraph style is special. It is always the "No Paragraph Style" style -- so special that it isn't even displayed in the InDesign CS2 paragraph palette, although you can see it in the Paragraph Style drop-down in the Find/Change panel. One thing that you can't do with that first style is access its basedOn property because it doesn't have one -- it is the ultimate base of all paragraph styles. So attempting to run the script produces this error:

What an informative error message that is! Tells me exactly what's wrong and which line of my script made the error.

Of course, the solution is easy. Since we know that No Paragraph Style can't have a based-on style, it surely isn't of interest to us, so we can simply ignore it by starting our loop at 1 instead of zero:
for (var j=0; mySlen > j; j++) {
And, whoopee! It worked. I have a style that was indeed added for this document called ChartAssignment that uses DTP as its based on.

I can't help thinking that it would have taken me less time to check each style manually than write this blog entry, but it would not have been nearly as much fun.

Footnote: This script is of such special, specific purpose that I will not be posting it for download.

Would it have been so hard to put an alert at the end of the script to indicate that no instances were found?

Of course not, but when I'm banging out a quick and dirty script for my own use, I tend to forget such niceties.
Post a Comment

<< Home

This page is powered by Blogger. Isn't yours?