Your prescription for increased productivity and profitability
The big reason why people write and use scripts is to save time. Sure, it takes time to write a sript but over the long haul the time saved should reap big rewards. What often amazes me is just how quickly the computer can process a page or many pages of code. Mind blowing!
To see how long it takes a script to run you can put the following at the top of the script:
set startTime to (current date)
Then put the following at the end:
set timeLapse to (current date) - startTime activate display alert ("Time lapsed: " & timeLapse)
Just for fun I recently put these lines on a script that produces an 11×17 calendar from a template: Twelve pages with twelve images and twelve tables. The script took a total of 18 seconds with most of the time I am sure in how long it took me to locate the folder of images to be placed.
One big time saver in an InDesign script that has a fair amount of work to do in a document is to hide the screen display. This eliminates the time it takes to update the display. Makes sense!
The following sample script hides the screen display when it opens or creates a document from a template selected by the user. (Note: Requires a template saved to a folder named Templates inside the InDesign application folder.)
set savePrompt to "Select folder and enter file name for save" try tell application "Adobe InDesign CC 2019" set appPath to file path as string set templateFolder to appPath & "templates" set templatePath to my getFile(templateFolder) set docRef to open file templatePath without showing window --statements to process the document then display the window tell docRef to make window --save the document set savePath to choose file name with prompt savePrompt save docRef to savePath without force save end tell on error errStr activate display alert ("Error: " & errStr) end try (*Returns path to file selected from folder identified by folderPath*) on getFile(folderPath) set fileList to list folder folderPath without invisibles set userResponse to choose from list fileList if userResponse is not false then set fileChosen to item 1 of userResponse return folderPath & ":" & fileChosen else error "User did not select a file" end if end getFile
If the script will take more than a second or two to do its job you might want to let the user know that the script is working. Without a window displaying, the user may panic and think there was a problem with the script. Sadly, as far as I know, InDesign does not have the capability of displaying a floating window with AppleScript but we can use JavaScript to do the work for us. We do this with do script.
Do script is InDesign’s way of allowing code in a different language to be used. For the purpose of creating a floating window in an AppleScript script do script comes to the rescue in allowing our script to target JavaScript.
tell application "Adobe InDesign CC 2019" set docRef to make document without showing window --puts a floating window to the screen set startScript to my getStartScript() do script startScript language javascript tell docRef --statements that work with the document end tell --now to close the window set endScript to my getEndScript() do script endScript language javascript tell docRef to make window set active page of active window to page 1 of docRef end tell --javascript code to create floating window telling user the script is running on getStartScript() set js to "#targetengine \"session\"" & return set js to js & "w = new Window ('palette', ' ');" & return set js to js & "var myText = w.add('statictext', undefined, 'WORKING...Please be patient');" & return set js to js & "app.activate();" & return set js to js & "w.show();" return js end getStartScript --javascript code to close floating window on getEndScript() set es to "#targetengine \"session\"" & return set es to es & "w.hide();" & return return es end getEndScript
…Script is Working window
Interestingly, I have found very few scripts that would need this capability. This of course depends on the speed of the particular computer running the script. On the other hand, protecting a script from failing because of a user error is a more common issue.
The most common error a script needs to trap is the user clicking a Cancel button instead of performing the intended instruction. If nothing else, surround your script with a try/on error trap to catch this and any other user-centered error.
try --script statements on error errStr activate display alert ("Error: " & errStr) end try
One common error that pops up when a user gets distracted or otherwise takes longer than anticipated to respond is a timeout error.
…Timeout error display
Most commonly this happens when a choose method such as choose folder or choose file is issued within a tell statement to an application such as InDesign. In this instance, AppleScript, by default, gives the application statement 120 seconds for a response. For most purposes this is ample time, but to be safe you will want to extend the timeout to three minutes (or more) by surrounding problematic statements with a timeout block.
with timeout of 300 seconds --something the user might take a long time to do end timeout
To trap a timeout error test the number returned from the error.
set promptStr to "Select folder for images" try with timeout of 300 seconds tell application "Adobe InDesign CC 2019" set folderChosen to choose folder with prompt promptStr --statements that work with files in folder end tell end timeout on error errStr number errorNumber if errorNumber is -1712 then activate display dialog "User exceeded allowed time for response" giving up after 10 end if end try
Notice the giving up after parameter added to the display dialog statement above with 10 (seconds) as its value. This automatically closes the error dialog when the time (in seconds) is reached. Giving up after also works with display alert.
The problem with the above is that the original choose folder window stays around until physically dismissed. You can, however, modify the code above to close the choose folder window programmatically. Modify the code for the script Timeout Error above to read as follows:
set promptStr to "Select folder for images" tell application "Adobe InDesign CC 2019" with timeout of 300 seconds try set folderChosen to choose folder with prompt promptStr on error errStr number errorNumber if errorNumber is -1712 then activate display dialog "User exceeded allowed time for response" giving up after 10 my closeWindow("Choose a Folder") else display dialog "Error: " & errStr giving up after 10 end if end try end timeout end tell on closeWindow(windowName) tell application "System Events" to tell process "Adobe InDesign CC 2019" click (button "Cancel" of window windowName) end tell end closeWindow
This works similarly when working with display dialog,
Should you wish to close a display dialog window when a script exits with a timeout error, you first need to identify the window. This is done by defining its label value. The label value becomes the name reference for a click button statement. The sample script below uses try/on error to trap a display dialog timeout error. The user is given a message that closes after 10 seconds. The display dialog is then closed programmatically.
set closeWindow to false tell application "Adobe InDesign CC 2019" with timeout of 300 seconds try set userResponse to display dialog "Enter your name" default answer "John Jones" with title "Enter Name" on error errStr number errorNumber if errorNumber is -1712 then --timeout error set errStr to "User exceeded allowed time for response" set closeWindow to true end if activate display alert "Error: " & errStr giving up after 10 end try end timeout end tell if closeWindow then tell application "System Events" to tell process "Adobe InDesign CC 2019" if exists (button "OK" of window "Enter Name") then click (button "OK" of window "Enter Name") end if end tell end if
…Display Dialog with Label
Notice that the label of the display dialog window displays in its title bar.
Note: Methods for closing windows has changed with system releases. The methods shown above were tested with Mojave version 10.14.5.
Make sure you to extend the timeout value for your scripts that require user input, especially custom dialogs. And, if a timeout error raises its head, notify the user. Be aware of instances that can cause errors in your code when working with the user and set up traps to catch those errors.
Disclaimer:
Scripts provided are for demonstration and educational purposes. No representation is made as to their accuracy or completeness. Readers are advised to use the code at their own risk.