Your prescription for increased productivity and profitability
To finish off our discussion series on working with lists, this post focuses on lists created and used when reading delimited text files. Along the way we will get a brief look at finding and replacing text in Adobe InDesign.
Lets say we have a plain text file with a number of text items separated with a line return. To use these text items in an InDesign document we want to place these into a list. For simplicity our file will read similar to the following:
Text for first paragraph Text for second paragraph Text for third paragraph
As a demonstration, our script will place each text item in the file to the beginning of consecutive paragraphs in an InDesign document.
First, we will need to have the script read the text file and place each text item into a list. We will set this up as a handler in AppleScript. The handler will use the choose file command to have the user identify the target file:
set textList to readFileAsList ("Choose plain text file to read") on readFileAsList(promptStr) set fileChoice to choose file of type "txt" with prompt promptStr set fileRef to fileChoice as string return read file fileRef using delimiter {"/n"} end readFileAsList
Although this handler is short there is a lot going on here. First an alias to the file chosen is placed into a variable using the choose file command. The alias reference is then coerced to a string. The methods for reading and writing files is part of AppleScript’s StandardAdditions. In its dictionary under the read we see:
read any : the file reference number, alias, or file reference of the file to read [using delimiter text] : the value that separates items to read… [using delimiters list of text] : …or a list of values that separate items to read that a file can be read
This requires a little explanation. Notice that the value of the delimiter for the first read option above is text. If you use the word return for the delimiter, the result will not be what you want. Instead, use the string equivalent of a line return “\n”.
set listText to read file textFileReference using delimiter return
The result will be a list of individual items. When the script is compiled, the value of the delimiter “\n” becomes a line return. The list is then returned to the variable textList which can then be parsed with each item used as needed in the script.
As in previous posts, a script can go through a list, item by item (parsing), using any one of a number of repeat methoods.
You can test this out by creating a script, the top part of which is as follows:
set textList to readFileAsList("Choose plain text file to read") set listLen to length of textList activate repeat with i from 1 to listLen display alert "Test " & item i of textList end repeat --Add readFileAsList handler here
Once a script has a list of strings, adding them to an InDesign document is a simple matter. With the readFileAsList handler added to the following, test with an open document with text added:
try set textList to readFileAsList("Choose plain text file to read") set listLen to length of textList tell application "Adobe InDesign CC 2019" set docRef to document 1 set paraCount to count of paragraphs of story -1 of docRef if paraCount ≥ listLen then repeat with i from 1 to listLen set thePara to (a reference to paragraph i of story -1 of docRef) set beginning of thePara to (item i of textList & " ") end repeat else error "Story does not have required number of paragraphs" end if end tell on error errStr activate display alert "Error: " & errStr end try --Add readFileAsList handler here
Notice that the variable for each paragraph (thePara) is a reference, and that a space is added to this variable as its value is added to the document.
Replacing text in a document is not quite as simple. Suppose our document has text to be replaced flagged with the following: “[text 1 here]” and so on scattered throughout the document. We could use a grep find and replace to do the job. The thing to remember is that the result of a find text returns the position of the text within the story as a reference:
text from character 1947 to character 1959 of story id 279 of document id 7 of application "Adobe InDesign CC 2019"
For this reason, the repeat structuref needs to work from the end of the story to the front so text replacements do not affect the position of the text to be replaced.
A grep string to replace any text within square brackets could be written:
set grepString to "\\[.*?\\]"
The script then sets find what of find grep preferences to the grepString. The result of the find grep method is a list of text references which can be used for replacement within a repeat loop. Finally, the demonstration script below resets find grep preferences to nothing to be a good neighbor. Add the readFileAsList handler to the following and test with a document to which you have added text flagged with square brackets to designate where text from the file read is to be inserted.
set grepString to "\\[.*?\\]" try set textList to readFileAsList("Choose plain text file to read") set listLen to length of textList tell application "Adobe InDesign CC 2019" set find grep preferences to nothing set find what of find grep preferences to grepString tell document 1 set findList to find grep set myLen to length of findList if myLen is not equal to listLen then error ("Not equal number of items for replacement") end if repeat with i from myLen to 1 by -1 set thisText to item i of textList tell item i of findList to set contents to thisText end repeat end tell set find grep preferences to nothing end tell on error errStr activate display alert ("Error: " & errStr) end try --Add readFileAsList handler here
In reading the dictionary for ScriptAdditions it would look as if you could read a tab return delimited file and get a list of lists. Close, but not quite. A script can get a list of the paragraphs and then use text item delimiters to change the tabbed items within each paragraph to a list.
set dataList to {} set promptStr to "Choose text file for data" set fileChoice to choose file of type "txt" with prompt promptStr set textFile to fileChoice as string set dataRead to read file textFile using delimiter {"/n"} set AppleScript's text item delimiters to " " repeat with i from 1 to length of dataRead set end of dataList to text items of item i of dataRead end repeat set AppleScript's text item delimiters to "" dataList --Add readFileAsList handler here
Think of the ways that you could use a text file to automate a repetitive process in InDesign. Then think of the various applications than can create a delimited text file. It opens the imagination to a variety of solutions that may work to automate any number of workflows.
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.