Result Set Creation (code snippet)

Description

The example below uses a single table to store the settings and contents of the result set. It also uses a counter for the lines in the contents, the advantage of this method over using table.insert is that you do not need to deal with nil values which can mean result contents are shown on the wrong lines in the result as inserting a nil value does not add a line to the table.

When possible using the item type for column values has the advantage that the items can be clicked on and the correct section of the Property Box opened so they can be edited. Note the use of Clone and fhGetItemPtr to handle the item columns.

Requires: None

Version 3 cleaner Metatables

Drop in Function

createResultTable.fh_lua
function createResultTable()
    local tblOutput_mt = {} -- create metatable
    local iC = 0 -- Define count of lines
    local tblOutput = {} -- Define Columns Table
    tblOutput_mt.col = 0
    tblOutput_mt.seq = {}
    tblOutput_mt.__newindex = 
      function (t,k,v)
        -- Set Values to Defaults if not supplied
        if v.content == nil then v.content = {} end
        if v.title == nil then v.title = k end
        if v.type == nil then v.type = 'notset' end
        if v.width == nil then v.width = 140 end
        if v.align == nil then v.align = 'align_left' end
        if v.sort == nil then v.sort = 0 end
        if v.sortAscending  == nil then v.sortAscending  = true end
        if v.sortType  == nil then v.sortType  = 'default' end
        if v.visibility == nil then v. visibility = 'show' end
        v.set = 
              function(self,value)
                 self.content[iC] = value
                  if self.type == 'notset' then
                    if type(value) == 'string' then 
                           self.type = 'text' 
                    elseif type(value) == 'number' then 
                           self.type = 'integer' 
                           self.width = '30'
                    else 
                           self.type = 'item' 
                    end
                 end
              end
        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
    tblOutput.newRow = function(t)
        iC = iC + 1
    end
    tblOutput.rowCount = function(t)
        return iC
    end
    tblOutput.outputResults = function(self)
        for l in self() do
            fhOutputResultSetColumn(l.title, l.type, l.content, iC, l.width,l.align,l.sort,l.sortAscending,l.sortType,l.visibility )
        end
    end
    setmetatable(tblOutput, tblOutput_mt)
    return tblOutput
end

Usage Example

    local tblResults = createResultTable()
    -- Define Columns
    tblResults.indi  = {title='Record'}
    tblResults.id    = {title='id',type='integer',align='align_right',width=20} 
    tblResults.death = {title='Death'}
    tblResults.name  = {title='Name',type='text'}
    tblResults.birth = {title='Birth',width=40}
 
    pi = fhNewItemPtr() -- declare pointer
    pi:MoveToFirstRecord("INDI") -- and set to the first record.
    while pi:IsNotNull() do
        -- Add Row
        tblResults:newRow()
        -- Set Columns
        tblResults.indi:set(pi:Clone())
        tblResults.name:set(fhGetDisplayText(pi))
        tblResults.birth:set(fhGetItemPtr(pi,'~.BIRT.DATE'))
        tblResults.death:set(fhGetItemPtr(pi,'~.DEAT.DATE'))
        tblResults.id:set(fhGetRecordId(pi)) 
        pi:MoveNext()
    end
    fhOutputResultSetTitles("All Individuals", "All Individuals", "Item List Example Date: %#x")
    tblResults:outputResults()

Version 2 using Metatables

Drop in Function

createResultTable.fh_lua
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

Usage Example

Note the loop logic of tblOutput() rather than the standard pairs function.

tblOutput,iC = createResultTable()
-- Define Columns
tblOutput.death = {title='Death',type='item',width=140,align='align_left',content={}}
tblOutput.indi = {title='Record',type='item',width=140,align='align_left',content={}}
tblOutput.name = {title='Name',type='text',width=140,align='align_left',content={}}
tblOutput.birth = {title='Birth',type='item',width=140,align='align_left',content={}}
 
pi = fhNewItemPtr()  -- declare pointer 
pi:MoveToFirstRecord("INDI") -- and set to the first record.
while pi:IsNotNull() do
   --  Add Columns
   iC = iC + 1
   tblOutput.indi.content[iC] = pi:Clone()   
   tblOutput.name.content[iC] = fhGetDisplayText(pi)
   tblOutput.birth.content[iC] = fhGetItemPtr(pi,'~.BIRT.DATE')
   tblOutput.death.content[iC] = fhGetItemPtr(pi,'~.DEAT.DATE')
 
   pi:MoveNext()
end
fhOutputResultSetTitles("All Individuals", "All Individuals", "Item List Example Date: %#x")
for t in tblOutput() do
   fhOutputResultSetColumn(t.title, t.type, t.content, iC, t.width,t.align)
end

Version 1

This example is simple, but has a draw back that the pairs() function does not return the columns in a predictable order. See the second example for a more advanced option.

local tblOutput = {}  -- Define Columns Table
local iC = 0          -- Define count of lines
 
-- Define Columns
tblOutput.indi = {title='Record',ctype='item',width=140,align='align_left',content={}}
tblOutput.name = {title='Name',ctype='text',width=140,align='align_left',content={}}
tblOutput.birth = {title='Birth',ctype='item',width=140,align='align_left',content={}}
 
pi = fhNewItemPtr()  -- declare pointer 
pi:MoveToFirstRecord("INDI") -- and set to the first record.
while pi:IsNotNull() do
   --  Add Columns
   iC = iC + 1
   tblOutput.indi.content[iC] = pi:Clone()   
   tblOutput.name.content[iC] = fhGetDisplayText(pi)
   tblOutput.birth.content[iC] = fhGetItemPtr(pi,'~.BIRT.DATE')
   pi:MoveNext()
end
fhOutputResultSetTitles("All Individuals", "All Individuals", "Item List Example Date: %#x")
for _,t in pairs(tblOutput) do
   fhOutputResultSetColumn(t.title, t.ctype, t.content, iC, t.width,t.align)
end