
This page lists some utility subroutines that may be used by more than one tutorial:
These utilities are written to be as general as possible so then can be reused in different scripts. You can copy and paste the script code in the boxes on this page into your own scripts.
(* Activate GEDitCOM II (if needed) and verify a document is open.
Return true or false if script can run.
*)
on CheckAvailable(sName)
tell application "GEDitCOM II"
activate
if number of documents is 0 then
user option title "The script '" & sName & ¬
"' requires a document to be open" ¬
message "Please open a document and try again." ¬
buttons {"OK"}
return false
end if
end tell
return true
end CheckAvailable
Nearly all GEDitCOM II scripts will start by calling this subroutine to verify that a document is open (because most scripts work on data in one or more documents). You can optionally add other checks to this method before the script is allowed to run.
This subroutine returns true if it passes all tests or returns false if any test fails. Note that the script name is passed in the variable sName. If needed, that name is displayed in a message window that explains the reason the script will not run.
Prior to GEDitCOM II, version 2.0, this subroutine would also check the version number and verify it was new enough for the current script. You should still check version number, but once you package the script in an extension, you can specify a minimum version number and that check will be done automatically before running the script.
-- set progress variables
set {fractionStepSize, nextFraction} to {0.01, 0.01}
-- main script loop
tell application "GEDitCOM II"
repeat with i from 1 to numTasks
-- the script code
-- time for progress
set fractionDone to i / numFams
if fractionDone > nextFraction then
notify progress fraction fractionDone
set nextFraction to nextFraction + fractionStepSize
end if
end repeat
end tell
notify progress CommandAppleScripting is a great tool, but it can get slow for large calculations in large files. For this reason, all good GEDitCOM II scripts should inform the user of the progress of the calculations. The code on the right gives the logic
At the beginning of the script you define two variables. The fractionStepSize defines how often to inform the user of progress. There is no point in sending too many notifications since the progress is rounded to the nearest present. A good choice is usually to notify the user after each percent is completed and thus fractionStepSize is set to 0.01. The nextFraction variable defines the next time the notification should be sent to GEDitCOM II. It is initialized to the same value as fractionStepSize to define the point for the first notification.
Periodically during the script, you should then calculate the fraction of the script that has finished. This sample code shows a script with a repeat loop that will execute numTasks times. At the end the each pass through the loop, the fractionDone is easily calculated to be i/numTasks. If this fraction has passed a predetermined notification point (stored in nextFraction), a notification is sent to GEDitCOM II using the notify progress command and nextFraction is advanced by the fractionStepSize defined at the start of the script.
For other scripts, it may be harder to determine the fraction completed (such as a script searching for ancestors when you do not know how many ancestors will be found). For these scripts, you have two options. First, you can periodically guess the fraction done and send a notify progress to GEDitCOM II. Second, you can post a message to the user with a second message argument to the notify progress command; it can be any string. Third, you can do nothing. The scripting palette in GEDitCOM II will still show a spinning progress wheel to indicate the script is still running.
(* Convert two date SDNs to years from first date to second date *) on GetAgeSpan(beginDate, endDate) return (endDate - beginDate) / 365.25 end GetAgeSpan
This simple subrouting converts the time between two day numbers into the number of years. The time span is from the beginDate to the endDate.
(* Round number n to numDecimal digits *)
on RoundNum(n, numDecimals)
if numDecimals = 0 then
return round n as string
end if
set x to 10 ^ numDecimals
set nstr to ((((n * x) + 0.5) div 1) / x) as string
set decPt to offset of "." in nstr
if decPt = 0 then
set nstr to nstr & "."
set extra to numDecimals
else
set extra to numDecimals - (number of characters in nstr) + decPt
end if
repeat with i from 1 to extra
set nstr to nstr ∓ "0"
end repeat
return nstr
end RoundNum
When outputting decimal numbers to a report or to a text file, it is often useful to control the format of the output number. I don't know of a AppleScript method for the task, but this subroutine does some formatting. Given any number in n, it will return a string representation of the number with numDecimals digits after the decimal point. If fewer digits are needed, extra "0" digits will added to reach the desired number of digits.
For example:
RoundNum(43.81534,2) -> 43.82
RoundNum(72,3) -> 72.000
RoundNum(22.8144,1) -> 22.8
RoundNum(52.8144,0) -> 53
(* Change current selection to theText using paragraph properties in pstyle
When done, move the selection point to the end of the inserted text.
*)
on TextToPages(theText, textStyle)
tell application "Pages"
tell front document
set nc to count of characters
set selection to theText & " "
set endnc to count of characters
if textStyle is not "" then
set nc to nc + 1
tell characters nc thru endnc
set properties to textStyle
end tell
end if
select character endnc
set selection to ""
end tell
end tell
end TextToPages
Figuring out how to add style text to a Pages document is challenging. This utility subroutine solves the problem and may be all you need to write scripts to create Pages documents. The subroutine write the text in theText to the current selection and then moves the insertion point to after the entered text. A series of calls to this subroutine can build any report by adding blocks of text to the document. WARNING: this Pages output option only works for Pages 4.x and older. Apple unfortunately decided to delete nearly all AppleScripting feature of Pages when they released Pages 5.0.
The textStyle parameter lets you control the font and paragraph style for the inserted text. This parameter is an AppleScript record with any property allowed in the character element defined in Pages' scripting dictionary. When inserting a series of text blocks, the textStyle only needs to include properties that have changed from the previous text. If there are no changes, it can be an empty string ("")
The subroutine sets the current selection to the input text and adds a single blank character. If textStyle is provided, it is used to set the properties of the recently inserted text. Finally, the last character of the inserted text is selected and deleted. This deleted character is the blank character inserted above. When done the selection point will be at the end of the document ready to insert the next text. The extra blank character was a trick that solved the problem of getting the selection to the end of the inserted text in all cases; there may be other solutions, but this one works.
(* Insert the text using changes in font in fontStyle and changes in
paragraph style in paraStyle. Either can be "" to ignore. The new
text replaces the current selection.
*)
on TextToWord(theText, fontStyle, paraStyle)
tell application "Microsoft Word"
tell selection
if fontStyle is not "" then
set properties of font object to fontStyle
end if
if paraStyle is not "" then
set properties of paragraph format of text object to paraStyle
end if
type text text theText
end tell
end tell
end TextToWord
The MS Word scripting dictionary is complex and verbose. It took some work to come up with a reliable method for inserting formatted text, but this method does the trick and turned out rather simple.
This subroutine will replace the current selection with theText and format the new text using the font style in fontStyle and the paragraph style in paraStyle. These two style parameters should be an AppleScript record. They can contain any property allowed for the font object or the paragraph format elements, both of which are defined in MS Word's scripting dictionary. When inserting a series of text blocks, the style parameters only need to include properties that have changed from the previous text. If there are no changes, they can be empty strings ("")
When the method is done, the insertion point will be moved to the end of the new text. A series of calls to this method can build a report by inserting blocks of text with any style desired. The key AppleScript command was the type text command. The philosophy of the MS Word scripting interface is more like "Macros" than background program. The scripting options are meant to duplicate all the ways a user can interact with MS Word. Here the type text command is literally typing the text you provide into the document after setting the new font and paragraph styles.