ADDING FUNCTIONALITY TO AN EXISTING SCRIPT

It goes without saying that once you have a basic script written, you may discover other processes that you will want to add. This is particularly true with the demonstration script written in our previous blog post. That script exports all groups and all graphics from a document based on results from the user’s response to a custom dialog. In testing or using this script later down the road, you may decide that it would be nice if the script would make sure the folders for the exported items exist. If the folders do not exist, the script could create the folders.

Current Folder Path

Currently the parent location for the export folders is hard-coded at the top of the script:

set folderPath to path to desktop from user domain as string

To give the user the ability to select where the folders will reside, you could add a choose folder statement to the script. Choose Folder allows the user to select a folder from the system choose dialog.

set folderAlias to choose folder with prompt "Select location for export folder(s)"
set folderPath to folderAlias as string

This might be a good solution, but it does add an additional step for the user and certainly would not be necessary if the export folder(s) already exist. Of course, if the folders will always be in the same location, you can skip the following and keep the path hardcoded in the script.

Choose From Dropdown

Optionally, you could give the user a dropdown list of locations to choose from as part of the user dialog. This would have the most used location chosen by default. Let’s explore this option.

First we need a list of string values that will define the optional locations to choose from. For the userDialog We can start with the userDialog handler from the previous script. The dropdown can be added as the first item inside the tell (make dialog column) statement block:

tell (make dialog row)
   make static text with properties ¬
   {static label:"Parent folder for export folders: "}		
   set folderChoice to make dropdown with properties ¬
   {string list:folderList, selected index:0}
end tell

With this added, our userDialog handler would now read as listed below. You can test this out by copying the code to a new document in the AppleScript Editor:

Test Script

set folderList to {"desktop", "home folder", "document folder"}
set userResult to userDialog(folderList)
userResult
on userDialog(folderList)
   set dialogName to "Export Preferences"
   tell application "Adobe InDesign CC 2017"
	set origLevel to user interaction level of script preferences
	set user interaction level of script preferences to interact with all
	set dlgRef to make dialog with properties ¬
			{name:dialogName, can cancel:true, label:dialogName}
	tell dlgRef
	   --add fields and widgets here
	   tell (make dialog column)
		tell (make dialog row)
		   make static text with properties {static label:"Parent folder for export folders: "}			
		   set folderChoice to make dropdown with properties ¬
                                {string list:folderList, selected index:0}
	        end tell
		set eGroup1 to make enabling group with properties ¬
				{static label:"Export Groups", checked state:true}
		set eGroup2 to make enabling group with properties ¬
				{static label:"Export images", checked state:true}
		tell eGroup1
		   set groupJpg to make checkbox control with properties ¬
				{static label:"Jpg export format", checked state:true}
		   set groupPng to make checkbox control with properties ¬
				{static label:"Png export format", checked state:false}
		end tell
		tell eGroup2
		   set graphicJpg to make checkbox control with properties ¬
				{static label:"Jpg export format", checked state:true}
		   set graphicPng to make checkbox control with properties ¬
				{static label:"Png export format", checked state:false}
		end tell
	   end tell --column
	end tell
	set userResponse to show dlgRef
	if userResponse = true then
	   set folderIndex to (selected index of folderChoice) + 1
	   set checkedList to {false, false, false, false}
	   --capture results from widgets
	   if (checked state of eGroup1 is true) then
		set item 1 of checkedList to checked state of groupJpg
		set item 2 of checkedList to checked state of groupPng
	   end if
	   if (checked state of eGroup2 is true) then
	        set item 3 of checkedList to checked state of graphicJpg
		set item 4 of checkedList to checked state of graphicPng
	   end if
	end if
	destroy dlgRef
	set user interaction level of script preferences to origLevel
	--return captured results or throw error based on value of userResponse
	if (userResponse is false) then
	   error ("User Cancelled")
	end if
   end tell
   return {folderIndex, checkedList}
end userDialog

Compile the script and then run it. When you run the script, the dialog should look like the following.

…our dialog with dropdown added

Click OK to close the dialog. You should also see the result of the user’s response in the editor’s Result window. Depending on choices made, it will look similar to:

{1, {true, false, true, false}}

The second value of the result is a list that indicates the choices made for export: {groups jpg export, groups png export, graphics jpg export, graphics png export}. Save your test script.

