Your prescription for increased productivity and profitability
With the latest release of InDesign Adobe added the ability to place images in table cells. Now, if you manually place an image into a table, InDesign will consider the cell as an image frame. All frame and fitting options apply, making it much easier to create tables that include both text and graphics.
This is new ability is also welcomed by those of us who use scripts for creating tables. This is made possible by a new property which can be assigned to a cell: cell type.
For review, a table can be created with a script using a number of items for its parent, including a text frame, an insertion point, a text object, and more. Basically, your script tells the parent object to make a table, setting the properties for column count, body row count and, optionally, header row count and footer row count. When using a text frame as the parent, if no measurement is defined for the table or column widths, the table width will adjust to fill the width of the text frame. This is demonstrated in the following:
With a text frame selected, this script creates a basic table having the number of rows and columns as defined by the variables rowCount and colCount.
set colCount to 4 set rowCount to 6 tell application "Adobe InDesign CC 2015" --define the parent object set selList to selection if class of item 1 of selList is text frame then set frameRef to item 1 of selList --create the table tell frameRef set tableRef to make table with properties {column count:colCount, body row count:rowCount} end tell end if end tell
Your script can set the column and row dimensions as needed. In the following example, the parent text frame is created by the script.
set colCount to 5 set rowCount to 4 set rowHeight to "100 pt" set colWidth to "80 pt" set frameBounds to {"72 pt", "36 pt", "475 pt", "436 pt"} tell application "Adobe InDesign CC 2015" set pageRef to page 1 of document 1 tell pageRef frameRef to make text frame with properties {geometric bounds:frameBounds} end tell tell frameRef set tableRef to make table with properties {body row count:rowCount, column count:colCount} end tell tell rows of tableRef set height to rowHeight set auto grow to true --allows row to grow to accommodate text end tell tell columns of tableRef set width to colWidth end tell end tell
To add text from a file to the table created in the script above, you have several options. If the text file is written with tabs between columns and a return between rows, you can read the file and convert it to a list of lists (items for each list is the content for each cell of the row).
The text for a table having two rows and three columns would be similar to the following (spaces between cell items is a tab):
text for cell 1 row 1 text for cell 2 row 1 text for cell 3 row 1 text for cell 1 row 2 text for cell 2 row 2 text for cell 3 row 3
Add the following to the script above. This calls a handler that reads a tab/delimited file and converts it into a list of lists. The handler, “readForTable”, is listed below:
--add before last "end tell" in script above: set fileContents to my readForTable () repeat with i from 1 to rowCount tell row i of tableRef set contents to item i of fileContents end tell end repeat
(*Handler reads tab/return delimited text file and returns list of lists*) on readForTable() set colDelim to tab set rowDelim to return set fileChoice to choose file with prompt "Choose text file for table" set fileRef to open for access fileChoice if ((get eof fileRef) is not 0) then set theData to read fileRef as list using delimiter rowDelim set oldDelim to AppleScript's text item delimiters set AppleScript's text item delimiters to colDelim repeat with i from 1 to length of theData set thisList to text items of item i of theData set item i of theData to thisList end repeat set AppleScript's text item delimiters to oldDelim end if close access fileRef return theData end readForTable
Of course you can just place a tab/return delimited text file and convert the placed text to a table. Make sure that the styling for the default paragraph style is appropriate for the table.
(*Uses convert to table with tab/return delimited text file to determine rows and columns for creating table*) --assumes text cursor is selected in text frame tell application "Adobe InDesign CC 2015" set selList to selection if class of item 1 of selList is insertion point then set rowDelim to return set colDelim to tab --establish reference to selected insertion point set insertRef to item 1 of selList --establish reference to text frame that contains insertion point set parentRef to item 1 of text containers of parent of insertRef --have user select the tab/return plain text file set fileRef to choose file with prompt "Select tab/return delimited file for table" --place the text tell text 1 of parentRef set tableText to place fileRef --convert the placed text to a table convert to table column separator colDelim row separator rowDelim end tell end if end tell
To place images in cells, you can have the text file define the file’s name as part of the text file that is placed. Our sample text file reads like the following:
BARRY FOREMAN Tyler.jpg INNOVATION DIRECTOR AND OWNER #rCCS Design JESSICA FORD Janene.jpg PROFESSOR #rMonoceros #rInstitute of Art MIGUEL JULIAN Devon.jpg DESIGN DIRECTOR #rSynth Collective
As you can see, this text is tab/return delimited (tabs between columns and a return for each row. Because text in the cells for the third column will occupy more than one row, a special character combination is used to designate where a forced tab will be placed (more about this later). The text file is saved as plain text using a text editor such as TextEdit.
Notice that the entries for column two are the file names for the images to be placed.
To identify the location for the image files, the idea is to use a folder structure similar to the following:
parentFolder plain_text_file.txt imagesFolder image_File_1.jpg etc.
With files set up in the folder structure shown above, the script asks the user to select the text file. With the path to this file defined, there are several options for getting the path to the text file’s parent folder. For this demonstration, we will be using string manipulation. Try the following out for size:
--have user choose the file; the variable fileRef is alias reference to file chosen set fileRef to choose file with prompt "select tab/return delimited text file for placing" --convert alias reference to text set fileString to fileRef as string --string manipulation gets offset of last colon in the string fileString set oset to offset of ":" in ((reverse of (text items of fileString)) as string) --get the part of fileString from the first character to the last colon (counting from the end of the string) set imagePath to text 1 thru -oset of fileString & "images"
With the path to the image folder defined (imagePath), your script just needs to add a colon and the name of the file to create a reference to the image file for placing. Images are sized 100 pt by 100 pt at 300 dpi.
Our demonstration script assumes there is a document open that has a paragraph style named “Name” for styling the text in the first column. The text in the third column depends on the text settings for the default style. The script creates a text frame for the table, imports the text file chosen by the user, and converts the text to a table. Lastly, the script gets the names of the files from the cells and adds to the string defined by the variable imagePath and places it in the appropriate cell.
set fileRef to choose file with prompt "Select tab/return delimited text file" set fileString to fileRef as string -get path to parent folder set oset to offset of ":" in ((reverse of (text items of fileString)) as string) set imagePath to text 1 thru -oset in fileString & "images" tell application "Adobe InDesign CC 2015" set measurement unit of script preferences to points set rowDelim to return set colDelim to tab set pageRef to active page of active window tell pageRef --create text frame for table set frameRef to make text frame with properties {geometric bounds:{72, 36, 500, 336}} --place text file and convert text to table place file fileString on frameRef tell text 1 of frameRef convert to table column separator colDelim row separator rowDelim end tell --establish reference to table set tableRef to table 1 of frameRef --determine number of rows in table and set table height set rowCount to count of rows of tableRef set height of tableRef to ((rowCount) * 100) + rowCount set height of rows of tableRef to 100 set auto grow of cells of tableRef to false end tell ---place image files tell pageRef repeat with i from 1 to rowCount set filePath to imagePath & ":" & contents of cell 2 of row i of tableRef set cell type of cell 2 of row i of tableRef to graphic type cell set width of cell 2 of row i of tableRef to 100 set height of cell 2 of row i of tableRef to 100 place file filePath on rectangle 1 of cell 2 of row i of tableRef tell rectangle 1 of cell 2 of row i of tableRef to fit given content to frame end repeat end tell end tell
The table at this point looks like the following screen capture.
Now it is just a matter of styling cells, text, and doing a find/change to change occurrences of “#r” in text to a forced return.
A table, a column in a table, and a cell can all use find and change text to replace text in table cells. If you recall from working with find/change, the script first needs to clear out the find text preference and change text preference. The Demonstration Script will do this within a subroutine (handler) called initTextPrefs:
(*clear find and change text preferences*) on initTextPrefs () tell application "Adobe InDesign CC 2015" set find text preferences to nothing set change text preferences to nothing end tell end initTextPrefs
The code for the actual find and change process will also be housed in a subroutine (handler) FindChangeText(). For this handler we will pass a reference to the object that is executing the find/change, the text to find, and the text to use for change text. Here is the handler:
on findChangeText (objRef, findText, changeText) tell application "Adobe InDesign CC 2015" set find what of find text preferences to findText set change to of change text preferences to changeText tell objRef set textChanged to change text end tell end tell return textChanged end findChangeText
With the two handlers in place, the script needs to define the string for findText and changeText, and call the findChangeText handler from within the script.
At the top of the script add:
set findText to "#r" --special character combination used in text file to designate forced return set changeText to "^n" --metacharacter for forced return
Before the last “end tell” for the script add:
--find and change text in column 3 set objRef to column 3 of tableRef my initTextPrefs() set foundSet to my findChangeText(objRef, findText, changeText) my initTextPrefs()
To style cells and text, the script assumes there is a paragraph style named “Name” to use for styling the names in column 1. To finish off the script, add the following below the code added above. (just after the second my initTextPrefs())
--style cells and text; assumes paragraph style "Name" exists tell column 1 of tableRef set vertical justification to center align set applied paragraph style of paragraph 1 of every cell to "Name" end tell set objRef to column 3 of tableRef set vertical justification of objRef to center align
Once you get the script put together and tested without error, try running the script with a document open. Make sure there is a paragraph style named “Name” to be used to style the text in column 1. If all goes well, your table will look similar to the result of our Demonstration Script:
Demonstration Script table after styling
Yes, it may seem like using a script is a little more involved than creating the table manually. But, once, you have the script, all that is needed for creating a similar table is to create the tab/return delimited text file and save it to a designated folder. The folder will have a folder named “images” which will contain the images for the table sized as needed to fit. Run the script and select the text file. The script will do the rest.
Notice that the script sets the measurements for script preferences to points. This allows all of the measurements used in the script to be point values without altering the measurement units set for the document. Cool!
To keep the script as readable as possible, no test is used to make sure there are files named as defined by the file names in the cells of column 2. To make your script bullet-proof you will need to add this test. Other tests will also be needed to trap any errors the user may throw at the script.