FIND/CHANGE TEXT BY ATTRIBUTE

In our last blog post we explored working with find/change for text in an InDesign document. We will expand on this discussion by creating a script for finding and replacing text based on attributes such as color, font, and font style. We will be writing the script in AppleScript, but you JavaScript users can follow along.

FIND ATTRIBUTES

Open the AppleScript scripting dictionary for InDesign. From within AppleScript Editor, choose Open Dictionary from its File menu. Select your version of InDesign from the application menu displayed. (We are using Adobe InDesign CC 2015.) When the dictionary opens, enter find text preference in the search field and select the entry listed as Class in the preferences suite. Be prepared for an eye opener.

 find text preferences

If you browse through the listing of attributes that can be used for finding text, you may discover some you may not have thought of before, and a lot that you will never ever use (unless your installation is for a foreign language).

FIND/REPLACE BY ATTRIBUTE

A script to do a find/change using an attribute record is fairly self-explanatory:

  • set find text preferences for the application to nothing
  • set change text preferences for the application to nothing
  • create an attribute list for the properties you want to find or change
  • tell the containing object (document, story, etc.) to perform the find

To change the attributes for the found text, add the following:

  • make sure the result of the find is not empty.
  • If the result of the find is not empty, tell the containing object to perform the change

When through doing find/change, clear the find/change preferences

  • set the find text preferences for the application to nothing
  • set the change text preferences for the application to nothing

FILL COLOR

Fill Color– requires a swatch (color, gradient, tint, or mixed ink) which is applied as a fill color. This can be used for both find and change.
Fill Tint – The tint as a percentage of the fill color used as part of the find text preference. This is expressed as a number in the range of 0 to 100, or -1 for the inherited or overridden value.

For each find/change operation, a list of three lists needs to be provided to the script. For a single fill color find/change, the first list will be a record of the fill color to find, the second list will be a record of the color to change to, and the third is a list of true/false values for setting the find change text options. These options, in order, will be: include footnotes, include master pages, include hidden layers, and whole word.

set findChangeAttribList to {{fill color:"Green"}, {fill color:"Black"}, {true, false, false, true}}

You can test this out by copying the following script to your AppleScript Editor. Run the script with an application open that has text with the fill color designated for the find. It is assumed that the color designated for the change is also available in the document.

Find/Change Color

   tell application "Adobe InDesign CC 2015"
	set findChangeAttribList to {{fill color:"Green"}, {fill color:"Black"}, {true, false, false, true}}
	set docRef to document 1
	copy findChangeAttribList to {findAttrib, changeAttrib, optionList}
	set find text preferences to nothing
	set change text preferences to nothing
	set properties of find text preferences to findAttrib
	--set properties of change text preferences to changeAttrib
	tell find change text options
	   set include footnotes to item 1 of optionList
	   set include master pages to item 2 of optionList
           set include hidden layers to item 3 of optionList
	   set whole word to item 4 of optionList
	end tell
	tell docRef
	   set myFoundItems to find text
           if myFoundItems is not "" then
	      change text
          end if
	end tell
	set properties of find text preferences to findAttrib
	set properties of change text preferences to changeAttrib
   end tell
   myFoundItems --for testing

