Your prescription for increased productivity and profitability
Previous posts demonstrate how we can use a text file to provide information for creating a grid of images with and without a caption. But what if you want to set up a document template that does not require a grid of images. Instead you would like to have placeholders for images placed strategically on pages. To automate image placement you may decide to use a script. For this some method will be needed to identify how placeholders will be matched to images to be placed. One way to do this is to use a naming convention. We will explore this option.
A simple naming convention can be to use an incremented number as part of the name for the placeholder as well as the image. For instance, the placeholders could be named Image_01 through Image_99 and the file names could start with the incremented number, as in:
01_[Name of file.jpg]
The link, of course, is the number.
For naming image placeholders you could select the items and use the following:
tell application "Adobe InDesign CC 2019" set selList to selection if selList is not {} then set rectList to every item of selection where class of it is rectangle repeat with i from 1 to length of rectList set theName to "image_" & (text -1 thru -2 of ("00" & i)) set name of item i of theList to theName end repeat end if end tell
Notice the statement that creates the name using the repeat variable i.
set theName to "image_" & (text -1 thru -2 of ("00" & i))
This insures that numbers 1 through 9 are preceded with a zero, so that all numbers will have two digits. Be aware that the rectangles will be named in the order in which they were selected.
To place the images to the active spread, the following script could be used:
set theFolder to choose folder with prompt ("Select folder of images for placement") set folderStr to theFolder as string set fileNames to list folder theFolder tell application "Adobe InDesign CC 2019" set thePage to active spread of layout window 1 set rectList to every rectangle of thePage where name of it begins with "Image_" repeat with i from 1 to length of rectList set theName to name of item i of rectList set theNumber to (text -1 thru -2) of theName set fileName to my getFileName(theNumber, fileNames) set fileRef to (folderStr & fileName) as alias tell item i of rectList place fileRef fit given fill proportionally end tell end repeat end tell (*Uses repeat loop to find the item in the list that begins with the value of the variable theNumber*) on getFileName(theNumber, fileNames) repeat with everyItem in fileNames if everyItem begins with theNumber then exit repeat end if end repeat return contents of everyItem end getFileName
The above will work only if all the rectangles are in the same spread. If more than one spread is involved, you will need to have some way to designate the spread as part of the naming convention or provide a way for the user to indicate the beginning number for the selected items.
If the document is to have images on a number of spreads it may be best to place all of the image placeholders on a specific layer. For the purpose of the following example script, the layer is named “Images”. A problem becomes apparent when placing the images. A list of all of the images found on the layer does not return the items in the order in which they were created. But there is a fix. When page items are created, InDesign assigns them an id incrementally. To name the items in the order of creation, the script can get a list of item ids and then sort the list. This is used in the following:
set layerName to "Images" tell application "Adobe InDesign CC 2019" set docRef to document 1 tell docRef set layerRef to layer layerName set idList to id of rectangles of layerRef set sortedList to my sortList(idList) repeat with i from 1 to length of sortedList set theName to "image_" & (text -1 thru -2 of ("00" & i)) set name of rectangle id (item i of sortedList) to theName end repeat end tell end tell sortedList (*Sorts list of numbers in ascending order*) on sortList(idList) set indexList to {} set sortedList to {} repeat (length of idList) times set lowItem to 0 repeat with i from 1 to (length of idList) if i is not in indexList then set thisItem to item i of idList if lowItem is 0 then set lowItem to thisItem set lowItemIndex to i else if thisItem comes before lowItem then set lowItem to thisItem set lowItemIndex to i end if end if end repeat set end of sortedList to lowItem set end of indexList to lowItemIndex end repeat return sortedList end sortList
To place the images into their respective placeholders, a script almost the same as the one above (Place Images to Named) can be used. In fact the script is so similar, you can copy it and paste it into a new script and make just a few changes. The changes are in the first three lines following the tell statement to InDesign.
tell application "Adobe InDesign CC 2019" set docRef to document 1 set layerRef to layer "Images" of docRef set rectList to every rectangle of layerRef where name of it begins with "Image_" All the rest of the script is the same.
One option for adding captions would be to set up a document template with text frames to which Live Captions have been assigned (Object > Captions). The cool thing about Live Captions is that the assigned text frame is automatically populated using information found in the image file (metadata).
Those who have worked with InDesign’s Caption feature have discovered it can have some serious limitations. For this reason we will use the script that places the images. This will require that the images have metadata that can be used for the captions. The metadata will define the Document Title and Description in the image file. Metadata can be assigned while processing the file in Photoshop (File > File Info).
For styling the caption, the document will require a text object style named “Caption”. This style will use a paragraph style named “Caption” with Next Style checked. The Caption paragraph style will have a paragraph style named “Description” as its Next Style. To create a space between the image frame and the caption frame, set Inset Spacing for Top as desired (about 6 to 9 points).
global captionDepth --depth of text frame for caption set captionDepth to 60 set layerName to "Images" set theFolder to choose folder with prompt ("Select folder of images for placement") set folderStr to theFolder as string set fileNames to list folder theFolder set objectStyleName to "Caption" tell application "Adobe InDesign CC 2019" set measurement unit of script preferences to points set layerRef to layer layerName of document 1 set objectStyleRef to object style objectStyleName of document 1 set rectList to every rectangle of layerRef where name of it begins with "Image_" repeat with i from 1 to length of rectList set theName to name of item i of rectList set theNumber to (text -1 thru -2) of theName set fileName to my getFileName(theNumber, fileNames) set fileRef to (folderStr & fileName) as alias tell item i of rectList place fileRef fit given fill proportionally set imageRef to image 1 set gBounds to geometric bounds set parentPage to parent page set layerRef to item layer end tell set linkRef to item link of imageRef my addCaption(gBounds, linkRef, parentPage, layerRef, objectStyleRef) end repeat end tell (*Creates text frame for images that have metadata, sets text content, assigns item layer and object style*) on addCaption(gBounds, linkRef, parentPage, layerRef, objectStyleRef) tell application "Adobe InDesign CC 2019" copy gBounds to {y0, x0, y1, x1} set linkMeta to properties of link xmp of linkRef set textStr to document title of linkMeta & return set textStr to textStr & description of linkMeta if textStr is not "" then tell parentPage make text frame with properties {geometric bounds:{y1, x0, y1 + captionDepth, x1},¬ contents:textStr, item layer:layerRef, applied object style:objectStyleRef} end tell end if end tell end addCaption (*Uses repeat loop to find the item in the list that begins with the value of the variable theNumber*) on getFileName(theNumber, fileNames) repeat with everyItem in fileNames if everyItem begins with theNumber then exit repeat end if end repeat return contents of everyItem end getFileName
If all goes well and the target document has a text frame Object Style with paragraph styles established, the placed images with their captions should look similar to the screencapture below.
…Our sample image with caption
A lot of territory was covered in the scripts above. Walk through the code to make sure you understand how each script and its handlers accomplish the automation. To keep the code as concise as possible, the scripts make a lot of assumptions. To bullet-proof the scripts be sure to surround the top portion of the script with a try/on error trap to notify the user of a problem and exit the script gracefully.
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.