--[[ @Title: Check Sort Dates @Type: Standard @Author: Mark Draper @Version: 1.0 @LastUpdated: 2 Sep 2022 @Licence: This plugin is copyright (c) 2022 Mark Draper, and is licensed under the MIT License which is hereby incorporated by reference (see https://pluginstore.family-historian.co.uk/fh-plugin-licence) @Description: Lists and optionally deletes sort dates that are either invalid or unnecessary ]] fhInitialise(7, 0, 0,'save_required') require('iuplua') require 'luacom' iup.SetGlobal('CUSTOMQUITMESSAGE','YES') iup.SetGlobal('UTF8MODE','YES') iup.SetGlobal('UTF8MODE_FILE','YES') function main() local selection -- set default IUP font local Registry = 'HKEY_CURRENT_USER\\Software\\Calico Pie\\Family Historian\\2.0\\' local k = getRegKey(Registry .. 'Preferences\\PDX Font') local scaling = getRegKey(Registry .. 'Preferences\\Font Scaling Percent') or 100 local tblK = ParseString(k) local font = tblK[14] local size = tblK[1] * scaling / 100 iup.SetGlobal('DEFAULTFONT',font .. ' ' .. size//20) -- create menu local Title = iup.label{title='Select option to check project sort dates',padding='10x10'} local btnSortDates = iup.button{title='Check sort dates',size='80x15'} local btnHelp = iup.button{title='Help'} local btnClose = iup.button{title='Close'} local Buttons = iup.vbox{btnSortDates,btnHelp,btnClose; normalizesize='BOTH',gap=10} local vbox = iup.vbox{Title,Buttons;alignment='ACENTER',gap=10;margin='10x10'} local dialog = iup.dialog{vbox; resize='No', minbox='No', maxbox='No', border='NO', title='Check Sort Dates (1.0)'} function btnSortDates:action() selection = 1 return iup.CLOSE end function btnHelp:action() selection = 2 return iup.CLOSE end function btnClose:action() selection = 0 return iup.CLOSE end repeat selection = 0 dialog:show() iup.MainLoop() dialog:hide() if selection == 1 then selection = SortDates() elseif selection == 2 then local Cmd = 'https://pluginstore.family-historian.co.uk/page/help/check-sort-dates' fhShellExecute(Cmd) fhSleep(1000) -- slight pause to suspend immediate redraw end until not selection or selection == 0 end -- ************************************************************************** -- function SortDates() -- deletes all invalid sort dates (those that do not resolve as dates) and superfluous sort dates -- (equal to actual date or start of range) local p = fhNewItemPtr() local pR = fhNewItemPtr() local tblX = {} local CountI, CountS = 0, 0 for _, Type in ipairs({'INDI', 'FAM'}) do pR:MoveToFirstRecord(Type) while pR:IsNotNull() do p:MoveToFirstChildItem(pR) while p:IsNotNull() do local pD = fhGetItemPtr(p, '~.DATE') local pSD = fhGetItemPtr(p, '~._SDATE') if pSD:IsNotNull() then local dtSDate = fhGetValueAsDate(pSD) if dtSDate:IsNull() then -- invalid date table.insert(tblX, pSD:Clone()) CountI = CountI + 1 else local dtDate = fhGetValueAsDate(pD) local dpDate = dtDate:GetDatePt1() local dpSDate = dtSDate:GetDatePt1() if dpDate:Compare(dpSDate) == 0 then table.insert(tblX, pSD:Clone()) CountS = CountS + 1 end end end p:MoveNext() end pR:MoveNext() end end if #tblX == 0 then fhMessageBox('No invalid or superfluous sort dates identified.', 'MB_OK', 'MB_ICONINFORMATION') return true end local msg = CountI .. ' invalid and ' .. CountS .. ' superfluous sort dates were identified.\n' if #tblX == 1 then msg = msg .. 'What do you want to do with it?' else msg = msg .. 'What do you want to do with them?' end local Action = iup.Alarm('Process Sort Dates', msg, 'List', 'Delete', 'Cancel') if Action == 3 then return true elseif Action == 2 then for _, p in ipairs(tblX) do fhDeleteItem(p) end fhUpdateDisplay() return true elseif Action == 1 then local tblXiE = {} local tblXiED = {} local tblXiR = {} local tblXSD = {} for _, p in ipairs(tblX) do local pE = fhNewItemPtr() pE:MoveToParentItem(p) local pED = fhGetItemPtr(pE, '~.DATE') local pR = fhNewItemPtr() pR:MoveToParentItem(pE) table.insert(tblXiE, pE:Clone()) table.insert(tblXiED, pED:Clone()) table.insert(tblXiR, pR:Clone()) table.insert(tblXSD, p:Clone()) end fhOutputResultSetTitles('Sort Dates') fhOutputResultSetColumn('Record', 'item', tblXiR, #tblXiR,200,'align_left', 0, true, 'default') fhOutputResultSetColumn('Fact', 'item', tblXiE, #tblXiE,175,'align_left', 0, true, 'default') fhOutputResultSetColumn('Date', 'item', tblXiED, #tblXiED,160,'align_left', 0, true, 'date') fhOutputResultSetColumn('Sort Date', 'item', tblXSD, #tblXSD,80,'align_left', 0, true, 'date') end end -- ************************************************************************** -- function getRegKey(key) local sh = luacom.CreateObject 'WScript.Shell' local ans if pcall(function () ans = sh:RegRead(key) end) then return ans else return nil,true end end -- ************************************************************************** -- function ParseString(S) -- splits a delimited string into a table without using stringx library local tblT = {} while true do local i = S:find(',') if not i then -- no more delimiters table.insert(tblT, S) break end table.insert(tblT, S:sub(1,i-1)) S = S:sub(i+1) end return tblT end -- ************************************************************************** -- main()