Automating Adobe InDesign 2019 - AppleScript


Automate Placing Images - Grid

Tuesday, April 23, 2019

Automate Placing Images

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.

Read Plain Text File

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.

Grid of Images

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.

Calculate grid cell size

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}

Calculate Grid

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

Place Images in Grid

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

Close But Not Done

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 with images placed in grid...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. 

Onward and Upward

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.

Trackback Link
http://www.yourscriptdoctor.com/BlogRetrieve.aspx?BlogID=18424&PostID=1528972&A=Trackback
Trackbacks
Post has no trackbacks.

Recent Posts


Tags


Archive