Marriage Length Report.fh_lua

--[[
@Title: Marriage Length Report
@Author: Jane Taubman
@Version: 1.1
@LastUpdated: Oct 2019
@Description: Reports Families with marriage dates, calculating the Marriage length taking into account, deaths of partners and divorce.
Please note where there are no death dates, Estimated Death values are used and can result in long marriages.
]]

function main()
    local tblOutput,iC = createResultTable()
    -- Define Columns
    tblOutput.length = {title='Length',type='integer',width=30,align='align_left',content={}, sort=1,ascending=false}
    tblOutput.fam = {title='F',type='item',width=1,align='align_left',content={}}
    tblOutput.husb = {title='Husband',type='item',width=80,align='align_left',content={}}
    tblOutput.husblifedates = {title='Dates Husb',type='text',width=40,align='align_left',content={}}
    tblOutput.wife = {title='Wife',type='item',width=80,align='align_left',content={}}
    tblOutput.wifelifedates = {title='Dates Wife',type='text',width=40,align='align_left',content={}}
    tblOutput.marriage = {title='Marriage',type='item',width=70,align='align_left',content={}}
    tblOutput.type = {title='Type',type='text',width=70,align='align_left',content={}}
    tblOutput.enddate = {title='End Date',type='date-point',width=70,align='align_left',content={}}
    -- Select Records to work on
    local res = fhMessageBox("Do you wish to select records?", "MB_YESNO")
    local reclist
    if res == "No" then
        reclist = allrecords('FAM')
    elseif res == "Yes" then
        reclist = fhPromptUserForRecordSel('FAM')
        if reclist == nil then
            return
        end
    else
        return
    end
    for _,pi in pairs(reclist) do
        local dtMarrDate = fhGetValueAsDate(fhGetItemPtr(pi,'~.MARR.DATE'))
        local dpMarrDate = dtMarrDate:GetDatePt1()
        local ph = fhGetItemPtr(pi,'~.HUSB>')
        local pw = fhGetItemPtr(pi,'~.WIFE>')
        if not(dpMarrDate:IsNull()) and ph:IsNotNull() and pw:IsNotNull() then
            -- Add Columns
            iC = iC + 1
            tblOutput.fam.content[iC] = pi:Clone()
            tblOutput.husb.content[iC] = fhGetItemPtr(pi,'~.HUSB>')
            tblOutput.wife.content[iC] = fhGetItemPtr(pi,'~.WIFE>')
            tblOutput.marriage.content[iC] = fhGetItemPtr(pi,'~.MARR.DATE')
            -- tblOutput.divorce.content[iC] = fhGetItemPtr(pi,'~.DIV')
            tblOutput.husblifedates.content[iC] = fhCallBuiltInFunction('LifeDates',ph)
            tblOutput.wifelifedates.content[iC] = fhCallBuiltInFunction('LifeDates',pw)
            local dpHusbDeath = fhCallBuiltInFunction('EstimatedDeathDate',ph, 'LATEST')
            local dpWifeDeath = fhCallBuiltInFunction('EstimatedDeathDate',pw, 'LATEST')
            local dtDivDate = fhGetValueAsDate(fhGetItemPtr(pi,'~.DIV.DATE'))
            local dpDivDate = dtDivDate:GetDatePt1()
            local dpToday = fhCallBuiltInFunction('Today')
            local dpEndDate
            local sType
            -- Marriage occured find lowest value
            if dpDivDate:IsNull() then
                -- Use Deaths if null they might be still alive so use today
                if dpHusbDeath:IsNull() then dpHusbDeath = dpToday end
                if dpWifeDeath:IsNull() then dpWifeDeath = dpToday end
                if dpHusbDeath:Compare(dpWifeDeath) < 1 then
                    dpEndDate = dpHusbDeath
                    sType = 'Husband\'s Death'
                else
                    dpEndDate = dpWifeDeath
                    sType = 'Wife\'s Death'
                end
            else
                dpEndDate = dpDivDate
                sType = 'Divorce'
            end
            if dpToday:Compare(dpEndDate) < 1 or dpEndDate:IsNull() then
                dpEndDate = dpToday
                sType = 'Current'
            end
            local dpLength = fhCallBuiltInFunction('Timespan',dpMarrDate,dpEndDate,'YEARS')
            tblOutput.length.content[iC] = dpLength
            tblOutput.enddate.content[iC] = dpEndDate
            tblOutput.type.content[iC] = sType
        end
    end
    fhOutputResultSetTitles("Marriage Lengths", "Marriage Lengths", "N.B Estimated Death value is used Print Date: %#x")
    for t in tblOutput() do
        fhOutputResultSetColumn(t.title, t.type, t.content, iC, t.width,t.align,(t.sort or 0),t.ascending)
    end
end
------------------------------------------ Functions

function allrecords(type)
    local list = {}
    local i = 0
    local ptr = fhNewItemPtr()
    ptr:MoveToFirstRecord(type) -- and set to the first record.
    while ptr:IsNotNull() do
        i = i + 1
        list[i] = ptr:Clone()
        ptr:MoveNext()
    end
    return list
end

function createResultTable()
    -- create metatable
    local tblOutput_mt = {}
    tblOutput_mt.col = 0
    tblOutput_mt.seq = {}
    tblOutput_mt.__newindex = function (t,k,v)
        rawset(t,k,v) -- update original table
        local m = getmetatable(t)
        m.col = m.col + 1
        table.insert(m.seq,k)
    end
    tblOutput_mt.__call = function (t)
        local i = 0
        local m = getmetatable(t)
        local n = table.getn(m.seq)
        return function ()
            i = i + 1
            if i <= n then return t[m.seq[i]] end
        end
    end
    local tblOutput = {} -- Define Columns Table
    setmetatable(tblOutput, tblOutput_mt)
    local iC = 0 -- Define count of lines
    return tblOutput,iC
end

-- If no table.getn function define one
if not(table.getn) then
  function table.getn(t)
      local count = 0
      for _, __ in pairs(t) do
          count = count + 1
      end
      return count
   end
end
------------------------------------------ Launch Main
main()

Source:Marriage-Length-Report-1.fh_lua