UDF List.fh_lua

--[[
@title: List all Unidentified Data Fields
@author: Calico Pie
@lastupdated: 27 Nov 2020
@version: 1.1
@description:
Produces a Result Set Containing all the Unidentified Data Fields
in the Gedcom.  Along with their data references and the Records containing them.
]]
require "iuplua"
iup.SetGlobal("CUSTOMQUITMESSAGE","YES")

----------------------------------------------------------- Start Progress Display
--[[
@Title: Progress Display (drop in)
@Author: Jane Taubman
@LastUpdated: July 2011
@Description: Allows easy adding of a Progress Bar to any long running Plugin

Sample of Use

ProgressDisplay.Start('This is my progress Box')
for i=1,100 do
	ProgressDisplay.SetMessage('I = '..i)
	for j = 1,100 do end
	ProgressDisplay.Step(.01)  -- loops 10 times
	if ProgressDisplay.Cancel() then
		break
	end
end 
ProgressDisplay.Reset()
ProgressDisplay.Close()
]]

ProgressDisplay = {
	Start = function (strTitle)
		cancelflag = false
		local cancelbutton = iup.button {
			title = "Cancel",
			size = "100x20",
			action=function()
				cancelflag = true
				return iup.CLOSE
			end
		}
		gaugeProgress = iup.progressbar{ expand="HORIZONTAL" }
		messageline   = iup.label{expand="HORIZONTAL",title = " ",alignment = "ACENTER",gap=10} 
		dlgProgress = iup.dialog{
			title = strTitle,
			dialogframe = "YES", border = "YES",
			iup.vbox {
				messageline,
				gaugeProgress,
				cancelbutton;
				alignment = "ACENTER",gap=10
			}
		}
		dlgProgress.size = "QUARTERxEIGHTH"
		dlgProgress.menubox = "NO"  --  Remove Windows close button and menu.
		dlgProgress.close_cb = cancelbutton.action
		dlgProgress:showxy(iup.CENTER, iup.CENTER)  --  Put up Progress Display
	end,
	Step = function (iStep)
		gaugeProgress.value = gaugeProgress.value + iStep
		iup.LoopStep()
	end,
	Close = function ()
		dlgProgress:destroy()
	end,
	Cancel = function ()
		iup.LoopStep()
		return cancelflag
	end,
	SetMessage = function(strMessage)
		messageline.title = strMessage
	end,
	Reset = function()
		gaugeProgress.value = 0
	end
}

----------------------------------------------------------- End Progress Display
--[[
@function: BuildDR
@description: Get Data Reference for Tag
@parameters: Item Pointer
@returns: Data reference String (excluding index)
@requires: none
]] 
function BuildDR(ptr)
   local ptrTemp = fhNewItemPtr()
   ptrTemp:MoveTo(ptr)
   strDR = fhGetTag(ptrTemp)
   while fhHasParentItem(ptrTemp) do
      ptrTemp:MoveToParentItem(ptrTemp)
      strDR = fhGetTag(ptrTemp)..'.'..strDR
   end
   return strDR
end


function recordCount(rcdType)
	local ptr = fhNewItemPtr()
	local count = 0
	ptr:MoveToFirstRecord(rcdType)
	while ptr:IsNotNull() do
		count = count + 1
		ptr:MoveNext()
	end
return count
end
---------------------------------------------------------------------------- Main Code
iCount = fhGetRecordTypeCount() -- Get Count of Record types
ii = 0
tblTextClass = {
text = true,
longtext = true,
name = true,
place = true,
}
ptr = fhNewItemPtr()
ptrItem = fhNewItemPtr()
ptrRecord = fhNewItemPtr()
ptrParent = fhNewItemPtr()
ptrDelete = fhNewItemPtr()
tblItem = {}
tblRecord = {}
tblRecordType = {}
tblItemTag = {}
tblItemDataRef = {}
ProgressDisplay.Start('Searching for UDF Items')
ProgressDisplay.SetMessage('Initialisation in Progress . . . ')
for ii =1,iCount do
    strType = fhGetRecordTypeTag(ii)
	istep = 1 / recordCount(strType) 
	ProgressDisplay.SetMessage('Processing '..strType)
	ProgressDisplay.Reset()
    ptrItem:MoveToFirstRecord(strType)
	iLast = 0
    while ptrItem:IsNotNull() do
		ptrDelete:SetNull()
            ptrRecord:MoveToRecordItem(ptrItem)
			 if fhGetRecordId(ptrRecord) ~= iLast then
				iLast = fhGetRecordId(ptrRecord)
				ProgressDisplay.Step(istep)
				if ProgressDisplay.Cancel() then
					error('User Cancelled')
				end
			 end
        if fhIsUDF(ptrItem) then
            table.insert(tblItem,ptrItem:Clone())
            table.insert(tblRecord,ptrRecord:Clone())
            table.insert(tblRecordType,strType)
            table.insert(tblItemTag,fhGetTag(ptrItem))
			table.insert(tblItemDataRef,BuildDR(ptrItem))
        end
        ptrItem:MoveNextSpecial()
    end
end
if (#tblItem > 0) then
	ProgressDisplay.Reset('Loading Result Set')
	fhOutputResultSetTitles("Unidentified Data References", "Unidentified Data References", "Date: %#x")
	fhOutputResultSetColumn("UDF Item", "item", tblItem, #tblItem, 180, "align_left")	
	fhOutputResultSetColumn("Record", "item", tblRecord, #tblRecord, 180, "align_left")
	fhOutputResultSetColumn("Record Type", "text", tblRecordType, #tblRecordType, 40, "align_left")
	fhOutputResultSetColumn("Item Tag", "text", tblItemTag, #tblItemTag, 40, "align_left")
	fhOutputResultSetColumn("Item Data Reference", "text", tblItemDataRef, #tblItemDataRef, 140, "align_left")
	ProgressDisplay.Close()
else
	ProgressDisplay.Close()
	fhMessageBox('No UDF items found')
end

Source:UDF-List-1.fh_lua