Get path to the Parent Folder

To create paths for the export folder(s) we need to get the path to the folder chosen by the user from the dropdown. For this we will create a handler named getFolderPath which will take the user’s choice from the dropdown as its argument. The top portion of the script will now read as follows:

set folderList to {"desktop", "home folder", "document folder"}
set userResult to userDialog(folderList)
set folderPath to getFolderPath (item 1 of userResult)
folderPath

Add this handler to the bottom of your Test Script

on getFolderPath(choiceIndex)
   if choiceIndex is 1 then
	set folderPath to (path to desktop from user domain) as string
   else if choiceIndex is 2 then
	set folderPath to (path to home folder from user domain) as string
   else if choiceIndex is 3 then
	tell application "Adobe InDesign CC 2017"
	   set folderPath to (file path of document 1) as string
	end tell
   end if
   return folderPath
end getFolderPath

At this point we are assuming that the user has a document open and has made a selection in the dialog. You may wish to test the script at this point.

We now need to make sure folders exist for the jpeg and/or png exports, based on the export options checked in the dialog. This is returned to the main portion of the script as the second item of the list. We will place this value in a variable named choiceList. This will be the next statement in the main (top) portion of the script.

set choiceList to item 2 of userResult

Check for Folder(s)

If item 1 or 3 (or both) of choiceList is true the script will test for a folder named “images_Jpg”. Similarly if items 2 or 4 (or both) of choiceList is true, the script will check for a folder named “images_PNG”. Let’s write the code for this and test.

Add the following to the main section of the script (after the statement that sets the choiceList variable).

if choiceList contains true then
  if item 1 of choiceList or item 3 of choiceList then
    set jpgPath to checkFolder (folderPath, "images_jpg")
  end if
  if item 2 of choiceList or item 4 of choiceList then
    set pngPath to checkFolder (folderPath, "images_PNG")
  end if
end if

For the checkFolder handler, add the following to the bottom of the script:

on checkFolder(folderPath, folderName)
   tell application "Finder"
	set folderExists to exists folder (folderPath & folderName)
	if not folderExists then
	   make folder at folderPath with properties {name:folderName}
	end if
   end tell
   --returning string reference to the folder
   folderPath & folderName
end checkFolder

Test the script making sure to check at least one jpg option and one png option under an enabling group in the user dialog.

…options to use when testing

After running the script you should have a folder named images_jpg and one named images_PNG at the location designated from the user dialog dropdown (desktop by default).

Export Preferences

Another possible functionality you may want for the script is the option to set export preferences rather than assume they are set as needed. This opens up a whole new set of possibilities. You could:

  • Have default settings for the exports written into the script
  • Have the user determine if these default settings will need to be set

Lets explore this train of thought.

Add two more checkboxes to the user dialog to indicate the user’s choice for setting jpeg and PNG export preferences. For the last statement block inside the tell (make dialog coloumn) block, add:

tell (make dialog row)
   set jpgPrefs to make checkbox control with properties {static label: "Set jpeg export preferences", checked state: false}
   set pngPrefs to make checkbox control with properties {static label: "Set PNG export preferences", checked state: false}
end tell

Then below the comment that reads “capture results from widgets” add:

set preferencesList to {checked state of jpgPrefs, checked state of pngPrefs}

Lastly, change the return statement for the userDialog handler to read:

return {folderIndex, checkedList, preferencesList}

With this, we can add a call to a handler to set export preferences based on the list of preferences passed back from userDialog. Place this before the last end if in the main portion of the script:

if item 3 of userResult contains true then
   setExportPrefs (item 3 of userResult) 
end if

For the setExportPrefs handler, add the following to the bottom of the script:

on setExportPrefs (exportPrefs)
   tell application "Adobe InDesign CC 2017"
	if item 1 of exportPrefs then
	   set properties of JPEG export preferences to ¬
          {jpeg color space:RGB, JPEG Quality:high, JPEG Rendering style:baseline encoding, ¬
          use document bleeds:true}
	end if
	if item 2 of exportPrefs then
	   set properties of PNG export preferences to ¬
          {PNG color space:RGB, PNG Quality:medium, anti alias:true, export resolution:72, ¬
           Exporting Spread:false, transparent background:true, use document bleeds:true}
	end if
   end tell
end setExportPrefs

