Your prescription for increased productivity and profitability
Placing and positioning multiple files in an InDesign document one at a time can be a tedious and time-consuming process. There are a number of workflows that can be used to automate this process. With this post we will start a series that will explore some of these which, of course, involve using a script.
To build on our previous post, the workflow we will start with will use a plain text file that lists the names of the files to be used for the active page. Our text file will be placed in the same folder as the images and will list the files which for our demonstration are named as follows:
BalancingRock.jpg LavaRidges.jpg NorthValley.jpg FirstLight.jpg DeadTree.jpg GoldenThrone.jpg
The image names are listed in order of their intended placement on the page: left to right, top to bottom. The images are sized to 3.7 inches horizontal by 2.9 inches vertical. Once you have the images and the plain text file, start a script in Script Editor and paste in the following:
set fileChoice to choose file with prompt ("Choose plain text for file names") set fileList to readFileAsList(fileChoice) fileList (*Reads return-delimited plain text file as a list*) on readFileAsList(fileChoice) set fileRef to fileChoice as string return read file fileRef using delimiter "\n" end readFileAsList
Compile and run the script choosing the plain text file when prompted. The Result window should show the file names as a list. This list will be used by our demonstration script to place the images incrementally into a grid. To do this the script will need a path to the image files, not just the name. With the plain text file in the same folder as the images, the following handler can be used to get the path to the file.
(*Removes the name of the file from the filePath to return path to its parent folder*) on getParentFolder(filePath) set AppleScript's text item delimiters to ":" set folderPath to items 1 thru -2 of text items of filePath set folderStr to folderPath as string set AppleScript's text item delimiters to "" return folderStr end getParentFolder
Add this handler to the script above and change the top of the script to read as follows:
set fileChoice to choose file with prompt ("Choose plain text for file names") set fileList to readFileAsList(fileChoice) set folderPath to getParentFolder(fileChoice as string) set test to (folderPath & ":" & item 1 of fileList) as alias
This is just to test to make sure the path to the first file will be correct, assuming the others will also be correct. If your script runs without error, you are ready to put the rest of the script together.
Our script will need a letter size InDesign document (8.5 x 11 inches) with the following margins: top and bottom – 1 inch; left and right – .5 inches. With this document open, we will have our script create a grid of six rectangles. To do this, the script will first determine the width and height of the page area inside of the margins (live bounds). Our measurements will be calculated in points (72 to the inch). The calculation can be done using the following handler:
(*Returns geometric bounds of usable area inside page margins Assumes left and right margins are the same*) on getLiveBounds() tell application "Adobe InDesign CC 2019" set measurement unit of script preferences to points set pageRef to page 1 of active spread of layout window 1 of document 1 tell pageRef copy bounds to {y0, x0, y1, x1} tell margin preferences copy {left, top, bottom, right} to {lft, tp, bt, rgt} end tell set liveBounds to {y0 + tp, x0 + lft, y1 - bt, x1 - rgt} end tell end tell return liveBounds end getLiveBounds
Add this handler to the script above and change the top of the script to read as follows:
(*set fileChoice to choose file with prompt ("Choose plain text for file names") set fileList to readFileAsList(fileChoice) set folderPath to getParentFolder(fileChoice as string)*) set liveBounds to getLiveBounds()
In running the script with a document as specified above, the Result window should read as follows:
{72.0, 36.0, 720.0, 576.0}
Notice in the above that we have commented out the lines that read the plain text file as this is not needed at this point.
To calculate the width and height for the cells within a grid, the available page area (liveBounds) is used in the following generalized formulas:
totalWidth = item 4 of liveBounds - item 2 of liveBounds totalHeight = item 3 of liveBounds - item 1 of liveBounds cellWidth = totalWidth - ((numberCells - 1)* gutter))/numberCells cellHeight = totalHeight - ((numberCells - 1)* gutter))/numberCells
To test this out, add the following so the top of the script reads as follows:
set hCells to 2 set vCells to 3 set gutter to 12 set gap to 12 (*set fileChoice to choose file with prompt ("Choose plain text for file names") set fileList to readFileAsList(fileChoice) set folderPath to getParentFolder(fileChoice as string)*) set liveBounds to getLiveBounds() copy liveBounds to {py0, px0, py1, px1} set celWid to ((px1 - px0) - ((hCells - 1) * gutter)) / hCells set celHgt to ((py1 - py0) - ((vCells - 1) * gap)) / vCells {celWid, celHgt}
We will use these calculations inside a handler (calcGrid) that will use a nested repeat loop to create the geometric bounds for each of the rectangles of our grid. The geometric bounds for the grid rectangles is calculated based on the number of horizontal and vertical grid cells (hCells and vCells), the horizontal spacing (gutter), and the vertical spacing (gap) specified.
The script at this point should read as follows with the handlers getLiveBounds, readFileAsList and getParentFolder added at the bottom of the script:
set hCells to 2 set vCells to 3 set gutter to 12 set gap to 12 (*set fileChoice to choose file with prompt ("Choose plain text for file names") set fileList to readFileAsList(fileChoice) set folderPath to getParentFolder(fileChoice as string)*) set liveBounds to getLiveBounds() set gridBounds to calcGrid (liveBounds, hCells, vCells, gutter, gap) gridBounds (*Calculates grid given number of horizontal and vertical cells, gutter and gap*) on calcGrid(liveBounds, hCells, vCells, gutter, gap) set gridBounds to {} copy liveBounds to {py0, px0, py1, px1} set celWid to ((px1 - px0) - ((hCells - 1) * gutter)) / hCells set celHgt to ((py1 - py0) - ((vCells - 1) * gap)) / vCells set x0 to px0 set y0 to py0 repeat with i from 1 to vCells set y1 to y0 + celHgt repeat with j from 1 to hCells set x1 to x0 + celWid set end of gridBounds to {y0, x0, y1, x1} set x0 to x1 + gutter end repeat --j loop set x0 to px0 set y0 to y1 + gap end repeat --i loop return gridBounds end calcGrid --handler for getLiveBounds here --handlers for getParentFolder and readFileAsList here
Now all that is left for the script to do is create the grid and add the images. For this we create one more handler: placeImages. Change the top of the script to read as follows (notice comments have been removed from the three lines at the top).
set hCells to 2 set vCells to 3 set gutter to 12 set gap to 12 set fileChoice to choose file with prompt ("Choose plain text for file names") set fileList to readFileAsList(fileChoice) set folderPath to getParentFolder(fileChoice as string) set liveBounds to getLiveBounds() set gridBounds to calcGrid(liveBounds, hCells, vCells, gutter, gap) placeImages(fileList, folderPath, gridBounds)
Copy and add the placeImages handler to the script:
(*Creates grid using gridBounds and fills with images from the fileList*) on placeImages(fileList, folderPath, gridBounds) tell application "Adobe InDesign CC 2019" tell page 1 of active spread of layout window 1 of document 1 repeat with i from 1 to length of gridBounds set rectRef to make rectangle with properties {geometric bounds:item i of gridBounds, name:("image" & i)} set imageRef to (folderPath & ":" & item i of fileList) as alias tell rectRef place imageRef fit given fill proportionally end tell end repeat end tell end tell end placeImages
To make the script bulletproof, add a try statement before the line that sets the variable for fileChoice.
try
End this with an error statement to catch errors with a display alert and end try. Place this after the last line at the top of the script:
on error errStr activate display alert ("Error: " & errStr) end try
Run the script with your InDesign document open. If all goes well, your page should look similar to the following screen capture.
…Page after running script
Now all that is needed is a custom dialog to have the user to specify the number of rows, columns, gutter, and gap for the grid.
Instead of using a plain text file to designate the images to be added, you might have the user choose the image folder and get the names of the files using list folder. This workflow would require image placement to be designated possibly using a numerical file naming convention. We will see how this would be accomplished in our next blog post. We will also add a handler to create a custom dialog for entering grid specifications. See you then.
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.