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
-
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
-
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 drawback 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