You may want to set your export preferences differently. Refer to Script Editor’s Dictionary for InDesign.

Bullet Proofing

Should you test the script without a document open, and select Document folder from the dropdown you will get an error. To handle this, we will add a handler to get a reference to the topmost document (document 1). If a document does not exist, an error is thrown. We will add a trap for this error later.

on getDocRef()
   tell application "Adobe InDesign CC 2017"
	if (count of documents) = 0 then
	   error "Requires open document with graphics for export."
	end if
	set docRef to document 1
   end tell
   return docRef
end getDocRef

Testing for the existence of a document should be done before we even present the user with a dialog. The following statement will now be the second line of the script.

set docRef to getDocRef ()

With all of this code in place, we still have not exported any groups or graphics from our document. As you can see, most of the supporting functionality has been moved to handlers. These handlers can possibly be used many times in other scripts. We have just one more handler to add: doExport, the code that does the actual export. Copy the following to the bottom of the script.

on doExport(docRef, jpgPath, pngPath, choiceList)
   tell application "Adobe InDesign CC 2017"
	tell docRef
	   if item 1 of choiceList or item 2 of choiceList then
		set groupList to every group & every group of every page item
		repeat with i from 1 to length of groupList
		   set itemId to id of item i of groupList
		   set itemClass to class of item i of groupList
		   if itemClass is group then
			if item 1 of choiceList then
			   export item i of groupList to ¬
                           (jpgPath & ":" & itemClass & "_" & itemId & ".jpg") format JPG
			end if
			if item 2 of choiceList then
			   export item i of groupList to ¬
                           (pngPath & ":" & itemClass & "_" & itemId & ".png") format PNG format
			end if
		   end if
		end repeat
	    end if
	    if item 3 of choiceList or item 4 of choiceList then
		set graphicList to all graphics
		repeat with i from 1 to length of graphicList
		   set itemId to id of item i of graphicList
                   set itemClass to class of item i of graphicList
		   if item 3 of choiceList then
			export item i of graphicList to ¬
                       (jpgPath & ":" & itemClass & "_" & itemId & ".jpg") format JPG
		   end if
		   if item 4 of choiceList then
			export item i of graphicList to ¬
                       (pngPath & ":" & itemClass & "_" & itemId & ".png") format PNG format
		   end if
		end repeat
	    end if
	end tell --document
   end tell
end doExport

With this in place we can now finalize the top (main) portion of the script. We will add the following:

  • default values for the jpgPath and pngPath variables
  • a try statement block to trap any errors
  • a call to the doExport handler

The top of the script will now look like the following:

Test Script

set folderList to {"Desktop", "Home Folder", "Document Folder"}
set jpgPath to missing value
set pngPath to missing value
try
   set docRef to getDocRef()
   set userResult to userDialog(folderList)
   set choiceList to item 2 of userResult
   if choiceList contains true then
	set folderPath to getFolderPath(item 1 of userResult)
	if item 1 of choiceList or item 3 of choiceList then
	   set jpgPath to my checkFolder(folderPath, "images_jpg")
	end if
	if item 2 of choiceList or item 4 of choiceList then
	   set pngPath to my checkFolder(folderPath, "images_PNG")
	end if
	if item 3 of userResult contains true then 
           setExportPrefs(item 3 of userResult)
        end if
	doExport(docRef, jpgPath, pngPath, choiceList)
   else
	error "No export choices made"
   end if
on error errMsg
   activate
   display alert errMsg
end try

Notice that we have simplified the main portion of the script from that in the previous blog post. By creating a handler to check for the active document we have put all statements targeted to the application in handlers. This modularizes the script while creating handlers that can be reused in other scripts down the road.

…the finished dialog with options to set export preferences

ON YOUR OWN

One nice little touch to the script would be to get a count of groups and a count of graphics exported and present the user a dialog with this information when the script completes. We will leave this (and further improvements to the script) up to you. Additionally, think about how you could made the script even more modularized by breaking the jpeg and png export processes into a separate handler from out of the doExport handler. Oh, and don’t forget to add a comment to the top each handler to describe its functionality and arguments.

ONWARD AND UPWARD

Yes, there is a lot of code involved in this script. But having a library of handlers at your disposal can made a script like this a simple matter to write (once you decide the functionality you want the script to have). In our next blog we will start a discussion on how you can create your own easy-to-use library of handlers.