Your prescription for increased productivity and profitability
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.
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.
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.
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
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).
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:
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.
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:
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
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.
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.