IMAGES IN TABLES

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.

CREATING TABLES WITH CODE

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:

Basic Table

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

READING TEXT FILE FOR TABLE CONTENTS

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 

CONVERTING PLACED TEXT TO TABLE

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 

ADDING IMAGES

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.

CREATE TABLE WITH IMAGES

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.

Demonstration Script

    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.

FIND/CHANGE IN TABLES

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()

STYLE CELLS AND TEXT

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.

FINE POINTS

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.