CWCG Build from CSV.fh_lua--[[
@Title: Commonwealth War Graves Commission CSV Import
@Author: Richard Sellens
@Version: 0.4
@LastUpdated: 23/12/2012
@Description: Import saved search result CSV file, created by CWGC website
]]
--- Include IUP Extensions
require( "iuplua" )
--
----------------------------------------------------------------------------
-- Functions
----------------------------------------------------------------------------
--
--- GetExistingFile
-- @name GetExistingFile
-- @uses IUP
-- @param strTitle Prompt Title
-- @param strFilter Filter template e.g *.CSV;*.TXT
-- @param strFilterInfo Display Text for the Selection
function GetExistingFile(strTitle,strFilter,strFilterInfo,strDir)
-- Creates a file dialog and sets its type, title, filter and filter info
filedlg = iup.filedlg{dialogtype = "OPEN", title = strTitle,
filter = strFilter, filterinfo = strFilterInfo,
directory=strDir}
-- Shows file dialog in the center of the screen
filedlg:popup (iup.ANYWHERE, iup.ANYWHERE)
-- Gets file dialog status
status = filedlg.status
return status,filedlg.value
end
--- fromCSV
-- @name fromCSV
-- @description Converts a string to a table of fields, spliting according to normal CSV rules
-- @param string comma separated string
-- @return table of fields
function fromCSV (s)
s = s .. ',' -- ending comma
local t = {} -- table to collect fields
local fieldstart = 1
iID = iID + 1
table.insert(t, iID)
repeat
-- next field is quoted? (start with `"'?)
if string.find(s, '^"', fieldstart) then
local a, c
local i = fieldstart
repeat
-- find closing quote
a, i, c = string.find(s, '"("?)', i+1)
until c ~= '"' -- quote not followed by quote?
if not i then
error('unmatched "')
end
local f = string.sub(s, fieldstart+1, i-1)
table.insert(t, (string.gsub(f, '""', '"')))
fieldstart = string.find(s, ',', i) + 1
else -- unquoted; find next comma
local nexti = string.find(s, ',', fieldstart)
table.insert(t, string.sub(s, fieldstart, nexti-1))
fieldstart = nexti + 1
end
until fieldstart > string.len(s)
return t
end
--- LoadFile
-- @name loadfile
-- @description Loads a CSV file into a table of tables
-- @usage provide valid filename, use ipairs loop to use resulting table
-- @param filename filename to load
-- @return table of tables
function loadfile(filename)
contents = {}
bheader = false
for line in io.lines(filename) do
fields = fromCSV(line)
data = {}
--
if bheader then
-- Build Data Table with the Header Descriptions
for i,field in ipairs(fields) do
if field ~= '' then
data[header[i]] = field
end
end
contents[fields[1]] =data
else
-- Grab Column Names
header = fields
bheader = true
end
end
return contents
end
--- CreateSource
-- @name CreateSource
-- @description Creates a new Source Record SOUR
-- @param name string
-- @return item pointer for new record
function CreateSource(sName)
local ptrSOUR = fhCreateItem("SOUR") -- create an Source record and ret ptr to it
local ptrTITL = fhCreateItem("TITL", ptrSOUR) -- create a TITLE field within this record, and ret ptr to it
fhSetValueAsText(ptrTITL, sName) -- set value of the name using passed in parameter
local ptrREPO = fhCreateItem("REPO", ptrSOUR)
fhSetValueAsLink(ptrREPO, CreateRepo())
return ptrSOUR -- return pointer to the newly-created Individual record
end
--- CreateRepo
-- @name CreateRepo
-- @description Creates a new Record REPO
-- @param name string
-- @return item pointer for new record
function CreateRepo()
local ptrREPO = fhCreateItem("REPO")
local ptrTITL = fhCreateItem("NAME", ptrREPO)
fhSetValueAsText(ptrTITL, 'Commonwealth War Graves Commission')
local ptrADDR = fhCreateItem("ADDR", ptrREPO)
fhSetValueAsText(ptrADDR, '2 Marlow Road\nMaidenhead\nBerkshire\nSL6 7DX\nEngland')
local ptrPHON = fhCreateItem("PHON", ptrREPO)
fhSetValueAsText(ptrPHON, '+44 (0) 1628 634221')
local ptrWEB = fhCreateItem("_WEB", ptrREPO)
fhSetValueAsText(ptrWEB, 'http://www.cwgc.org/')
return ptrREPO -- return pointer to the newly-created record
end
--- CreateInd
-- @name CreateInd
-- @description Creates a new individual Record INDI
-- @param name string in format forenames /surname/ NAME
-- @param sex string either M or F or Male or Female SEX
-- @param customid string for records custom ID REFN
-- @return item pointer for new record
function CreateInd(sName, sSex, sCustomID, ptrSource)
local ptrInd = fhCreateItem("INDI") -- create an Individual record and ret ptr to it
local ptrSOUR = fhCreateItem('SOUR', ptrInd) -- create a source subfield
fhSetValueAsLink(ptrSOUR, ptrSource)
local ptrName = fhCreateItem("NAME", ptrInd) -- create a NAME field within this record, and ret ptr to it
fhSetValueAsText(ptrName, sName) -- set value of the name using passed in parameter
if sSex ~= nil and sSex ~= ' ' then
local ptrSex = fhCreateItem("SEX", ptrInd) -- create a SEX field within this record, and ret ptr to it
fhSetValueAsText(ptrSex, sSex) -- set value of sex using passed in parameter
end
return ptrInd -- return pointer to the newly-created Individual record
end
--- AddEvent
-- @name AddEvent
-- @description Adds an event to a record
-- @usage event must be a valid data reference for the pointer provided
-- @param ptrRecord point for individual record INDI
-- @param event event type eg BIRT, DEAT etc
-- @param eventdate string containing date in FH reconised format DATE
-- @param eventplace place for event PLAC
-- @return none
function AddEvent(ptrRecord,event,eventdate,eventplace,ptrSource)
ptrEvent = fhCreateItem(event,ptrRecord) -- create a event field
ptrSOUR = fhCreateItem('SOUR', ptrEvent) -- create a source subfield for it
fhSetValueAsLink(ptrSOUR, ptrSource)
if eventdate ~= nil then
-- create a date subfield for it & set value of the date using passed in parameter
ptrDate = fhCreateItem('DATE', ptrEvent)
fhSetValueAsDate(ptrDate, eventdate)
end
if eventplace ~= nil then
-- create a place subfield for it & set value of the place using passed in parameter
ptrPlace = fhCreateItem('PLAC', ptrEvent)
fhSetValueAsText(ptrPlace, eventplace)
end
return(ptrEvent)
end
-- Set first letter to capital and the rest to lower case.
function tchelper(first, rest)
return first:upper()..rest:lower()
end
-- Set change the "middle" letter to upper case (eg McMull).
function upperspecial (start,middle,rest)
return start..middle:upper()..rest:lower()
end
-- Set change the first letter(s) to lower case (eg de'Watt).
function lowerspecial (start,middle,rest)
return start:lower()..middle:upper()..rest:lower()
end
function lowerspecial2 (start,middle,rest)
return start..middle..rest:lower()
end
function alllower (start)
return start:lower()
end
-- captialise string
function captialise(str)
str = str:gsub("(%a)([%w_]*)", tchelper)
-- Add Special Cases Here
str = str:gsub("(Mac)(%a)([%w_]*)", upperspecial)
str = str:gsub("(Mc)(%a)([%w_]*)", upperspecial)
str = str:gsub("(De')(%a)([%w_]*)", lowerspecial)
str = str:gsub("(O')(%a)([%w_]*)", upperspecial)
str = str:gsub("( Of )", alllower)
str = str:gsub("(%a)([%w_]*)('S)", lowerspecial2)
str = str:gsub("(%d+)([%w_]*)", tchelper)
return(str)
end
function MilService(str)
if string.find(str, 'Royal Navy')~= nil then
tService = 'Royal Navy'
elseif string.find(str, 'Royal Naval Volunteer Reserve')~= nil then
tService = 'Royal Naval Volunteer Reserve'
elseif string.find(str, 'Royal Naval Reserve')~= nil then
tService = 'Royal Naval Reserve'
elseif string.find(str, 'Royal Air Force')~= nil then
tService = 'Royal Air Force'
elseif string.find(str, 'Canadian')~= nil then
tService = 'Canadian Over-Seas Expeditionary Force'
elseif string.find(str, 'Australian')~= nil then
tService = 'Australian Infantry'
elseif string.find(str, 'Mercantile Marine')~= nil then
tService = 'Merchant Navy'
else
tService = 'British Army'
end
return(tService)
end
function MilAward(str)
local tandBar = ''
if string.find(str, 'and Bar')~= nil then
tandBar = string.sub(str, string.find(str, 'and Bar') - 1)
str = string.sub(str, 1, string.find(str, 'and Bar') - 2)
end
if str == 'M M' then
tMilAward = 'Military Medal'
elseif str == 'M B E' then
tMilAward = 'MBE'
elseif str == 'M C' then
tMilAward = 'Military Cross'
elseif str == 'D C M' then
tMilAward = 'Distinguished Conduct Medal'
elseif str == 'V C' then
tMilAward = 'Victoria Cross'
elseif str == 'T D' then
tMilAward = 'Territorial Decoration'
elseif str == 'M S M' then
tMilAward = 'Meritorious Service Medal'
elseif str == 'D S O' then
tMilAward = 'Distinguished Service Order'
else
tMilAward = captialise(str)
end
return(tMilAward ..tandBar)
end
function Gender(str)
if str == nil then
tGender = ' '
elseif string.find(str, 'MR. ')~= nil then
tGender = 'M'
elseif string.find(str, 'MR ')~= nil then
tGender = 'M'
elseif string.find(str, 'MRS. ')~= nil then
tGender = 'F'
elseif string.find(str, 'MISS ')~= nil then
tGender = 'F'
else
tGender = ' '
end
return(tGender)
end
function ExtractAddlInfo (s)
AddlNote = ''
tab_Individual = {}
tab_Family = {}
local tab_Siblings = {}
local tab_Children = {}
-- Initialise Number of relatives fields
tab_Family.NumSiblings = 0
tab_Family.NumChildren = 0
if s ~= nil then
s = s .. ';' -- ending
local t2 = {} -- table to collect fields
local fieldstart = 1
repeat
-- next field is quoted? (start with `"'?)
if string.find(s, '^"', fieldstart) then
local a, c
local i = fieldstart
repeat
-- find closing quote
a, i, c = string.find(s, '"("?)', i+1)
until c ~= '"' -- quote not followed by quote?
if not i then
error('unmatched "')
end
local f = string.sub(s, fieldstart+1, i-1)
tInsertTxt = string.gsub(f, '""', '"')
fieldstart = string.find(s, ';', i) + 1
else -- unquoted; find next semi-colon
local nexti = string.find(s, ';', fieldstart)
tInsertTxt = string.sub(s, fieldstart, nexti-1)
fieldstart = nexti + 1
end
-- Extract Details
if string.find(tInsertTxt, 'ADOPTED')~= nil then
tab_Family.Adopted = true
end
if string.find(tInsertTxt, 'FOSTER')~= nil then
tab_Family.Foster = true
end
if string.find(tInsertTxt, 'BORN AT')~= nil then
tab_Individual.BirthPlace = captialise(string.sub(tInsertTxt, string.find(tInsertTxt, 'BORN AT')+8))
elseif string.find(tInsertTxt, 'DIED AT')~= nil then
tab_Individual.DeathPlace = captialise(string.sub(tInsertTxt, string.find(tInsertTxt, 'DIED AT')+8))
elseif string.find(tInsertTxt, 'ENLISTED')~= nil then
tab_Individual.Enlistment = string.sub(tInsertTxt, string.find(tInsertTxt, 'ENLISTED')+9)
elseif string.find(tInsertTxt, 'EDUCATED AT') ~= nil then
tab_Individual.Educated = captialise(string.sub(tInsertTxt, string.find(tInsertTxt, 'EDUCATED AT')+12))
elseif string.find(tInsertTxt, 'SERVED IN') ~= nil then
tab_Individual.MilService = captialise(string.sub(tInsertTxt, string.find(tInsertTxt, 'SERVED IN')+10))
elseif string.find(tInsertTxt, 'NATIVE OF')~= nil then
tab_Individual.Native = captialise(string.sub(tInsertTxt, string.find(tInsertTxt, 'NATIVE OF')+10))
elseif string.find(tInsertTxt, 'HUSBAND OF')~= nil then
tab_Individual.Gender = 'M'
tab_Family.Spouse = true
tab_Family.SpouseGender = 'F'
local tBSpouse = string.sub(tInsertTxt, string.find(tInsertTxt, 'HUSBAND OF')+11)
if string.find(tBSpouse, ', OF')~= nil then
tab_Family.SpousePlc = captialise(string.sub(tBSpouse, string.find(tBSpouse, ', OF')+5))
tBSpouse = string.sub(tBSpouse, 1, string.find(tBSpouse, ', OF')-1)
end
tBSpouse = tBSpouse:gsub(tMainSurname, '')
tab_Family.SpouseFullName = FormatName(tBSpouse)
elseif string.find(tInsertTxt, 'BROTHER OF')~= nil then
tab_Individual.Gender = 'M'
tab_Family.Child = true
tab_Family.NumSiblings = tab_Family.NumSiblings + 1
local tab_SiblingDetails = {}
local tSibling = string.sub(tInsertTxt, string.find(tInsertTxt, 'BROTHER OF')+10)
if string.find(tSibling, ', OF')~= nil then
tab_SiblingDetails.ResidencePlc = captialise(string.sub(tSibling, string.find(tSibling, ', OF')+5))
tSibling = string.sub(tSibling, 1, string.find(tSibling, ', OF')-1)
end
tab_SiblingDetails.Gender = Gender(tSibling)
tab_SiblingDetails.FullName = FormatName(tSibling)
table.insert(tab_Siblings, tab_SiblingDetails)
elseif string.find(tInsertTxt, 'HIS BROTHER ') ~= nil or string.find(tInsertTxt, 'HIS BROTHER, ') ~= nil or
string.find(tInsertTxt, 'HIS BROTHERS ') ~= nil then
tab_Family.Child = true
local strtpos = 1
if string.find(tInsertTxt, 'HIS BROTHER ') ~= nil then
strtpos = string.find(tInsertTxt, 'HIS BROTHER ') + 12
elseif string.find(tInsertTxt, 'HIS BROTHER, ') ~= nil then
strtpos = string.find(tInsertTxt, 'HIS BROTHER, ') + 13
elseif string.find(tInsertTxt, 'HIS BROTHERS ') ~= nil then
strtpos = string.find(tInsertTxt, 'HIS BROTHERS ') + 13
end
local endpos = 1
if string.find(tInsertTxt, 'ALSO FELL') ~= nil then
endpos = string.find(tInsertTxt, 'ALSO FELL') - 1
elseif string.find(tInsertTxt, 'ALSO DIED') ~= nil then
endpos = string.find(tInsertTxt, 'ALSO DIED') - 1
end
local NameList = string.sub(tInsertTxt, strtpos, endpos) ..' AND '
local fieldstart = 1
repeat
local nexti = string.find(NameList, ' AND ', fieldstart)
tab_Family.NumSiblings = tab_Family.NumSiblings + 1
local tab_SiblingDetails = {}
tab_SiblingDetails.Gender = 'M'
tab_SiblingDetails.FullName = FormatName(string.sub(NameList, fieldstart, nexti-1))
table.insert(tab_Siblings, tab_SiblingDetails)
fieldstart = nexti + 5
until fieldstart > string.len(NameList)
elseif string.find(tInsertTxt, 'HIS BROTHER-IN-LAW', 1, true) ~= nil then
tab_Family.Child = true
tab_Family.NumSiblings = tab_Family.NumSiblings + 1
local tab_SiblingDetails = {}
tab_SiblingDetails.Gender = 'F'
tab_SiblingDetails.FullName = '/' ..captialise(tMainSurname) ..'/'
tab_SiblingDetails.SpouseGender = 'M'
local strtpos = string.find(tInsertTxt, 'HIS BROTHER-IN-LAW', 1, true) + 19
local endpos = -1
if string.find(tInsertTxt, 'ALSO FELL') ~= nil then
endpos = string.find(tInsertTxt, 'ALSO FELL') - 1
elseif string.find(tInsertTxt, 'ALSO DIED') ~= nil then
endpos = string.find(tInsertTxt, 'ALSO DIED') - 1
end
local NameList = string.sub(tInsertTxt, strtpos, endpos)
tab_SiblingDetails.SpouseName = FormatName(NameList)
table.insert(tab_Siblings, tab_SiblingDetails)
elseif string.find(tInsertTxt, 'FATHER OF')~= nil then
tab_Individual.Gender = 'M'
tab_Family.NumChildren = tab_Family.NumChildren + 1
local tab_ChildDetails = {}
local tChild = string.sub(tInsertTxt, string.find(tInsertTxt, 'FATHER OF')+10)
if string.find(tChild, ', OF')~= nil then
tab_ChildDetails.ResidencePlc = captialise(string.sub(tChild, string.find(tChild, ', OF')+5))
tChild = string.sub(tChild, 1, string.find(tChild, ', OF')-1)
end
tab_ChildDetails.FullName = FormatName(tChild)
table.insert(tab_Children, tab_ChildDetails)
elseif string.find(tInsertTxt, 'NEPHEW OF')~= nil then
tab_Individual.Gender = 'M'
table.insert(t2, tInsertTxt)
elseif string.find(tInsertTxt, 'GRANDSON OF')~= nil then
local tGrandParent1 = nil
local tGrandParent2 = nil
local tGrandParents = nil
tab_Individual.Gender = 'M'
tab_Family.GrandChild = true
tGrandParents = string.sub(tInsertTxt, string.find(tInsertTxt, 'GRANDSON OF')+12)
if string.find(tGrandParents, tMainSurname) ~= nil then
tab_Family.GrandChildFather = true
else
tab_Family.GrandChildMother = true
end
if string.find(tGrandParents, ', OF') ~= nil then
tab_Family.GrandParentsPlc = captialise(string.sub(tGrandParents, string.find(tGrandParents, ', OF')+5))
tGrandParents = string.sub(tGrandParents, 1, string.find(tGrandParents, ', OF')-1)
end
if string.find(tGrandParents, 'MR. AND MRS.') ~= nil then
tGrandParent1 = string.sub(tGrandParents, string.find(tGrandParents, 'MR. AND MRS.')+13)
tab_Family.GrandParent1Gender = 'M'
tab_Family.GrandParent2Gender = 'F'
else
if string.find(tGrandParents, ' AND ') ~= nil then
tGrandParent1 = string.sub(tGrandParents, 1, string.find(tGrandParents, ' AND ')-1)
if string.find(tGrandParent1, tMainSurname) == nil then
tGrandParent1 = tGrandParent1 ..' ' ..tMainSurname
end
tGrandParent2 = string.sub(tGrandParents, string.find(tGrandParents, ' AND ')+5)
tab_Family.GrandParent1Gender = Gender(tGrandParent1)
tab_Family.GrandParent2Gender = Gender(tGrandParent2)
else
tGrandParent1 = tGrandParents
tab_Family.GrandParent1Gender = Gender(tGrandParent1)
end
end
if tab_Family.GrandParent1Gender == 'F' then
tGrandParent1 = tGrandParent1:gsub(tMainSurname, '')
end
tab_Family.GrandParent1 = FormatName(tGrandParent1)
if tGrandParent2 ~= nil then
if tab_Family.GrandParent2Gender ~= 'M' then
tGrandParent2 = tGrandParent2:gsub(tMainSurname, '')
end
tab_Family.GrandParent2 = FormatName(tGrandParent2)
end
elseif string.find(tInsertTxt, 'SON OF') ~= nil or string.find(tInsertTxt, 'CHILD OF') ~= nil then
local tParent1 = nil
local tParent2 = nil
local tParents = nil
tab_Individual.Gender = 'M'
tab_Family.Child = true
if string.find(tInsertTxt, 'SON OF') ~= nil then
tParents = string.sub(tInsertTxt, string.find(tInsertTxt, 'SON OF')+7)
elseif string.find(tInsertTxt, 'CHILD OF') ~= nil then
tParents = string.sub(tInsertTxt, string.find(tInsertTxt, 'CHILD OF')+9)
end
if string.find(tParents, ', OF') ~= nil then
tab_Family.ParentsPlc = captialise(string.sub(tParents, string.find(tParents, ', OF')+5))
tParents = string.sub(tParents, 1, string.find(tParents, ', OF')-1)
end
if string.find(tParents, 'MR. AND MRS.') ~= nil then
tParent1 = string.sub(tParents, string.find(tParents, 'MR. AND MRS.')+13)
tab_Family.Parent1Gender = 'M'
tab_Family.Parent2Gender = 'F'
else
if string.find(tParents, ' AND ') ~= nil then
tParent1 = string.sub(tParents, 1, string.find(tParents, ' AND ')-1)
if string.find(tParent1, tMainSurname) == nil then
tParent1 = tParent1 ..' ' ..tMainSurname
end
tParent2 = string.sub(tParents, string.find(tParents, ' AND ')+5)
tab_Family.Parent1Gender = Gender(tParent1)
tab_Family.Parent2Gender = Gender(tParent2)
else
tParent1 = tParents
tab_Family.Parent1Gender = Gender(tParent1)
end
end
if tab_Family.Parent1Gender == 'F' then
tParent1 = tParent1:gsub(tMainSurname, '')
end
tab_Family.Parent1 = FormatName(tParent1)
if tParent2 ~= nil then
if tab_Family.Parent2Gender ~= 'M' then
tParent2 = tParent2:gsub(tMainSurname, '')
end
tab_Family.Parent2 = FormatName(tParent2)
end
else
table.insert(t2, tInsertTxt)
end
until fieldstart > string.len(s)
for i,str in ipairs(t2) do
AddlNote = AddlNote ..str ..'\n'
end
end
if tab_Family.NumSiblings > 0 then
tab_Family.Siblings = tab_Siblings
end
if tab_Family.NumChildren > 0 then
tab_Family.Children = tab_Children
end
return(AddlNote)
end
--- AddFamilyMember
-- @name AddFamilyMember
-- @description Adds a person to a family
-- @param type Type is either SPOU or CHIL for Spouse or Child.
-- @param family record pointer
-- @param individual record pointer)
-- @return none
function AddFamilyMember(type,ptrfam,ptrind)
ptrLink = fhCreateItem(type, ptrfam )
fhSetValueAsLink(ptrLink, ptrind)
end
--- CleanPlace
-- @name CleanPlace
-- @description Performs various clean up tasks on a place value
-- @param input place field
-- @return updated place field
function CleanPlace(strPlace)
local strRetPlace = nil
if strPlace ~= nil then
strRetPlace = strPlace
-- swap comma inside quoted field to outside
strRetPlace= strRetPlace:gsub("''", '"')
strRetPlace= strRetPlace:gsub(',"', '",')
-- remove comma between 'house number' and street
if string.find(strRetPlace, ', ')~= nil then
local str = string.sub(strRetPlace, 1, string.find(strRetPlace, ', ')-1)
local str2 = string.sub(strRetPlace, string.find(strRetPlace, ', ')+1)
if tonumber(str) ~= nil then --it's a number
strRetPlace = str:gsub(' ', '') ..str2
else
if string.find(str2, ', ') ~= nil then
local str3 = string.sub(str2, string.find(str2, ', ')+1)
str2 = string.sub(str2, 1, string.find(str2, ', ')-1)
if tonumber(str2) ~= nil then --it's a number
strRetPlace = str ..', ' ..str2:gsub(' ', '') ..str3
end
end
end
end
-- remove trailing 'full stop'
if string.sub(strRetPlace, -1) == '.' then
strRetPlace = string.sub(strRetPlace, 1, string.len(strRetPlace)-1)
end
-- correct "'S" in place
strRetPlace= strRetPlace:gsub("'S ", "'s ")
end
return(strRetPlace)
end
--- FormatName
-- @name FormatName
-- @description Performs various clean up tasks on a name value
-- @param input name field
-- @return updated name field
function FormatName(inName)
local strRetName = nil
local forename = ''
local surname = tMainSurname
local suffix = ''
-- remarried ?
if string.find(inName, '%(FORMERLY') ~= nil then
inName = string.sub(inName, 1, string.find(inName, '%(FORMERLY') -2)
local fieldstart = 1
repeat
if string.find(inName, ' ', fieldstart, true) ~= nil then
local findpos = string.find(inName, ' ', fieldstart, true)
forename = string.sub(inName, 1, findpos - 1)
surname = ''
fieldstart = findpos + 1
else
fieldstart = string.len(inName) + 1
end
until fieldstart > string.len(inName)
-- Maiden name ?
elseif string.find(inName, '%(NEE') ~= nil then
forename = string.sub(inName, 1, string.find(inName, '%(NEE') -2)
if string.find(forename, tMainSurname)~= nil then
forename = string.sub(forename, 1, string.find(forename, tMainSurname)-2)
end
surname = string.sub(inName, string.find(inName, '%(NEE') +5)
surname = surname:gsub('%)', '')
else
-- Extract forname, surname & suffix fields
if string.find(inName, tMainSurname)~= nil then
forename = string.sub(inName, 1, string.find(inName, tMainSurname)-2)
local strtPos = string.find(inName, tMainSurname) + string.len(tMainSurname) + 1
suffix = string.sub(inName, strtPos, string.len(inName)-2)
else
forename = inName
surname = ''
end
end
-- Drop 'titles'
forename= forename:gsub('MR. ', '')
forename= forename:gsub('MR ', '')
forename= forename:gsub('MRS. ', '')
forename= forename:gsub('MISS ', '')
forename= forename:gsub('THE LATE ', '')
strRetName = captialise(forename) ..' /' ..captialise(surname) ..'/' ..captialise(suffix)
return(strRetName)
end
--- ExtractEnlistmentDetails
-- @name ExtractEnlistmentDetails
-- @description takes the enlistment string & extracts details
-- @param input Enlistment text string field
-- @return none
function ExtractEnlistmentDetails(strEnlist)
local EnlistmentNote = ''
-- Correct 'Regiment' text
strEnlist = strEnlist:gsub("REGT.,", "Regt. ,")
-- Remove any unwanted text in field
strEnlist = strEnlist:gsub("%.,", "")
strEnlist = strEnlist:gsub("IN ", "")
-- Extract 'data' blocks from Enlistment String
local t4 = SplitString_Comma(strEnlist .. ',')
-- Process Blocks
for i,str in ipairs(t4) do
-- Look for Enlistment Date
local enlistdatefield = fhNewDate()
if enlistdatefield:SetValueAsText(str,false) then
tab_Individual.EnlistmentDate = enlistdatefield
else
EnlistmentNote = EnlistmentNote ..str ..'\n'
end
end
if EnlistmentNote ~= '' then
tab_Individual.EnlistmentNote = captialise(EnlistmentNote)
end
end
--- SplitString_Comma
-- @name SplitString_Comma
-- @description splits string into blocks based on comma
-- @param input text string field
-- @return table of blocks
function SplitString_Comma(inStr)
-- Extract 'data' blocks from String
local RetTable = {} -- table to collect fields
local fieldstart = 1
inStr = inStr:gsub(", ", ",")
repeat
-- next field is quoted? (start with `"'?)
if string.find(inStr, '^"', fieldstart) then
local a, c
local i = fieldstart
repeat
-- find closing quote
a, i, c = string.find(inStr, '"("?)', i+1)
until c ~= '"' -- quote not followed by quote?
if not i then
error('unmatched "')
end
local f = string.sub(inStr, fieldstart+1, i-1)
tInsertTxt = string.gsub(f, '""', '"')
fieldstart = string.find(inStr, ',', i) + 1
else -- unquoted; find next semi-colon
local nexti = string.find(inStr, ',', fieldstart)
tInsertTxt = string.sub(inStr, fieldstart, nexti-1)
fieldstart = nexti + 1
end
table.insert(RetTable, tInsertTxt)
until fieldstart > string.len(inStr)
return(RetTable)
end
--
----------------------------------------------------------------------------
-- Main Code
----------------------------------------------------------------------------
--
-- Check for Empty gedcom
--
ptrind = fhNewItemPtr()
ptrind:MoveToFirstRecord("INDI") -- set the first to point to the first Source record
if ptrind:IsNotNull() then
sMessage = [[
Warning: Data exists in the GEDCOM file.
This script takes no account of existing data
and is better used on a New empty file.
Do you wish to continue?
]]
a = fhMessageBox(sMessage, "MB_YESNO","MB_ICONEXCLAMATION")
if a == "No" then
error('Script Aborted')
end
end
--
-- Prompt for file to Process
--
status,strfilename = GetExistingFile("Select Missing File","*.csv","Comma Separated File","Documents")
if status == '-1' then
error('Prompt Cancelled')
end
iID = 0
-- Call loadfile function to return a table with the data in.
contents = loadfile(strfilename)
family = {}
individual = {}
-- Create Source record
ptrSource = CreateSource('CWGC Search')
-- Create People
for key,data in pairs(contents) do
-- Create Name
if data['forename'] ~= nil then
fornames = data['forename']
else
fornames = data['initials']
end
name = captialise(fornames)..' /'..captialise(data['surname'])..'/'
tMainSurname = data['surname']
-- Create Individual Record
AddlInfo = ExtractAddlInfo(data['additionalinformation'])
ptrind = CreateInd(name, tab_Individual.Gender, 0, ptrSource)
individual[0] = ptrind:Clone()
tempdatefield = fhNewDate()
tempdatefield:SetValueAsText(data['date_of_death'],true)
dpDatePt = tempdatefield:GetDatePt1()
-- Add Birth Event
if data['age_text'] ~= nil then
iAge = data['age_text']
iYear = dpDatePt:GetYear()
iBirth = iYear - iAge
tempdatefield = fhNewDate()
tempdatefield:SetValueAsText(iBirth,true)
eventdatefield = fhNewDate()
eventdatefield:SetSimpleDate(tempdatefield:GetDatePt1(), 'cal')
ptrBIRT = AddEvent(ptrind, 'BIRT', eventdatefield, CleanPlace(tab_Individual.BirthPlace), ptrSource)
else
if tab_Individual.BirthPlace ~= nil then
ptrBIRT = AddEvent(ptrind, 'BIRT', nil, CleanPlace(tab_Individual.BirthPlace), ptrSource)
end
end
-- Add Death Event
eventdatefield = fhNewDate()
eventdatefield:SetValueAsText(data['date_of_death'],true)
ptrDEAT = AddEvent(ptrind, 'DEAT', eventdatefield, CleanPlace(tab_Individual.DeathPlace), ptrSource)
if data['age_text'] ~= nil then
ptrAge = fhCreateItem('AGE', ptrDEAT)
tAge = data['age_text']..'y'
fhSetValueAsText(ptrAge, tAge)
end
-- Add Burial/Memorial Event
if string.find(data['cemeterymemorial'], 'MEMORIAL') ~= nil then
strTag = fhGetFactTag("Memorial", "Event", "INDI", false)
tRefTxt = 'Memorial Reference : '
else
strTag = 'BURI'
tRefTxt = 'Burial Reference : '
end
if data['country'] == 'Civilian War Dead' then
tPLAC = ', , United Kingdom'
else
tPLAC = ', , '..captialise(data['country'])
end
ptrBURMEM = AddEvent(ptrind, strTag, nil, tPLAC, ptrSource)
ptrPlace = fhCreateItem('ADDR', ptrBURMEM)
tADDR = captialise(data['cemeterymemorial'])..tPLAC
fhSetValueAsText(ptrPlace, tADDR)
if data['gravereference'] ~= nil then
ptrNOTE = fhCreateItem('NOTE2', ptrBURMEM)
fhSetValueAsText(ptrNOTE, tRefTxt..data['gravereference'])
end
if data['rank'] ~= 'Civilian' then
-- Add Military Enlistment
if tab_Individual.Enlistment ~= nil then
local dummy = ExtractEnlistmentDetails(tab_Individual.Enlistment)
end
strTag = fhGetFactTag("Military Enlistment", "Attribute", "INDI", false)
if tab_Individual.EnlistmentDate ~= nil then
dToDate = tab_Individual.EnlistmentDate
else
dToDate = fhNewDate()
dToDate:SetRange('before',dpDatePt)
end
ptrEnlist = AddEvent(ptrind, strTag, dToDate, nil, ptrSource)
fhSetValueAsText(ptrEnlist, MilService(data['regiment']))
ptrNOTE = fhCreateItem('NOTE2', ptrEnlist)
if data['servicenumberExport'] ~= nil then
tSrvNum = 'Military Service No. : '..string.gsub(data['servicenumberExport'], '\'', '')
else
tSrvNum = 'Military Service No. : '
end
fhSetValueAsText(ptrNOTE, tSrvNum)
if tab_Individual.EnlistmentNote ~= nil then
local ptrNOTE2 = fhCreateItem('NOTE2', ptrEnlist)
fhSetValueAsText(ptrNOTE2, tab_Individual.EnlistmentNote)
end
-- Add Military Service
strTag = fhGetFactTag("Military Service", "Attribute", "INDI", false)
dToDate = fhNewDate()
dToDate:SetPeriod('to',dpDatePt)
ptrMilS = AddEvent(ptrind, strTag, dToDate, nil, ptrSource)
if data['unitshipsquadron'] ~= nil then
tUnit = data['unitshipsquadron']..' '..data['regiment']
else
tUnit = data['regiment']
end
tMilSvc = data['rank']..', '..tUnit
fhSetValueAsText(ptrMilS, tMilSvc)
-- Add Military Award
if data['honours_awards'] ~= nil then
local t3 = SplitString_Comma(data['honours_awards'] .. ',')
local strTag = fhGetFactTag("Military Award", "Attribute", "INDI", false)
for i,str in ipairs(t3) do
ptrMilA = AddEvent(ptrind, strTag, nil, nil, ptrSource)
fhSetValueAsText(ptrMilA, MilAward(str))
end
end
-- Add Military Conflict
if tab_Individual.MilService ~= nil then
local strTag = fhGetFactTag("Military Conflict", "Attribute", "INDI", false)
local ptrMilS = AddEvent(ptrind, strTag, nil, nil, ptrSource)
fhSetValueAsText(ptrMilS, tab_Individual.MilService)
end
end
-- Add Education Detail
if tab_Individual.Educated ~= nil then
ptrEduc = AddEvent(ptrind, 'EDUC', nil, nil, ptrSource)
fhSetValueAsText(ptrEduc, tab_Individual.Educated)
end
-- Add 'Native of' details
if tab_Individual.Native ~= nil then
ptrResi = AddEvent(ptrind, 'RESI', nil, CleanPlace(tab_Individual.Native), ptrSource)
end
-- Add Note
if AddlInfo ~= nil and AddlInfo ~= '' then
ptrNOTE = fhCreateItem('NOTE2', ptrind)
fhSetValueAsText(ptrNOTE, AddlInfo)
end
-- Add Spouse & Family
if tab_Family.Spouse ~= nil or tab_Family.NumChildren > 0 then
local dAfterDate = fhNewDate()
dAfterDate:SetRange('after',dpDatePt)
-- Create New Family
ptrSpouseFam = fhCreateItem("FAM")
-- Add main individual to family
if tab_Individual.Gender == 'F' then
tRel = 'WIFE'
tSpouseRel = 'HUSB'
else
tRel = 'HUSB'
tSpouseRel = 'WIFE'
end
AddFamilyMember(tRel, ptrSpouseFam, ptrind)
-- Add Spouse
if tab_Family.Spouse ~= nil then
-- Build Spouse
ptrSpouse = CreateInd(tab_Family.SpouseFullName, tab_Family.SpouseGender, 0, ptrSource)
-- Add Residence if exists
if tab_Family.SpousePlc ~= nil then
ptrSpouseRes = AddEvent(ptrSpouse, 'RESI', dAfterDate, CleanPlace(tab_Family.SpousePlc), ptrSource)
end
-- Add Spouse of family
AddFamilyMember(tSpouseRel,ptrSpouseFam,ptrSpouse)
end
-- Add Children
if tab_Family.NumChildren > 0 then
for key2,ChildData in pairs(tab_Family.Children) do
-- Add Individual Child
local ptrChild = CreateInd(ChildData['FullName'], ChildData['Gender'], 0 , ptrSource)
AddFamilyMember('CHIL', ptrSpouseFam, ptrChild)
-- Add Residence if exists
if ChildData['ResidencePlc'] ~= nil then
local ptrChildRes = AddEvent(ptrChild, 'RESI', dAfterDate, CleanPlace(ChildData['ResidencePlc']), ptrSource)
end
end
end
end
ptrPartsFam = nil
-- Add Parent(s) & Family
if tab_Family.Child ~= nil then
local dAfterDate = fhNewDate()
dAfterDate:SetRange('after',dpDatePt)
-- Create family
ptrPartsFam = fhCreateItem("FAM")
-- Add main individual as child of family
AddFamilyMember('CHIL', ptrPartsFam, ptrind)
-- Set relationship type for the individual
if tab_Family.Adopted then
ptrFAMC = fhGetItemPtr(ptrind,'~.FAMC')
ptrAdopted = fhCreateItem('PEDI', ptrFAMC)
fhSetValueAsText(ptrAdopted, 'Adopted')
else
if tab_Family.Foster then
ptrFAMC = fhGetItemPtr(ptrind,'~.FAMC')
ptrAdopted = fhCreateItem('PEDI', ptrFAMC)
fhSetValueAsText(ptrAdopted, 'Foster')
end
end
-- Create Siblings
if tab_Family.NumSiblings > 0 then
for key2,SibData in pairs(tab_Family.Siblings) do
-- Add Individual Sibling
local ptrSibling = CreateInd(SibData['FullName'], SibData['Gender'], 0 , ptrSource)
AddFamilyMember('CHIL', ptrPartsFam, ptrSibling)
-- Add Residence if exists
if SibData['ResidencePlc'] ~= nil then
local ptrSibling1Res = AddEvent(ptrSibling, 'RESI', dAfterDate, CleanPlace(SibData['ResidencePlc']), ptrSource)
end
-- Add Siblings Spouse if exists
if SibData['SpouseName'] ~= nil then
local ptrSiblingSpouse = CreateInd(SibData['SpouseName'], SibData['SpouseGender'], 0 , ptrSource)
local ptrSpouseSibFam = fhCreateItem("FAM")
AddFamilyMember('WIFE', ptrSpouseSibFam, ptrSibling)
AddFamilyMember('HUSB', ptrSpouseSibFam, ptrSiblingSpouse)
end
end
end
if tab_Family.Parent1 ~= nil then
-- Add Parent
ptrParent1 = CreateInd(tab_Family.Parent1, tab_Family.Parent1Gender, 0 , ptrSource)
-- Add Residence if exists
if tab_Family.ParentsPlc ~= nil then
ptrParent1Res = AddEvent(ptrParent1, 'RESI', dAfterDate, CleanPlace(tab_Family.ParentsPlc), ptrSource)
end
-- Add to Family
local tParRel = 'HUSB'
if tab_Family.Parent1Gender == 'F' then
tParRel = 'WIFE'
elseif tab_Family.Parent2Gender == 'M' then
tParRel = 'WIFE'
end
AddFamilyMember(tParRel, ptrPartsFam, ptrParent1)
end
-- Parent 2
if tab_Family.Parent2 ~= nil then
-- Add Parent
ptrParent2 = CreateInd(tab_Family.Parent2, tab_Family.Parent2Gender, 0 , ptrSource)
-- Add Residence if exists
if tab_Family.ParentsPlc ~= nil then
ptrParent1Res = AddEvent(ptrParent2, 'RESI', dAfterDate, CleanPlace(tab_Family.ParentsPlc), ptrSource)
end
local tParRel = 'WIFE'
if tab_Family.Parent2Gender == 'M' then
tParRel = 'HUSB'
elseif tab_Family.Parent1Gender == 'F' then
tParRel = 'HUSB'
end
AddFamilyMember(tParRel,ptrPartsFam,ptrParent2)
end
end
-- Add GrandParent(s) Family
if tab_Family.GrandChild ~= nil then
local dAfterDate = fhNewDate()
dAfterDate:SetRange('after',dpDatePt)
-- Create family
ptrGrandPartsFam = fhCreateItem("FAM")
if tab_Family.GrandParent1 ~= nil then
-- Add GrandParent
local ptrGrandParent1 = CreateInd(tab_Family.GrandParent1, tab_Family.GrandParent1Gender, 0 , ptrSource)
-- Add Residence if exists
if tab_Family.GrandParentsPlc ~= nil then
ptrGrandParent1Res = AddEvent(ptrGrandParent1, 'RESI', dAfterDate, CleanPlace(tab_Family.GrandParentsPlc), ptrSource)
end
-- Add to Family
local tParRel = 'HUSB'
if tab_Family.GrandParent1Gender == 'F' then
tParRel = 'WIFE'
elseif tab_Family.GrandParent2Gender == 'M' then
tParRel = 'WIFE'
end
AddFamilyMember(tParRel, ptrGrandPartsFam, ptrGrandParent1)
end
-- GrandParent 2
if tab_Family.GrandParent2 ~= nil then
-- Add GrandParent
local ptrGrandParent2 = CreateInd(tab_Family.GrandParent2, tab_Family.GrandParent2Gender, 0 , ptrSource)
-- Add Residence if exists
if tab_Family.ParentsPlc ~= nil then
ptrGrandParent1Res = AddEvent(ptrGrandParent2, 'RESI', dAfterDate, CleanPlace(tab_Family.GrandParentsPlc), ptrSource)
end
local tParRel = 'WIFE'
if tab_Family.GrandParent2Gender == 'M' then
tParRel = 'HUSB'
elseif tab_Family.GrandParent1Gender == 'F' then
tParRel = 'HUSB'
end
AddFamilyMember(tParRel,ptrGrandPartsFam,ptrGrandParent2)
end
-- Link to Parents
if ptrPartsFam ~= nil then
if tab_Family.GrandChildFather == true then
AddFamilyMember('CHIL', ptrGrandPartsFam, ptrParent1)
else
AddFamilyMember('CHIL', ptrGrandPartsFam, ptrParent2)
end
else
-- Create family
ptrPartsFam = fhCreateItem("FAM")
-- Add main individual as child of family
AddFamilyMember('CHIL', ptrPartsFam, ptrind)
-- Dummy Parent
local ptrParent = nil
if tab_Family.GrandChildFather == true then
ptrParent = CreateInd('/' .. captialise(tMainSurname) .. '/', 'M', 0 , ptrSource)
AddFamilyMember('HUSB', ptrPartsFam, ptrParent)
else
ptrParent = CreateInd('//', 'F', 0 , ptrSource)
AddFamilyMember('WIFE', ptrPartsFam, ptrParent)
end
AddFamilyMember('CHIL', ptrGrandPartsFam, ptrParent)
end
end
end
--[[
@Title: Commonwealth War Graves Commission CSV Import
@Author: Richard Sellens
@Version: 0.4
@LastUpdated: 23/12/2012
@Description: Import saved search result CSV file, created by CWGC website
]]
--- Include IUP Extensions
require( "iuplua" )
--
----------------------------------------------------------------------------
-- Functions
----------------------------------------------------------------------------
--
--- GetExistingFile
-- @name GetExistingFile
-- @uses IUP
-- @param strTitle Prompt Title
-- @param strFilter Filter template e.g *.CSV;*.TXT
-- @param strFilterInfo Display Text for the Selection
function GetExistingFile(strTitle,strFilter,strFilterInfo,strDir)
-- Creates a file dialog and sets its type, title, filter and filter info
filedlg = iup.filedlg{dialogtype = "OPEN", title = strTitle,
filter = strFilter, filterinfo = strFilterInfo,
directory=strDir}
-- Shows file dialog in the center of the screen
filedlg:popup (iup.ANYWHERE, iup.ANYWHERE)
-- Gets file dialog status
status = filedlg.status
return status,filedlg.value
end
--- fromCSV
-- @name fromCSV
-- @description Converts a string to a table of fields, spliting according to normal CSV rules
-- @param string comma separated string
-- @return table of fields
function fromCSV (s)
s = s .. ',' -- ending comma
local t = {} -- table to collect fields
local fieldstart = 1
iID = iID + 1
table.insert(t, iID)
repeat
-- next field is quoted? (start with `"'?)
if string.find(s, '^"', fieldstart) then
local a, c
local i = fieldstart
repeat
-- find closing quote
a, i, c = string.find(s, '"("?)', i+1)
until c ~= '"' -- quote not followed by quote?
if not i then
error('unmatched "')
end
local f = string.sub(s, fieldstart+1, i-1)
table.insert(t, (string.gsub(f, '""', '"')))
fieldstart = string.find(s, ',', i) + 1
else -- unquoted; find next comma
local nexti = string.find(s, ',', fieldstart)
table.insert(t, string.sub(s, fieldstart, nexti-1))
fieldstart = nexti + 1
end
until fieldstart > string.len(s)
return t
end
--- LoadFile
-- @name loadfile
-- @description Loads a CSV file into a table of tables
-- @usage provide valid filename, use ipairs loop to use resulting table
-- @param filename filename to load
-- @return table of tables
function loadfile(filename)
contents = {}
bheader = false
for line in io.lines(filename) do
fields = fromCSV(line)
data = {}
--
if bheader then
-- Build Data Table with the Header Descriptions
for i,field in ipairs(fields) do
if field ~= '' then
data[header[i]] = field
end
end
contents[fields[1]] =data
else
-- Grab Column Names
header = fields
bheader = true
end
end
return contents
end
--- CreateSource
-- @name CreateSource
-- @description Creates a new Source Record SOUR
-- @param name string
-- @return item pointer for new record
function CreateSource(sName)
local ptrSOUR = fhCreateItem("SOUR") -- create an Source record and ret ptr to it
local ptrTITL = fhCreateItem("TITL", ptrSOUR) -- create a TITLE field within this record, and ret ptr to it
fhSetValueAsText(ptrTITL, sName) -- set value of the name using passed in parameter
local ptrREPO = fhCreateItem("REPO", ptrSOUR)
fhSetValueAsLink(ptrREPO, CreateRepo())
return ptrSOUR -- return pointer to the newly-created Individual record
end
--- CreateRepo
-- @name CreateRepo
-- @description Creates a new Record REPO
-- @param name string
-- @return item pointer for new record
function CreateRepo()
local ptrREPO = fhCreateItem("REPO")
local ptrTITL = fhCreateItem("NAME", ptrREPO)
fhSetValueAsText(ptrTITL, 'Commonwealth War Graves Commission')
local ptrADDR = fhCreateItem("ADDR", ptrREPO)
fhSetValueAsText(ptrADDR, '2 Marlow Road\nMaidenhead\nBerkshire\nSL6 7DX\nEngland')
local ptrPHON = fhCreateItem("PHON", ptrREPO)
fhSetValueAsText(ptrPHON, '+44 (0) 1628 634221')
local ptrWEB = fhCreateItem("_WEB", ptrREPO)
fhSetValueAsText(ptrWEB, 'http://www.cwgc.org/')
return ptrREPO -- return pointer to the newly-created record
end
--- CreateInd
-- @name CreateInd
-- @description Creates a new individual Record INDI
-- @param name string in format forenames /surname/ NAME
-- @param sex string either M or F or Male or Female SEX
-- @param customid string for records custom ID REFN
-- @return item pointer for new record
function CreateInd(sName, sSex, sCustomID, ptrSource)
local ptrInd = fhCreateItem("INDI") -- create an Individual record and ret ptr to it
local ptrSOUR = fhCreateItem('SOUR', ptrInd) -- create a source subfield
fhSetValueAsLink(ptrSOUR, ptrSource)
local ptrName = fhCreateItem("NAME", ptrInd) -- create a NAME field within this record, and ret ptr to it
fhSetValueAsText(ptrName, sName) -- set value of the name using passed in parameter
if sSex ~= nil and sSex ~= ' ' then
local ptrSex = fhCreateItem("SEX", ptrInd) -- create a SEX field within this record, and ret ptr to it
fhSetValueAsText(ptrSex, sSex) -- set value of sex using passed in parameter
end
return ptrInd -- return pointer to the newly-created Individual record
end
--- AddEvent
-- @name AddEvent
-- @description Adds an event to a record
-- @usage event must be a valid data reference for the pointer provided
-- @param ptrRecord point for individual record INDI
-- @param event event type eg BIRT, DEAT etc
-- @param eventdate string containing date in FH reconised format DATE
-- @param eventplace place for event PLAC
-- @return none
function AddEvent(ptrRecord,event,eventdate,eventplace,ptrSource)
ptrEvent = fhCreateItem(event,ptrRecord) -- create a event field
ptrSOUR = fhCreateItem('SOUR', ptrEvent) -- create a source subfield for it
fhSetValueAsLink(ptrSOUR, ptrSource)
if eventdate ~= nil then
-- create a date subfield for it & set value of the date using passed in parameter
ptrDate = fhCreateItem('DATE', ptrEvent)
fhSetValueAsDate(ptrDate, eventdate)
end
if eventplace ~= nil then
-- create a place subfield for it & set value of the place using passed in parameter
ptrPlace = fhCreateItem('PLAC', ptrEvent)
fhSetValueAsText(ptrPlace, eventplace)
end
return(ptrEvent)
end
-- Set first letter to capital and the rest to lower case.
function tchelper(first, rest)
return first:upper()..rest:lower()
end
-- Set change the "middle" letter to upper case (eg McMull).
function upperspecial (start,middle,rest)
return start..middle:upper()..rest:lower()
end
-- Set change the first letter(s) to lower case (eg de'Watt).
function lowerspecial (start,middle,rest)
return start:lower()..middle:upper()..rest:lower()
end
function lowerspecial2 (start,middle,rest)
return start..middle..rest:lower()
end
function alllower (start)
return start:lower()
end
-- captialise string
function captialise(str)
str = str:gsub("(%a)([%w_]*)", tchelper)
-- Add Special Cases Here
str = str:gsub("(Mac)(%a)([%w_]*)", upperspecial)
str = str:gsub("(Mc)(%a)([%w_]*)", upperspecial)
str = str:gsub("(De')(%a)([%w_]*)", lowerspecial)
str = str:gsub("(O')(%a)([%w_]*)", upperspecial)
str = str:gsub("( Of )", alllower)
str = str:gsub("(%a)([%w_]*)('S)", lowerspecial2)
str = str:gsub("(%d+)([%w_]*)", tchelper)
return(str)
end
function MilService(str)
if string.find(str, 'Royal Navy')~= nil then
tService = 'Royal Navy'
elseif string.find(str, 'Royal Naval Volunteer Reserve')~= nil then
tService = 'Royal Naval Volunteer Reserve'
elseif string.find(str, 'Royal Naval Reserve')~= nil then
tService = 'Royal Naval Reserve'
elseif string.find(str, 'Royal Air Force')~= nil then
tService = 'Royal Air Force'
elseif string.find(str, 'Canadian')~= nil then
tService = 'Canadian Over-Seas Expeditionary Force'
elseif string.find(str, 'Australian')~= nil then
tService = 'Australian Infantry'
elseif string.find(str, 'Mercantile Marine')~= nil then
tService = 'Merchant Navy'
else
tService = 'British Army'
end
return(tService)
end
function MilAward(str)
local tandBar = ''
if string.find(str, 'and Bar')~= nil then
tandBar = string.sub(str, string.find(str, 'and Bar') - 1)
str = string.sub(str, 1, string.find(str, 'and Bar') - 2)
end
if str == 'M M' then
tMilAward = 'Military Medal'
elseif str == 'M B E' then
tMilAward = 'MBE'
elseif str == 'M C' then
tMilAward = 'Military Cross'
elseif str == 'D C M' then
tMilAward = 'Distinguished Conduct Medal'
elseif str == 'V C' then
tMilAward = 'Victoria Cross'
elseif str == 'T D' then
tMilAward = 'Territorial Decoration'
elseif str == 'M S M' then
tMilAward = 'Meritorious Service Medal'
elseif str == 'D S O' then
tMilAward = 'Distinguished Service Order'
else
tMilAward = captialise(str)
end
return(tMilAward ..tandBar)
end
function Gender(str)
if str == nil then
tGender = ' '
elseif string.find(str, 'MR. ')~= nil then
tGender = 'M'
elseif string.find(str, 'MR ')~= nil then
tGender = 'M'
elseif string.find(str, 'MRS. ')~= nil then
tGender = 'F'
elseif string.find(str, 'MISS ')~= nil then
tGender = 'F'
else
tGender = ' '
end
return(tGender)
end
function ExtractAddlInfo (s)
AddlNote = ''
tab_Individual = {}
tab_Family = {}
local tab_Siblings = {}
local tab_Children = {}
-- Initialise Number of relatives fields
tab_Family.NumSiblings = 0
tab_Family.NumChildren = 0
if s ~= nil then
s = s .. ';' -- ending
local t2 = {} -- table to collect fields
local fieldstart = 1
repeat
-- next field is quoted? (start with `"'?)
if string.find(s, '^"', fieldstart) then
local a, c
local i = fieldstart
repeat
-- find closing quote
a, i, c = string.find(s, '"("?)', i+1)
until c ~= '"' -- quote not followed by quote?
if not i then
error('unmatched "')
end
local f = string.sub(s, fieldstart+1, i-1)
tInsertTxt = string.gsub(f, '""', '"')
fieldstart = string.find(s, ';', i) + 1
else -- unquoted; find next semi-colon
local nexti = string.find(s, ';', fieldstart)
tInsertTxt = string.sub(s, fieldstart, nexti-1)
fieldstart = nexti + 1
end
-- Extract Details
if string.find(tInsertTxt, 'ADOPTED')~= nil then
tab_Family.Adopted = true
end
if string.find(tInsertTxt, 'FOSTER')~= nil then
tab_Family.Foster = true
end
if string.find(tInsertTxt, 'BORN AT')~= nil then
tab_Individual.BirthPlace = captialise(string.sub(tInsertTxt, string.find(tInsertTxt, 'BORN AT')+8))
elseif string.find(tInsertTxt, 'DIED AT')~= nil then
tab_Individual.DeathPlace = captialise(string.sub(tInsertTxt, string.find(tInsertTxt, 'DIED AT')+8))
elseif string.find(tInsertTxt, 'ENLISTED')~= nil then
tab_Individual.Enlistment = string.sub(tInsertTxt, string.find(tInsertTxt, 'ENLISTED')+9)
elseif string.find(tInsertTxt, 'EDUCATED AT') ~= nil then
tab_Individual.Educated = captialise(string.sub(tInsertTxt, string.find(tInsertTxt, 'EDUCATED AT')+12))
elseif string.find(tInsertTxt, 'SERVED IN') ~= nil then
tab_Individual.MilService = captialise(string.sub(tInsertTxt, string.find(tInsertTxt, 'SERVED IN')+10))
elseif string.find(tInsertTxt, 'NATIVE OF')~= nil then
tab_Individual.Native = captialise(string.sub(tInsertTxt, string.find(tInsertTxt, 'NATIVE OF')+10))
elseif string.find(tInsertTxt, 'HUSBAND OF')~= nil then
tab_Individual.Gender = 'M'
tab_Family.Spouse = true
tab_Family.SpouseGender = 'F'
local tBSpouse = string.sub(tInsertTxt, string.find(tInsertTxt, 'HUSBAND OF')+11)
if string.find(tBSpouse, ', OF')~= nil then
tab_Family.SpousePlc = captialise(string.sub(tBSpouse, string.find(tBSpouse, ', OF')+5))
tBSpouse = string.sub(tBSpouse, 1, string.find(tBSpouse, ', OF')-1)
end
tBSpouse = tBSpouse:gsub(tMainSurname, '')
tab_Family.SpouseFullName = FormatName(tBSpouse)
elseif string.find(tInsertTxt, 'BROTHER OF')~= nil then
tab_Individual.Gender = 'M'
tab_Family.Child = true
tab_Family.NumSiblings = tab_Family.NumSiblings + 1
local tab_SiblingDetails = {}
local tSibling = string.sub(tInsertTxt, string.find(tInsertTxt, 'BROTHER OF')+10)
if string.find(tSibling, ', OF')~= nil then
tab_SiblingDetails.ResidencePlc = captialise(string.sub(tSibling, string.find(tSibling, ', OF')+5))
tSibling = string.sub(tSibling, 1, string.find(tSibling, ', OF')-1)
end
tab_SiblingDetails.Gender = Gender(tSibling)
tab_SiblingDetails.FullName = FormatName(tSibling)
table.insert(tab_Siblings, tab_SiblingDetails)
elseif string.find(tInsertTxt, 'HIS BROTHER ') ~= nil or string.find(tInsertTxt, 'HIS BROTHER, ') ~= nil or
string.find(tInsertTxt, 'HIS BROTHERS ') ~= nil then
tab_Family.Child = true
local strtpos = 1
if string.find(tInsertTxt, 'HIS BROTHER ') ~= nil then
strtpos = string.find(tInsertTxt, 'HIS BROTHER ') + 12
elseif string.find(tInsertTxt, 'HIS BROTHER, ') ~= nil then
strtpos = string.find(tInsertTxt, 'HIS BROTHER, ') + 13
elseif string.find(tInsertTxt, 'HIS BROTHERS ') ~= nil then
strtpos = string.find(tInsertTxt, 'HIS BROTHERS ') + 13
end
local endpos = 1
if string.find(tInsertTxt, 'ALSO FELL') ~= nil then
endpos = string.find(tInsertTxt, 'ALSO FELL') - 1
elseif string.find(tInsertTxt, 'ALSO DIED') ~= nil then
endpos = string.find(tInsertTxt, 'ALSO DIED') - 1
end
local NameList = string.sub(tInsertTxt, strtpos, endpos) ..' AND '
local fieldstart = 1
repeat
local nexti = string.find(NameList, ' AND ', fieldstart)
tab_Family.NumSiblings = tab_Family.NumSiblings + 1
local tab_SiblingDetails = {}
tab_SiblingDetails.Gender = 'M'
tab_SiblingDetails.FullName = FormatName(string.sub(NameList, fieldstart, nexti-1))
table.insert(tab_Siblings, tab_SiblingDetails)
fieldstart = nexti + 5
until fieldstart > string.len(NameList)
elseif string.find(tInsertTxt, 'HIS BROTHER-IN-LAW', 1, true) ~= nil then
tab_Family.Child = true
tab_Family.NumSiblings = tab_Family.NumSiblings + 1
local tab_SiblingDetails = {}
tab_SiblingDetails.Gender = 'F'
tab_SiblingDetails.FullName = '/' ..captialise(tMainSurname) ..'/'
tab_SiblingDetails.SpouseGender = 'M'
local strtpos = string.find(tInsertTxt, 'HIS BROTHER-IN-LAW', 1, true) + 19
local endpos = -1
if string.find(tInsertTxt, 'ALSO FELL') ~= nil then
endpos = string.find(tInsertTxt, 'ALSO FELL') - 1
elseif string.find(tInsertTxt, 'ALSO DIED') ~= nil then
endpos = string.find(tInsertTxt, 'ALSO DIED') - 1
end
local NameList = string.sub(tInsertTxt, strtpos, endpos)
tab_SiblingDetails.SpouseName = FormatName(NameList)
table.insert(tab_Siblings, tab_SiblingDetails)
elseif string.find(tInsertTxt, 'FATHER OF')~= nil then
tab_Individual.Gender = 'M'
tab_Family.NumChildren = tab_Family.NumChildren + 1
local tab_ChildDetails = {}
local tChild = string.sub(tInsertTxt, string.find(tInsertTxt, 'FATHER OF')+10)
if string.find(tChild, ', OF')~= nil then
tab_ChildDetails.ResidencePlc = captialise(string.sub(tChild, string.find(tChild, ', OF')+5))
tChild = string.sub(tChild, 1, string.find(tChild, ', OF')-1)
end
tab_ChildDetails.FullName = FormatName(tChild)
table.insert(tab_Children, tab_ChildDetails)
elseif string.find(tInsertTxt, 'NEPHEW OF')~= nil then
tab_Individual.Gender = 'M'
table.insert(t2, tInsertTxt)
elseif string.find(tInsertTxt, 'GRANDSON OF')~= nil then
local tGrandParent1 = nil
local tGrandParent2 = nil
local tGrandParents = nil
tab_Individual.Gender = 'M'
tab_Family.GrandChild = true
tGrandParents = string.sub(tInsertTxt, string.find(tInsertTxt, 'GRANDSON OF')+12)
if string.find(tGrandParents, tMainSurname) ~= nil then
tab_Family.GrandChildFather = true
else
tab_Family.GrandChildMother = true
end
if string.find(tGrandParents, ', OF') ~= nil then
tab_Family.GrandParentsPlc = captialise(string.sub(tGrandParents, string.find(tGrandParents, ', OF')+5))
tGrandParents = string.sub(tGrandParents, 1, string.find(tGrandParents, ', OF')-1)
end
if string.find(tGrandParents, 'MR. AND MRS.') ~= nil then
tGrandParent1 = string.sub(tGrandParents, string.find(tGrandParents, 'MR. AND MRS.')+13)
tab_Family.GrandParent1Gender = 'M'
tab_Family.GrandParent2Gender = 'F'
else
if string.find(tGrandParents, ' AND ') ~= nil then
tGrandParent1 = string.sub(tGrandParents, 1, string.find(tGrandParents, ' AND ')-1)
if string.find(tGrandParent1, tMainSurname) == nil then
tGrandParent1 = tGrandParent1 ..' ' ..tMainSurname
end
tGrandParent2 = string.sub(tGrandParents, string.find(tGrandParents, ' AND ')+5)
tab_Family.GrandParent1Gender = Gender(tGrandParent1)
tab_Family.GrandParent2Gender = Gender(tGrandParent2)
else
tGrandParent1 = tGrandParents
tab_Family.GrandParent1Gender = Gender(tGrandParent1)
end
end
if tab_Family.GrandParent1Gender == 'F' then
tGrandParent1 = tGrandParent1:gsub(tMainSurname, '')
end
tab_Family.GrandParent1 = FormatName(tGrandParent1)
if tGrandParent2 ~= nil then
if tab_Family.GrandParent2Gender ~= 'M' then
tGrandParent2 = tGrandParent2:gsub(tMainSurname, '')
end
tab_Family.GrandParent2 = FormatName(tGrandParent2)
end
elseif string.find(tInsertTxt, 'SON OF') ~= nil or string.find(tInsertTxt, 'CHILD OF') ~= nil then
local tParent1 = nil
local tParent2 = nil
local tParents = nil
tab_Individual.Gender = 'M'
tab_Family.Child = true
if string.find(tInsertTxt, 'SON OF') ~= nil then
tParents = string.sub(tInsertTxt, string.find(tInsertTxt, 'SON OF')+7)
elseif string.find(tInsertTxt, 'CHILD OF') ~= nil then
tParents = string.sub(tInsertTxt, string.find(tInsertTxt, 'CHILD OF')+9)
end
if string.find(tParents, ', OF') ~= nil then
tab_Family.ParentsPlc = captialise(string.sub(tParents, string.find(tParents, ', OF')+5))
tParents = string.sub(tParents, 1, string.find(tParents, ', OF')-1)
end
if string.find(tParents, 'MR. AND MRS.') ~= nil then
tParent1 = string.sub(tParents, string.find(tParents, 'MR. AND MRS.')+13)
tab_Family.Parent1Gender = 'M'
tab_Family.Parent2Gender = 'F'
else
if string.find(tParents, ' AND ') ~= nil then
tParent1 = string.sub(tParents, 1, string.find(tParents, ' AND ')-1)
if string.find(tParent1, tMainSurname) == nil then
tParent1 = tParent1 ..' ' ..tMainSurname
end
tParent2 = string.sub(tParents, string.find(tParents, ' AND ')+5)
tab_Family.Parent1Gender = Gender(tParent1)
tab_Family.Parent2Gender = Gender(tParent2)
else
tParent1 = tParents
tab_Family.Parent1Gender = Gender(tParent1)
end
end
if tab_Family.Parent1Gender == 'F' then
tParent1 = tParent1:gsub(tMainSurname, '')
end
tab_Family.Parent1 = FormatName(tParent1)
if tParent2 ~= nil then
if tab_Family.Parent2Gender ~= 'M' then
tParent2 = tParent2:gsub(tMainSurname, '')
end
tab_Family.Parent2 = FormatName(tParent2)
end
else
table.insert(t2, tInsertTxt)
end
until fieldstart > string.len(s)
for i,str in ipairs(t2) do
AddlNote = AddlNote ..str ..'\n'
end
end
if tab_Family.NumSiblings > 0 then
tab_Family.Siblings = tab_Siblings
end
if tab_Family.NumChildren > 0 then
tab_Family.Children = tab_Children
end
return(AddlNote)
end
--- AddFamilyMember
-- @name AddFamilyMember
-- @description Adds a person to a family
-- @param type Type is either SPOU or CHIL for Spouse or Child.
-- @param family record pointer
-- @param individual record pointer)
-- @return none
function AddFamilyMember(type,ptrfam,ptrind)
ptrLink = fhCreateItem(type, ptrfam )
fhSetValueAsLink(ptrLink, ptrind)
end
--- CleanPlace
-- @name CleanPlace
-- @description Performs various clean up tasks on a place value
-- @param input place field
-- @return updated place field
function CleanPlace(strPlace)
local strRetPlace = nil
if strPlace ~= nil then
strRetPlace = strPlace
-- swap comma inside quoted field to outside
strRetPlace= strRetPlace:gsub("''", '"')
strRetPlace= strRetPlace:gsub(',"', '",')
-- remove comma between 'house number' and street
if string.find(strRetPlace, ', ')~= nil then
local str = string.sub(strRetPlace, 1, string.find(strRetPlace, ', ')-1)
local str2 = string.sub(strRetPlace, string.find(strRetPlace, ', ')+1)
if tonumber(str) ~= nil then --it's a number
strRetPlace = str:gsub(' ', '') ..str2
else
if string.find(str2, ', ') ~= nil then
local str3 = string.sub(str2, string.find(str2, ', ')+1)
str2 = string.sub(str2, 1, string.find(str2, ', ')-1)
if tonumber(str2) ~= nil then --it's a number
strRetPlace = str ..', ' ..str2:gsub(' ', '') ..str3
end
end
end
end
-- remove trailing 'full stop'
if string.sub(strRetPlace, -1) == '.' then
strRetPlace = string.sub(strRetPlace, 1, string.len(strRetPlace)-1)
end
-- correct "'S" in place
strRetPlace= strRetPlace:gsub("'S ", "'s ")
end
return(strRetPlace)
end
--- FormatName
-- @name FormatName
-- @description Performs various clean up tasks on a name value
-- @param input name field
-- @return updated name field
function FormatName(inName)
local strRetName = nil
local forename = ''
local surname = tMainSurname
local suffix = ''
-- remarried ?
if string.find(inName, '%(FORMERLY') ~= nil then
inName = string.sub(inName, 1, string.find(inName, '%(FORMERLY') -2)
local fieldstart = 1
repeat
if string.find(inName, ' ', fieldstart, true) ~= nil then
local findpos = string.find(inName, ' ', fieldstart, true)
forename = string.sub(inName, 1, findpos - 1)
surname = ''
fieldstart = findpos + 1
else
fieldstart = string.len(inName) + 1
end
until fieldstart > string.len(inName)
-- Maiden name ?
elseif string.find(inName, '%(NEE') ~= nil then
forename = string.sub(inName, 1, string.find(inName, '%(NEE') -2)
if string.find(forename, tMainSurname)~= nil then
forename = string.sub(forename, 1, string.find(forename, tMainSurname)-2)
end
surname = string.sub(inName, string.find(inName, '%(NEE') +5)
surname = surname:gsub('%)', '')
else
-- Extract forname, surname & suffix fields
if string.find(inName, tMainSurname)~= nil then
forename = string.sub(inName, 1, string.find(inName, tMainSurname)-2)
local strtPos = string.find(inName, tMainSurname) + string.len(tMainSurname) + 1
suffix = string.sub(inName, strtPos, string.len(inName)-2)
else
forename = inName
surname = ''
end
end
-- Drop 'titles'
forename= forename:gsub('MR. ', '')
forename= forename:gsub('MR ', '')
forename= forename:gsub('MRS. ', '')
forename= forename:gsub('MISS ', '')
forename= forename:gsub('THE LATE ', '')
strRetName = captialise(forename) ..' /' ..captialise(surname) ..'/' ..captialise(suffix)
return(strRetName)
end
--- ExtractEnlistmentDetails
-- @name ExtractEnlistmentDetails
-- @description takes the enlistment string & extracts details
-- @param input Enlistment text string field
-- @return none
function ExtractEnlistmentDetails(strEnlist)
local EnlistmentNote = ''
-- Correct 'Regiment' text
strEnlist = strEnlist:gsub("REGT.,", "Regt. ,")
-- Remove any unwanted text in field
strEnlist = strEnlist:gsub("%.,", "")
strEnlist = strEnlist:gsub("IN ", "")
-- Extract 'data' blocks from Enlistment String
local t4 = SplitString_Comma(strEnlist .. ',')
-- Process Blocks
for i,str in ipairs(t4) do
-- Look for Enlistment Date
local enlistdatefield = fhNewDate()
if enlistdatefield:SetValueAsText(str,false) then
tab_Individual.EnlistmentDate = enlistdatefield
else
EnlistmentNote = EnlistmentNote ..str ..'\n'
end
end
if EnlistmentNote ~= '' then
tab_Individual.EnlistmentNote = captialise(EnlistmentNote)
end
end
--- SplitString_Comma
-- @name SplitString_Comma
-- @description splits string into blocks based on comma
-- @param input text string field
-- @return table of blocks
function SplitString_Comma(inStr)
-- Extract 'data' blocks from String
local RetTable = {} -- table to collect fields
local fieldstart = 1
inStr = inStr:gsub(", ", ",")
repeat
-- next field is quoted? (start with `"'?)
if string.find(inStr, '^"', fieldstart) then
local a, c
local i = fieldstart
repeat
-- find closing quote
a, i, c = string.find(inStr, '"("?)', i+1)
until c ~= '"' -- quote not followed by quote?
if not i then
error('unmatched "')
end
local f = string.sub(inStr, fieldstart+1, i-1)
tInsertTxt = string.gsub(f, '""', '"')
fieldstart = string.find(inStr, ',', i) + 1
else -- unquoted; find next semi-colon
local nexti = string.find(inStr, ',', fieldstart)
tInsertTxt = string.sub(inStr, fieldstart, nexti-1)
fieldstart = nexti + 1
end
table.insert(RetTable, tInsertTxt)
until fieldstart > string.len(inStr)
return(RetTable)
end
--
----------------------------------------------------------------------------
-- Main Code
----------------------------------------------------------------------------
--
-- Check for Empty gedcom
--
ptrind = fhNewItemPtr()
ptrind:MoveToFirstRecord("INDI") -- set the first to point to the first Source record
if ptrind:IsNotNull() then
sMessage = [[
Warning: Data exists in the GEDCOM file.
This script takes no account of existing data
and is better used on a New empty file.
Do you wish to continue?
]]
a = fhMessageBox(sMessage, "MB_YESNO","MB_ICONEXCLAMATION")
if a == "No" then
error('Script Aborted')
end
end
--
-- Prompt for file to Process
--
status,strfilename = GetExistingFile("Select Missing File","*.csv","Comma Separated File","Documents")
if status == '-1' then
error('Prompt Cancelled')
end
iID = 0
-- Call loadfile function to return a table with the data in.
contents = loadfile(strfilename)
family = {}
individual = {}
-- Create Source record
ptrSource = CreateSource('CWGC Search')
-- Create People
for key,data in pairs(contents) do
-- Create Name
if data['forename'] ~= nil then
fornames = data['forename']
else
fornames = data['initials']
end
name = captialise(fornames)..' /'..captialise(data['surname'])..'/'
tMainSurname = data['surname']
-- Create Individual Record
AddlInfo = ExtractAddlInfo(data['additionalinformation'])
ptrind = CreateInd(name, tab_Individual.Gender, 0, ptrSource)
individual[0] = ptrind:Clone()
tempdatefield = fhNewDate()
tempdatefield:SetValueAsText(data['date_of_death'],true)
dpDatePt = tempdatefield:GetDatePt1()
-- Add Birth Event
if data['age_text'] ~= nil then
iAge = data['age_text']
iYear = dpDatePt:GetYear()
iBirth = iYear - iAge
tempdatefield = fhNewDate()
tempdatefield:SetValueAsText(iBirth,true)
eventdatefield = fhNewDate()
eventdatefield:SetSimpleDate(tempdatefield:GetDatePt1(), 'cal')
ptrBIRT = AddEvent(ptrind, 'BIRT', eventdatefield, CleanPlace(tab_Individual.BirthPlace), ptrSource)
else
if tab_Individual.BirthPlace ~= nil then
ptrBIRT = AddEvent(ptrind, 'BIRT', nil, CleanPlace(tab_Individual.BirthPlace), ptrSource)
end
end
-- Add Death Event
eventdatefield = fhNewDate()
eventdatefield:SetValueAsText(data['date_of_death'],true)
ptrDEAT = AddEvent(ptrind, 'DEAT', eventdatefield, CleanPlace(tab_Individual.DeathPlace), ptrSource)
if data['age_text'] ~= nil then
ptrAge = fhCreateItem('AGE', ptrDEAT)
tAge = data['age_text']..'y'
fhSetValueAsText(ptrAge, tAge)
end
-- Add Burial/Memorial Event
if string.find(data['cemeterymemorial'], 'MEMORIAL') ~= nil then
strTag = fhGetFactTag("Memorial", "Event", "INDI", false)
tRefTxt = 'Memorial Reference : '
else
strTag = 'BURI'
tRefTxt = 'Burial Reference : '
end
if data['country'] == 'Civilian War Dead' then
tPLAC = ', , United Kingdom'
else
tPLAC = ', , '..captialise(data['country'])
end
ptrBURMEM = AddEvent(ptrind, strTag, nil, tPLAC, ptrSource)
ptrPlace = fhCreateItem('ADDR', ptrBURMEM)
tADDR = captialise(data['cemeterymemorial'])..tPLAC
fhSetValueAsText(ptrPlace, tADDR)
if data['gravereference'] ~= nil then
ptrNOTE = fhCreateItem('NOTE2', ptrBURMEM)
fhSetValueAsText(ptrNOTE, tRefTxt..data['gravereference'])
end
if data['rank'] ~= 'Civilian' then
-- Add Military Enlistment
if tab_Individual.Enlistment ~= nil then
local dummy = ExtractEnlistmentDetails(tab_Individual.Enlistment)
end
strTag = fhGetFactTag("Military Enlistment", "Attribute", "INDI", false)
if tab_Individual.EnlistmentDate ~= nil then
dToDate = tab_Individual.EnlistmentDate
else
dToDate = fhNewDate()
dToDate:SetRange('before',dpDatePt)
end
ptrEnlist = AddEvent(ptrind, strTag, dToDate, nil, ptrSource)
fhSetValueAsText(ptrEnlist, MilService(data['regiment']))
ptrNOTE = fhCreateItem('NOTE2', ptrEnlist)
if data['servicenumberExport'] ~= nil then
tSrvNum = 'Military Service No. : '..string.gsub(data['servicenumberExport'], '\'', '')
else
tSrvNum = 'Military Service No. : '
end
fhSetValueAsText(ptrNOTE, tSrvNum)
if tab_Individual.EnlistmentNote ~= nil then
local ptrNOTE2 = fhCreateItem('NOTE2', ptrEnlist)
fhSetValueAsText(ptrNOTE2, tab_Individual.EnlistmentNote)
end
-- Add Military Service
strTag = fhGetFactTag("Military Service", "Attribute", "INDI", false)
dToDate = fhNewDate()
dToDate:SetPeriod('to',dpDatePt)
ptrMilS = AddEvent(ptrind, strTag, dToDate, nil, ptrSource)
if data['unitshipsquadron'] ~= nil then
tUnit = data['unitshipsquadron']..' '..data['regiment']
else
tUnit = data['regiment']
end
tMilSvc = data['rank']..', '..tUnit
fhSetValueAsText(ptrMilS, tMilSvc)
-- Add Military Award
if data['honours_awards'] ~= nil then
local t3 = SplitString_Comma(data['honours_awards'] .. ',')
local strTag = fhGetFactTag("Military Award", "Attribute", "INDI", false)
for i,str in ipairs(t3) do
ptrMilA = AddEvent(ptrind, strTag, nil, nil, ptrSource)
fhSetValueAsText(ptrMilA, MilAward(str))
end
end
-- Add Military Conflict
if tab_Individual.MilService ~= nil then
local strTag = fhGetFactTag("Military Conflict", "Attribute", "INDI", false)
local ptrMilS = AddEvent(ptrind, strTag, nil, nil, ptrSource)
fhSetValueAsText(ptrMilS, tab_Individual.MilService)
end
end
-- Add Education Detail
if tab_Individual.Educated ~= nil then
ptrEduc = AddEvent(ptrind, 'EDUC', nil, nil, ptrSource)
fhSetValueAsText(ptrEduc, tab_Individual.Educated)
end
-- Add 'Native of' details
if tab_Individual.Native ~= nil then
ptrResi = AddEvent(ptrind, 'RESI', nil, CleanPlace(tab_Individual.Native), ptrSource)
end
-- Add Note
if AddlInfo ~= nil and AddlInfo ~= '' then
ptrNOTE = fhCreateItem('NOTE2', ptrind)
fhSetValueAsText(ptrNOTE, AddlInfo)
end
-- Add Spouse & Family
if tab_Family.Spouse ~= nil or tab_Family.NumChildren > 0 then
local dAfterDate = fhNewDate()
dAfterDate:SetRange('after',dpDatePt)
-- Create New Family
ptrSpouseFam = fhCreateItem("FAM")
-- Add main individual to family
if tab_Individual.Gender == 'F' then
tRel = 'WIFE'
tSpouseRel = 'HUSB'
else
tRel = 'HUSB'
tSpouseRel = 'WIFE'
end
AddFamilyMember(tRel, ptrSpouseFam, ptrind)
-- Add Spouse
if tab_Family.Spouse ~= nil then
-- Build Spouse
ptrSpouse = CreateInd(tab_Family.SpouseFullName, tab_Family.SpouseGender, 0, ptrSource)
-- Add Residence if exists
if tab_Family.SpousePlc ~= nil then
ptrSpouseRes = AddEvent(ptrSpouse, 'RESI', dAfterDate, CleanPlace(tab_Family.SpousePlc), ptrSource)
end
-- Add Spouse of family
AddFamilyMember(tSpouseRel,ptrSpouseFam,ptrSpouse)
end
-- Add Children
if tab_Family.NumChildren > 0 then
for key2,ChildData in pairs(tab_Family.Children) do
-- Add Individual Child
local ptrChild = CreateInd(ChildData['FullName'], ChildData['Gender'], 0 , ptrSource)
AddFamilyMember('CHIL', ptrSpouseFam, ptrChild)
-- Add Residence if exists
if ChildData['ResidencePlc'] ~= nil then
local ptrChildRes = AddEvent(ptrChild, 'RESI', dAfterDate, CleanPlace(ChildData['ResidencePlc']), ptrSource)
end
end
end
end
ptrPartsFam = nil
-- Add Parent(s) & Family
if tab_Family.Child ~= nil then
local dAfterDate = fhNewDate()
dAfterDate:SetRange('after',dpDatePt)
-- Create family
ptrPartsFam = fhCreateItem("FAM")
-- Add main individual as child of family
AddFamilyMember('CHIL', ptrPartsFam, ptrind)
-- Set relationship type for the individual
if tab_Family.Adopted then
ptrFAMC = fhGetItemPtr(ptrind,'~.FAMC')
ptrAdopted = fhCreateItem('PEDI', ptrFAMC)
fhSetValueAsText(ptrAdopted, 'Adopted')
else
if tab_Family.Foster then
ptrFAMC = fhGetItemPtr(ptrind,'~.FAMC')
ptrAdopted = fhCreateItem('PEDI', ptrFAMC)
fhSetValueAsText(ptrAdopted, 'Foster')
end
end
-- Create Siblings
if tab_Family.NumSiblings > 0 then
for key2,SibData in pairs(tab_Family.Siblings) do
-- Add Individual Sibling
local ptrSibling = CreateInd(SibData['FullName'], SibData['Gender'], 0 , ptrSource)
AddFamilyMember('CHIL', ptrPartsFam, ptrSibling)
-- Add Residence if exists
if SibData['ResidencePlc'] ~= nil then
local ptrSibling1Res = AddEvent(ptrSibling, 'RESI', dAfterDate, CleanPlace(SibData['ResidencePlc']), ptrSource)
end
-- Add Siblings Spouse if exists
if SibData['SpouseName'] ~= nil then
local ptrSiblingSpouse = CreateInd(SibData['SpouseName'], SibData['SpouseGender'], 0 , ptrSource)
local ptrSpouseSibFam = fhCreateItem("FAM")
AddFamilyMember('WIFE', ptrSpouseSibFam, ptrSibling)
AddFamilyMember('HUSB', ptrSpouseSibFam, ptrSiblingSpouse)
end
end
end
if tab_Family.Parent1 ~= nil then
-- Add Parent
ptrParent1 = CreateInd(tab_Family.Parent1, tab_Family.Parent1Gender, 0 , ptrSource)
-- Add Residence if exists
if tab_Family.ParentsPlc ~= nil then
ptrParent1Res = AddEvent(ptrParent1, 'RESI', dAfterDate, CleanPlace(tab_Family.ParentsPlc), ptrSource)
end
-- Add to Family
local tParRel = 'HUSB'
if tab_Family.Parent1Gender == 'F' then
tParRel = 'WIFE'
elseif tab_Family.Parent2Gender == 'M' then
tParRel = 'WIFE'
end
AddFamilyMember(tParRel, ptrPartsFam, ptrParent1)
end
-- Parent 2
if tab_Family.Parent2 ~= nil then
-- Add Parent
ptrParent2 = CreateInd(tab_Family.Parent2, tab_Family.Parent2Gender, 0 , ptrSource)
-- Add Residence if exists
if tab_Family.ParentsPlc ~= nil then
ptrParent1Res = AddEvent(ptrParent2, 'RESI', dAfterDate, CleanPlace(tab_Family.ParentsPlc), ptrSource)
end
local tParRel = 'WIFE'
if tab_Family.Parent2Gender == 'M' then
tParRel = 'HUSB'
elseif tab_Family.Parent1Gender == 'F' then
tParRel = 'HUSB'
end
AddFamilyMember(tParRel,ptrPartsFam,ptrParent2)
end
end
-- Add GrandParent(s) Family
if tab_Family.GrandChild ~= nil then
local dAfterDate = fhNewDate()
dAfterDate:SetRange('after',dpDatePt)
-- Create family
ptrGrandPartsFam = fhCreateItem("FAM")
if tab_Family.GrandParent1 ~= nil then
-- Add GrandParent
local ptrGrandParent1 = CreateInd(tab_Family.GrandParent1, tab_Family.GrandParent1Gender, 0 , ptrSource)
-- Add Residence if exists
if tab_Family.GrandParentsPlc ~= nil then
ptrGrandParent1Res = AddEvent(ptrGrandParent1, 'RESI', dAfterDate, CleanPlace(tab_Family.GrandParentsPlc), ptrSource)
end
-- Add to Family
local tParRel = 'HUSB'
if tab_Family.GrandParent1Gender == 'F' then
tParRel = 'WIFE'
elseif tab_Family.GrandParent2Gender == 'M' then
tParRel = 'WIFE'
end
AddFamilyMember(tParRel, ptrGrandPartsFam, ptrGrandParent1)
end
-- GrandParent 2
if tab_Family.GrandParent2 ~= nil then
-- Add GrandParent
local ptrGrandParent2 = CreateInd(tab_Family.GrandParent2, tab_Family.GrandParent2Gender, 0 , ptrSource)
-- Add Residence if exists
if tab_Family.ParentsPlc ~= nil then
ptrGrandParent1Res = AddEvent(ptrGrandParent2, 'RESI', dAfterDate, CleanPlace(tab_Family.GrandParentsPlc), ptrSource)
end
local tParRel = 'WIFE'
if tab_Family.GrandParent2Gender == 'M' then
tParRel = 'HUSB'
elseif tab_Family.GrandParent1Gender == 'F' then
tParRel = 'HUSB'
end
AddFamilyMember(tParRel,ptrGrandPartsFam,ptrGrandParent2)
end
-- Link to Parents
if ptrPartsFam ~= nil then
if tab_Family.GrandChildFather == true then
AddFamilyMember('CHIL', ptrGrandPartsFam, ptrParent1)
else
AddFamilyMember('CHIL', ptrGrandPartsFam, ptrParent2)
end
else
-- Create family
ptrPartsFam = fhCreateItem("FAM")
-- Add main individual as child of family
AddFamilyMember('CHIL', ptrPartsFam, ptrind)
-- Dummy Parent
local ptrParent = nil
if tab_Family.GrandChildFather == true then
ptrParent = CreateInd('/' .. captialise(tMainSurname) .. '/', 'M', 0 , ptrSource)
AddFamilyMember('HUSB', ptrPartsFam, ptrParent)
else
ptrParent = CreateInd('//', 'F', 0 , ptrSource)
AddFamilyMember('WIFE', ptrPartsFam, ptrParent)
end
AddFamilyMember('CHIL', ptrGrandPartsFam, ptrParent)
end
end
endSource:CWCG-Build-from-CSV1.fh_lua