Writing Script Results to an MS Word Document

The main AppleScript tutorial outputs the report to a GEDitCOM II window. One advantage of AppleScript is that scripts can send messages to any scriptable application. Using this feature, AppleScripts can export reports to other applications and, in some cases, use scripting tools of that application to format nice output. This tutorial demonstrates this option by describing the changes needed to output the report to an MS Word document. The entire script is actually the same except for the WriteToReport() subroutine that is described in this tutorial.

This new script is in the "Generation Ages To MS Word.applescript". To run this tutorial report, select "Custom Report Tutorial" from the Extensions menu and then choose the "AppleScript Custom Report to MS Word" option. Because output is to MS Word, the script requires MS Word to be on your computer. To view the script source, expand "Properties" section of the extension, click on "other files" and then double click on "Generation Ages To MS Word.applescript". The AppleScript will open in Script Editor for viewing and editing.

The ability of AppleScripts run by applications (such as in GEDitCOM II extensions) has unfortunately been blocked for any applications in the AppStore. As a consequence, this script only works in GEDitCOM II and not in the AppStore version GEDitCOM.

WriteToReport() Subroutine

Listing 3
(* Write the results now in the global variables to an MS Word document *)
on WriteToReport()
  set fname to name of front document of application "GEDitCOM II"
  
  tell application "Microsoft Word"
    make document
    set titleFont to {name:"Times New Roman", font size:14, Â
        bold:true, italic:false}
    set titlePara to {alignment:align paragraph center}
    set captionFont to {font size:12, bold:false, italic:true}
    set captionPara to ""
    set headerFont to {bold:true, italic:false}
    set tablePara to {alignment:align paragraph left}
    set rowFont to {bold:false}
  end tell
  
  -- title
  TextToWord("Generational Age Analysis in " & fname, titleFont, titlePara)
  TextToWord(return & return, "", "")
  
  -- caption
  TextToWord("Summary of spouse ages when married and when children were born", Â
      captionFont, captionPara)
  TextToWord(return & return, "", "")
  
  -- first row is column labels
  tell selection of application "Microsoft Word"
    set tableStart to selection end
  end tell
  TextToWord("Age Item" & tab & "Husband" & Â
      tab & "Wife" & return, headerFont, tablePara)
  
  -- rows for ages when married and when children were borm
  TextToWord(InsertRowSep("Avg. Age at Marriage", numHusbAge, Â
      sumHusbAge, numWifeAge, sumWifeAge), rowFont, "")
  TextToWord(InsertRowSep("Avg. Age at Childbirth", numFathAge, Â
      sumFathAge, numMothAge, sumMothAge), "", "")
  
  -- format the table
  tell application "Microsoft Word"
    -- select the table text and convert to MS word table
    tell selection
      set tableEnd to selection end
    end tell
    -- need this approach since separator option in convert to table broken
    set default table separator to tab
    set aDoc to the active document
    set myRange to set range text object of aDoc start tableStart end tableEnd
    set myTable to convert to table myRange table format table format grid3
    
    -- do some table formatting
    set alignment of paragraph format of text object of Â
         first row of myTable to align paragraph center
    repeat with i from 2 to 11
      repeat with j from 2 to 3
        set acell to get cell from table myTable row i column j
        set alignment of paragraph format of text object of Â
            acell to align paragraph center
      end repeat
    end repeat
  end tell
end WriteToReport

(* Insert table row with husband and wife results in plain text *)
on InsertRowSep(rowLabel, numHusb, sumHusb, numWife, sumWife)
  set tr to rowLabel & tab
  if numHusb > 0 then
    set tr to tr & RoundNum(sumHusb / numHusb, 2) & tab
  else
    set tr to tr & "-" & tab
  end if
  if numWife > 0 then
    set tr to tr & RoundNum(sumWife / numWife, 2)
  else
    set tr to tr & "-"
  end if
  return tr & return
end InsertRowSep

Microsoft Word is fully scriptable and provides an enormous number of options (a text copy of its scripting dictionary posted by Microsoft is 574 pages). It is tricky to get started and some features of the AppleScripting interface do not work (one to create tables was needed for this script). Again, the key task is to write formatted text to a new document. A utility method called TextToWord() was written to accomplish this task. The WriteToReport() subroutine (shown on the right) uses that method along with some direct commands to create the report.

The first section makes a new document and defines some font and paragraph styles to be used later. The TextToWord() subroutine is then used to add the title and caption. This method takes three parameters - the text to add to the report, the style for the font for that text, and the style for the paragraph to hold the text. The styles are AppleScript records and use options from MS Word's scripting dictionary.

The next section creates the table. The process is to insert table text using tab delimited items in each row, to select all inserted text, and then to invoke MS Word's convert to table command. Here the header rows are inserted and the report rows are inserted using the InsertRowSep() subroutine.

The last section selects the text for the table and converts to a table. Although MS Word's dictionary defines an option on the convert to table command to set the separator used in the text between columns, that option does not work. The problem was solved by setting the default table separator to tab before using the convert to table command. The table is created using a built-in MS Word style ("grid3"). Once the table is created, some additional MS Word options are used to set alignments of the cells in the table.

Alternatives

The option to work with other applications could write a report to any scriptable application. The challenge in that task is always to learn how to script the other application. The first steps are:

  1. Start Apple's "Script Editor" application (in Applications/Utilities folder).
  2. Use "Open Dictionary..." menu command and choose the application you want to target.
  3. Read the dictionary and try to work out how to write a report to that application.

AppleScript dictionaries are most useful when you already know how to script an application; they are more a reference than they are scripting documentation. If you have experience in AppleScript, you may be able to proceed. Most likely, your scripting goals will require much experimentation to see how the other application behaves.

An obvious extension of exporting to MS Word is to export to Pages instead (because Pages is provided with MacOS). While this used to work, Apple removed almost all the scriptability of Pages starting with version 5.0. It is still possible to output to current Pages, but it requires low level "key stroke" methods, which may or may not continue to work. You can see a sample of this method in action by opening "AncestorsOutline.gplug" in GEDitCOM Editor, expanding "Properties" section, clicking on "other files", and then double clicking "Ancestors_To_Pages5.applescript" to open it in "Script Editor." The name says Pages 5, but that is just when it needed to be written. As of now (March 2024), it continues to work on all subseauent Pages versions. Scripting of current Pages lacks many of the options for outputing to MS Word, but at least continues to provide a document.