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.
# Verify acceptable version of GEDitCOM II is running and a document is open. # Return 1 or 0 if script can run or not. def CheckAvailable(gedit,sName,vNeed) if gedit.versionNumber()<vNeed errMsg = "The script '" + sName + "' requires GEDitCOM II, Version "\ + vNeed.to_s + " or newer.\nPlease upgrade and try again." puts errMsg return 0 end if gedit.documents().count()<1 errMsg = "The script '"+sName+"' requires requires a document to be"\ + " open\nPlease open a document and try again." puts errMsg return 0 end return 1 end
Nearly all GEDitCOM II scripts will start by calling this subroutine to verify the script can run.
First, this subroutine checks the version number of GEDitCOM II by using the
versionNumber() property of the application (using application reference in first argument). As GEDitCOM II develops, it will add new scripting features, but new features cannot be used unless the version currently running supports them. The AppleScripting dictionary for GEDitCOM II will mention which features are only available in some versions (e.g., it will say "since 1.5" for a particular command or property). If you use such a feature, this subroutine can verify that feature is in the currently running GEDitCOM II. The version number you need is passed in the
vNeed subroutine argument.
Second, it almost never makes sense to run a script unless a document is open. The second check verifies that at least one document is open.
Finally, this subroutine returns
1 if it passes all tests or returns
0 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.
# set progress variables fractionStepSize = nextFraction = 0.01 # main script loop for i in 1...numTasks # the script code # time for progress fractionDone = Float(i)/Float(numTasks) if fractionDone > nextFraction: gdoc.notifyProgressFraction_message_(fractionDone,nil) nextFraction = nextFraction + fractionStepSize end end
Scripting of GEDitCOM II 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 percent. 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 (converted to floating point). If this fraction has passed a predetermined notification point (stored in
nextFraction), a notification is sent to a document (here it is assumed
gdoc references a document) using the
notifyProgressFraction_message_() 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 three options. First, you can periodically guess the fraction done and send a
notifyProgressFraction_message_() to a document. Second, you can post a message to the user with the second argument to the
notifyProgressFraction_message_(); 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. For Ruby scripts, that palette will also have an abort button (with an "
X") that can be clicked to stop any script.
# Convert two date SDNs to years from first date to second date def GetAgeSpan(beginDate, endDate) return (endDate - beginDate) / 365.25 end
This simple subrouting converts the time between two day numbers into the number of years. The time span is from the
beginDate to the
# convert string to AppleScript enumerated constant def GCConstant(uniqueStr) if uniqueStr=="chart" byteForm = 0x74724348 # trCH elsif uniqueStr=="outline" byteForm = 0x74724F55 # trOU elsif uniqueStr=="the children" byteForm = 0x736B4348 # skCH elsif uniqueStr=="the events" byteForm = 0x736B4556 # skEV elsif uniqueStr=="the spouses" byteForm = 0x736B5350 # skSP elsif uniqueStr=="char_MacOS" byteForm = 0x784F7031 # xOp1 elsif uniqueStr=="char_ANSEL" byteForm = 0x784F7032 # xOp2 elsif uniqueStr=="char_UTF8" byteForm = 0x784F7033 # xOp3 elsif uniqueStr=="char_UTF16" byteForm = 0x784F7034 # xOp4 elsif uniqueStr=="char_Windows" byteForm = 0x784F7035 # xOp5 elsif uniqueStr=="lines_LF" byteForm = 0x784F7036 # xOp6 elsif uniqueStr=="lines_CR" byteForm = 0x784F7037 # xOp7 elsif uniqueStr=="lines_CRLF" byteForm = 0x784F7038 # xOp8 elsif uniqueStr=="mm_GEDitCOM" byteForm = 0x784F7039 # xOp9 elsif uniqueStr=="mm_Embed" byteForm = 0x784F7041 # xOpA elsif uniqueStr=="mm_PhpGedView" byteForm = 0x784F7042 # xOpB elsif uniqueStr=="logs_Include" byteForm = 0x784F7043 # xOpC elsif uniqueStr=="logs_Omit" byteForm = 0x784F7044 # xOpD elsif uniqueStr=="places_Include" byteForm = 0x784F7045 # xOpE elsif uniqueStr=="places_Omit" byteForm = 0x784F7046 # xOpF elsif uniqueStr=="books_Include" byteForm = 0x784F7047 # xOpG elsif uniqueStr=="books_Omit" byteForm = 0x784F7048 # xOpH elsif uniqueStr=="settings_Embed" byteForm = 0x784F7049 # xOpI elsif uniqueStr=="settings_Omit" byteForm = 0x784F7050 # xOpJ elsif uniqueStr=="thumbnails_Embed" byteForm = 0x784F7051 # xOpK elsif uniqueStr=="thumbnails_Omit" byteForm = 0x784F7052 # xOpL elsif uniqueStr=="locked" byteForm = 0x724C636B # rLck elsif uniqueStr=="privacy" byteForm = 0x72507276 # rPrv elsif uniqueStr=="unlocked" byteForm = 0x72556E6C # rUnl else byteForm = 0 end return byteForm end
Some commands take arguments that select among two or more defined constants (such as
outline for family trees). Similarly, the
restriction property of individual records returns a defined constant (amoung
privacy). These constants are used in AppleScript by their name, but in Ruby scripts, you have to use the underlying numeric codes instead. The
GCConstant() subroutine solves this problem by translating any constant to its numeric value. The constant's name is passed as the subroutine's single argument as a string variable. For example.
GCConstant("chart") will return the numeric value for the chart constant.