How To Write A Plugin

How Many People in my File

ACCESSING PROJECT DATA

We will want to use plugins to access the data in your project. To explain how this is done requires introducing several new concepts, the first of which is the 'item pointer'.

The following code simply loops through all the Individual records in the current project, and then reports on the number of Individual records found.
pi = fhNewItemPtr()  -- declare pointer and set to the first record.
        pi:MoveToFirstRecord('INDI')  -- Get first Individual in file
         
        iCount = 0
        while not pi:IsNull() do
           iCount = iCount + 1
           pi:MoveNext()
        end
        fhMessageBox('There are '..iCount..' people in the project')

A 'pointer' is like a bookmark.  You place a bookmark in  a book, to mark which page you are currently reading.  In the same way, you can move your pointer to point at (mark) the record or field that you are currently working with.

The function fhNewItemPtr creates an item pointer. The statement pi:MoveToFirstRecord positions this pointer to point at the first record of the specified type (the parameter 'INDI' indicates that the required record type is 'Individual').

The 'while' command is a Lua control command, which allows a section of code to repeat (to loop) until a condition is fulfilled.  The loop section of code is the lines between while and end.  The loop includes a pi:MoveNext() command.  This command moves the pointer (pi) to point to the next Individual record in the project.  When the end line is reached, processing jumps back to the while line. The while condition causes the code to continue to loop as long as the pi pointer is not Null. When pi becomes Null - which will happen when the pointer is moved past the last Individual record - the while loop is exited, and processing jumps to the first line after the end line.  At this point the message box will displayed.

Notice that iCount is set to zero outside of the loop. Failure to do this would mean that value of iCount would be nil (i.e. unassigned) and an error would occur when 1 was added to it. Whenever a while loop is used, the first value of the fields must be assigned outside of the loop or the loop will never be entered.

The following line increments the count:

iCount = iCount + 1

You can find out more about item pointers in the FH API/Item Pointer section.

Males and Females

More functionality can easily be added to the simple loop built above using the if .. then .. else .. end condition. The following code counts the number of males and females in the project:

pi = fhNewItemPtr()  -- declare pointer and set to the first record.
        pi:MoveToFirstRecord('INDI')  -- Get first Individual in file
        -- Initializing all the count values ensures they exist at the end.
        iCount = 0
        iNoSex = 0
        iMale  = 0
        iFemale = 0
        iOther = 0
         
        while not pi:IsNull() do
           iCount = iCount + 1
           ptrSex = fhGetItemPtr(pi,'INDI.SEX')
           if ptrSex:IsNull() then  --Check for the Sex item if none add to NoSex Count.
              iNoSex = iNoSex + 1
           else
              strSex = fhGetValueAsText(ptrSex) -- Get the Sex Value and add to the count based on the value.
              if strSex == 'Male' then
                 iMale = iMale + 1
              elseif strSex == 'Female' then
                 iFemale = iFemale + 1
              else
                 iOther = iOther + 1
              end
           end
              pi:MoveNext()
        end
        fhMessageBox('There are '..iCount..' people in the project\n'..
        'There are '..iMale..' men in the project\n'..
        iFemale..' women in the project\n'..
        iOther..' others in the project\n'..
        iNoSex..' people with a missing sex value in the project\n'
        )

Notice that at the beginning of the plugin, four additional variables are set to zero.

This code uses two new functions.  The first new function is fhGetItemPtr which allows you to use Family Historian Data References (see the main Help for more information on Data References if you are not familiar with them) to get a new item pointer from an existing one.  In the example it is given a pointer to an Individual record, and returns (thanks to the Data Reference, 'INDI.SEX') a pointer to the field which stores that person's sex.  This pointer is stored in the ptrSex variable.  The second new function, fhGetValueAsText, takes this pointer as a parameter and returns the value of the sex item as a string.  Before passing ptrSex to the function, however, a check is made to see if ptrSex is Null, using the IsNull() method (note the colon in "ptrSex::IsNull()").  A pointer will be Null if an attempt has been made to point it at something which does not exist.  In this case, if the pointer is Null, 1 is added to the iNoSex count.  If it is not Null, the string strSex is set to the value of the SEX field.  This string is then checked to see if it matches 'Male', 'Female' or something else,  and the appropriate counter variable is incremented.  Finally, a message box is displayed showing all the counter values.  The value '/n' is inserted into the strings,  to force a line break so that each counter is displayed on its own line.

In the next section, you will learn how to output more complex information, using a result set.