The script assumes that both the find and change fill colors exist for the document. If the color to find is not available for the document, an invalid parameter error is raised. To prevent this, the script will need to verify that the colors exist. You could add the following to the script where the copy statement is found:

   copy findChangeAttribList to {findAttrib, changeAttrib, optionList}
      set colorName to fill color of findAttrib
      if (exists swatch colorName of docRef) is false then
         activate
         display alert ("color " & colorName & " not installed for document
         return
      end if

On the other hand, you may want to test to make sure that both colors designated for find/change are available. Instead of repeating this if statement for the change color, you may want to use a handler.

Test Color Handler

   on testColor (docRef, colorName)
      tell application "Adobe InDesign CC 2015"
         tell docRef
            if not (exists swatch colorName) then
               error "Color " & colorName & " is not installed for this document"
            end if
         end tell
      end tell
   end testColor

To accommodate this, you will need a call to the handler inside the main section of the script. You also need to surround the main section of the document with a try/on error statement block to handle the error generated.

   try
      tell application "Adobe InDesign CC 2015"
         --after copy findChangeAttribList to {findAttrib, changeAttrib, optionList)
         my testColor (docRef, fill color of findAttrib)
         my testColor (docRef, fill color of changeAttrib)
         --rest of the main section of the script
      end tell
      on error errStr
         activate
         display alert errStr
      end try

The advantage of using a handler such as this is that you now have a try/on error block that can catch any errors that may occur while executing the script. We will use a similar approach for our next sample script to do a find/change using the applied font text attributes.

FIND/CHANGE FONT

To do a find/change using the font applied to the text, your script needs to supply a value for both the applied font and the font style properties. applied font – specified either as a font object or using the name of the font family.
font style – the name of the font style such as “Regular” or “Bold”

The sample script to do a find/change for text using the applied font and font style is a little more involved as the myFindChangeList now has two properties for each the find and the change attribute lists:

   set findChangeAttribList to {{applied font:"Avenir", font style:"Roman"}, {applied font:"Minion Pro", font style:"Regular"}, {true, false, false, true}}

To test this out, copy the following script to your AppleScript Editor:

Find/Change_Font

   try
	tell application "Adobe InDesign CC 2015"
	   set findChangeAttribList to {{applied font:"Minion Pro", font style:"Regular"}, {applied font:"Avenir", font style:"Roman"}, {true, false, false, true}}
	   set docRef to document 1
	   copy findChangeAttribList to {findAttrib, changeAttrib, optionList}
	   set find text preferences to nothing
	   set change text preferences to nothing
           --call handler to test fonts
	   my testFont(findAttrib)
	   my testFont(changeAttrib)
	   set properties of find text preferences to findAttrib
	   if changeAttrib is not {} then
	      set properties of change text preferences to changeAttrib
	   end if
	   tell find change text options
              set include footnotes to item 1 of optionList
	      set include master pages to item 2 of optionList
              set include hidden layers to item 3 of optionList
	      set whole word to item 4 of optionList
	   end tell
	   tell docRef
	      set myFoundItems to find text
	      if myFoundItems is not "" and changeAttrib is not {} then
	         change text
	      end if
	    end tell
	    set find text preferences to nothing
	    set change text preferences to nothing
	    myFoundItems --for testing
	end tell
   on error errStr
	activate
	display alert errStr
   end try


   on testFont(fontAttribute)
	tell application "Adobe InDesign CC 2015"
	   set fontName to applied font of fontAttribute
	   set fontStyle to font style of fontAttribute
	   set testName to (fontName & tab & fontStyle) --space is a tab
	   set fontTest to status of font testName
	   if fontTest is not installed then
	      error "Font " & testName & " is not installed for application"
	   end if
	end tell
	return {fontName, fontStyle}
   end testFont

MULTIPLE FIND/CHANGE

If you were to want to do more than one find/change when the script is run, the findChangeAttribList can become a little intimidating as you now would need to have three lists inside of a number of lists inside of the findChangeAttribList. We will leave this up to those of you who want to tackle this situation.

FONT NAME PROBLEM

In testing the Find/Change_Font script with a number of type fonts, we discovered a problem that we need to mention. Even though the script did not raise a font not installed error, there were occasions when the script failed to find a font match even though the font was used in the document. To discover the problem, we selected the text with the font and ran the following test script:

Test Script

   tell application "Adobe InDesign CC 2015"
	set selList to selection
	set selItem to item 1 of selList
	set thisTest to properties of applied font of selItem
   end tell
   thisTest

The properties returned revealed that the name of the font was “Avenir Roman ” (space between font name and style is a tab). Notice that a space was included at the end of the style name (“Roman “). Once we changed the style designation in the script to include the space, the text was found and the script performed as anticipated. Surprisingly, after running the script with the style designated having the space (“Roman “), running the Test Script script a second time revealed that the space was now dropped from the name. I am sure you will find similar anomalies with other fonts. We just tested a representative sampling.

ONWARD AND UPWARD

Now that you have a sample for finding and changing text based on color and font, you can create a real world script that will allow any number of find/change attributes. And, of course, you will want to give your user a custom dialog in which these attributes can be designated as well as the scope of the find/change (document or selection).