Automating Adobe InDesign 2018


Tables and AppleScript

Monday, December 03, 2018

Wrapping Up Tables

If you have been following this post series you should be fairly comfortable using scripts to create tables with the aid of scripts. But there are a few issues that need to be covered before we close the door on our tables.

Deleting Cells

A recent post on Adobe's User Forum asked for a script to delete empty cells in a table. Never done that, so I did some tests. Every test I tried came back with the error "Cells cannot be deleted." That looks pretty definite.

On the other hand, you can merge cells, so I guess that is the best solution. Simplistically, you could look for every cell of a table where its contents is an empty string. Then, parsing through the list, if the parent column of the cell is not the last column of the table, merge the cell with the next cell. If the parent column of the cell is the last column of the table, merge the cell with the one previous. Sounds like a good example script to introduce the concept of a table cell's parents (parent row and parent column).

Introducing Cell Parents

Merge Empty Cells

(*requires text frame containing the table to be selected*)
tell application "Adobe InDesign CC 2018"
   set myTable to table 1 of item 1 of selection
   set myList to every cell of myTable where contents of it is ""
   set rowRef to parent row of item -1 of myList
   repeat with i from length of myList to 1 by -1
      set myCell to item i of myList
      set myIndx to index of myCell
      if parent column of myCell is not column -1 of myTable then
         set targetCell to cell (myIndx + 1) of myTable
      else
         set targetCell to cell (myIndx -1) of myTable
      end if
      tell rowRef to merge myCell with targetCell
   end repeat
end tell

Notice that the repeat loop starts with the last item in the list (myList) and works backward. This is to keep the references to the cells from shifting when cells are "deleted".

Interestingly, if you merge cells that contain content, the content remains, so you can end up with a graphic and its title in the same cell.

Next, you might want to resize the cells so they are the same width. Have your script calculate the widths and apply widths to cells. This is not one situation where you would consider using the redistribute method.

Redistribute

Redistribute is a touchy method and can be used to even out the width of columns (or the height of rows); but it only works under certain circumstances. For instance, if you have merged cells in row 1 to a single cell, trying to redistribute columns 2 thru whatever of the table won't work because there now is no column 2 in row 1.

To use redistribute, a range reference is required. Where this works best is when you resize the width of a column or the height of a row and you want to readjust the size of the remaining columns or rows to take up the remaining space equally. The following script demonstrates:

Redistribute

(*Requires open page in InDesign document*)
tell application "Adobe InDesign CC 2018"
   set measurement unit of script preferences to points
   tell page 1 of document 1
	set frameRef to make text frame with properties {geometric bounds:{30, 30, 450, 430}}
   end tell
   tell frameRef
	set tableRef to make table
   end tell
   tell tableRef
	set body row count to 5
	set column count to 4
	set header row count to 1
	set width to 400
	set height to 420
	set width of column 1 to 72
	set height of row 1 to 48
	redistribute column 2 thru column 4 using vertical
	redistribute row 2 thru row 6 using horizontal
    end tell
end tell

Alternating Rows

Of course you are going to use a table style to style your table, but for those one-off tables where you don't have a style, a script can easily add some styling. One situation may be to set rows and/or columns to alternate fill.

For the next example script, you may want to experiment with the table created using the Redistribute script above. Select its containing text frame and try the following:

(*Expects a text frame with a table to be selected*)
tell application "Adobe InDesign CC 2018"
   set frameRef to item 1 of selection
   set tableRef to table 1 of frameRef
   set myFill to swatch "Black" of document 1
   set altFill to swatch "Paper" of document 1
   tell tableRef
	set alternating fills to alternating rows
	set start row fill color to myFill
	set start row fill tint to 30
	set end row fill color to altFill
	set end row fill tint to 30
	set skip first alternating fill rows to 0
   end tell
end tell

Try changing the value for skip first alternating fill rows to 1 and run the script again. Try using alternating columns with alternating fills. Then, get brave and try alternating strokes.

Text for Tables

When designers are given a list of files to be used for tables in a document, they may be glad to know that the files have been created as tab-delimited text. But that is only one-half of the story.

How the text is set up may be far from what is needed for the final table. If you don't know how the tab-delimited file was created, it may be wise to just import the text and see what the heck you are up against. With Show Hidden Characters enabled, you should be able to determine what, if anything, needs to be done before the text is converted.

First, there is the problem of Character Set. If a character set other than UTF-8 or a type font other than OpenType is used, you may find many of the characters in the table are given a mixture of other-worldly characters. For just a few of these, you may decide to just do a quick Find/Change. (That's another whole subject of its own.)

Another common problem is empty columns. (The person entering the text, either did not clear default tabs, or forgot how many tabs were actually needed for a row.) This may only become obvious after converting the text to table.

A third problem is extra paragraph returns putting text that should all be in one row into several.

Whatever the problem, a script may be just the ticket to clean up the text and create the table for you (or fix some problems after the table is created). At the same time, the script can be applying cell styles and importing images based on the contents of the cell.

In each of the preceding, you will most likely select the text for the script and run the script using selection as the script's target reference. Just remember that the script requires a reference to the text.

Object Reference

Object reference is a subject new programmers often have a problem understanding. If you find yourself in this category, follow the few steps below.

What is selected? First, remember that selection returns a list. If text is selected the class of item 1 of the selection is text. Try the following with text selected.

(*Requires text selection*)
tell application "Adobe InDesign CC 2018"
   set selList to selection
   get class of item 1 of selList
end tell   --returns text

Item 1 of a text selection is a reference to the text. Change the code above to read. The result should be a text reference (text 1 of text frame ...):

tell application "Adobe InDesign CC 2018"
   set selList to selection
   if class of item 1 of selList is text then
     set objRef to item 1 of selList
   end if
end tell
objRef

If, on the other hand, an insertion point or a text frame is selected, you have another situation. Select a text frame (or its insertion point) and verify the selection:

tell application "Adobe InDesign CC 2018"
   set selList to selection
   if class of item 1 of selList is insertion point then
	set frameRef to item 1 of parent text frames of item 1 of selList
   else if class of item 1 of selList is text frame then
	set frameRef to item 1 of selection
   else
	activate
	display alert "Requires text frame or insertion point selection"
	return
   end if
	set objRef to text 1 of frameRef
end tell
objRef

You may be surprised to see the result of this script is the actual text. If this were used as the object to be converted to a table, you will get a nasty error. Instead change the last line before the end tel to read:

set objRef to a reference to text 1 of frameRef

When you run the script with this change, the result is something that reads like "text 1 of text frame..." Now you can complete the script with the following. With tab/return delimited text, your script should create a table.

tell objRef
   set tableRef to convert to table column separator tab row separator return
end tell

Notice in the above how the script tested to see if a text frame or its insertion point is selected. Having the insertion point selected is a common error users often make when instructed to select a text frame.

Above and Beyond

Some hints on getting the most from your table and cell styles.

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=18391&PostID=1527995&A=Trackback
Trackbacks
Post has no trackbacks.