fdfToArray function
Bob Sneidar
bobsneidar at iotecdigital.com
Thu Oct 25 18:44:45 EDT 2018
Hi all.
Anyone interested in getting data from, or putting data into an Acrobat Fillable Form will appreciate this. It parses an FDF file into an LC array. I have a companion function that takes an array (formatted properly of course) and creates an fdf file that a PDF form can use to populate itself (if configured to do so). This version can parse the data created by exporting from Adobe Acrobat, or the file produced by pdftk (which contains spaces and linefeeds for some unknown reason). There is no reason it shouldn't work with *any* properly formatted fdf file.
Enjoy:
function fdfToArray2 theFDFSource, theMode
if theMode = "data" then
-- create a temporary source file for the fdf data
setDefaultFolder
put the defaultfolder & "/" & "temp/FDF_Data.fdf" into theFDFFile
open file theFDFFile for binary write
write theFDFSource to file theFDFFile
close file theFDFFile
put theFDFFile into theFDFSource
end if
open file theFdfSource for binary read
read from file theFdfSource until eof -- we will parse with LC
close file theFdfSource
put it into tFileData
-- get the header
put offset("<", tFileData) -1 into tHeaderEnd
put char 1 to tHeaderEnd of tFileData into aFDFData ["header"]
delete char 1 to tHeaderEnd of tFileData
-- get the PDF filename (if any)
-- note the filename must be present for a fillable form to auto-fill from the fdf file
put offset("/f(", tFileData) into tFilenameFieldStart
if tFilenameFieldStart >0 then
put offset(")", tFileData) into tFilenameFieldEnd
put char tFilenameFieldStart +3 to tFilenameFieldEnd -1 of tFileData into aFDFData ["filename"]
else
put empty into aFDFData ["filename"]
end if
-- extract the field data
put offset("/Fields", tFileData) into tFieldStartPos
if tFieldStartPos = 0 then return empty -- no field data
put offSet("<<", tFileData, tFieldStartPos) + tFieldStartPos into tFieldStartPos
put offset("endobj", tFileData) into tFieldEndPos
put char tFieldStartPos to tFieldEndPos -1 of tFileData into tFieldData
-- check for ID tag
put offset("/ID[", tFieldData) into tIDStartPos
if tIDStartPos > 0 then
put offset("]", tFieldData, tIDStartPos) into tIDEndPos
put char tIDStartPos +5 to tIDStartPos + tIDEndPos -2 of tFieldData into aFDFData ["ID"]
delete char tIDStartPos to tIDStartPos + tIDEndPos of tFieldData
else
put empty into aFDFData ["ID"]
end if
-- check for end of file tag
put offset("/UF(", tFieldData) into tEndFileTagStartPos
if tEndFileTagStartPos >0 then
put offset(")", tFieldData, tEndFileTagStartPos) into tEndFileTagEndPos
delete char tEndFileTagStartPos -1 to -1 of tFieldData
end if
-- get the footer
put offset("endObj", tFileData) into tFooterStartPos
put char tFooterStartPos to -1 of tFileData into aFDFData ["footer"]
delete char tFooterStartPos to -1 of tFileData
-- clean up the field data
replace "\" & cr with empty in tFieldData
replace numToChar(10) with empty in tFieldData
replace "/T " with "/T" in tFieldData
replace "/V " with "/V" in tFieldData
replace "/Kids [" with "/Kids[" in tFieldData
replace ">> <<" with ">><<" in tFieldData
replace "<<>>" with empty in tFieldData
replace ">>>>" with ">>" in tFieldData
-- Parse fillable control data
-- table objects first (kids)
put 0 into tPointer
repeat
put offset("/Kids[", tFieldData) into tKidsStartPos
if tKidsStartPos = 0 then exit repeat
put offset("]", tFieldData, tKidsStartPos) + tKidsStartPos into tKidsEndPos
put char tKidsStartPos +6 to tKidsEndPos -1 of tFieldData into tKids
put offset("/T(", tFieldData, tKidsEndPos) + tKidsEndPos into tLabelStartPos
put offset(")", tFieldData, tLabelStartPos) + tLabelStartPos into tLabelEndPos
put char tLabelStartPos +3 to tLabelEndPos-1 of tFieldData into tLabel
delete char tKidsStartPos to tLabelEndPos of tFieldData
-- kids loop
repeat
put offset("<<", tKids) into tThisKidStartPos
put offset(">>", tKids) into tThisKidEndPos
if tThisKidEndPos = 0 then exit repeat
put char tThisKidStartPos to tThisKidEndPos +2 of tKids into tThisKid
delete char 1 to tThisKidEndPos +1 of tKids
-- parse this kid
put offset("/T", tThisKid) into tElementStartPos
put offset("(", tThisKid, tElementStartPos) + tElementStartPos into tElementStartPos
put offset(")", tThisKid, tElementStartPos) + tElementStartPos into tElementEndPos
put char tElementStartPos +1 to tElementEndPos -1 of tThisKid into tElement
put offset("/V", tThisKid) into tValueStartPos
put offset("(", tThisKid, tValueStartPos) + tValueStartPos into tValueStartPos
put offset(")", tThisKid, tValueStartPos) + tValueStartPos into tValueEndPos
put char tValueStartPos +1 to tValueEndPos -1 of tThisKid into tValue
put tValue into aFDFData ["fields"] [tLabel] [tElement]
end repeat
end repeat
-- other form objects loop
replace "<<>>" with empty in tFieldData
repeat
put offset("<<", tFieldData) into tFieldStartPos
if tFieldStartPos = 0 then exit repeat
put offset(">>", tFieldData) into tFieldEndPos
put char 3 to tFieldEndPos -1 of tFieldData into tThisField
delete char 1 to tFieldEndPos +1 of tFieldData
put offset("/T(", tThisField) +2 into tElementStartPos
put offset(")", tThisField, tElementStartPos) + tElementStartPos into tElementEndPos
put char tElementStartPos +1 to tElementEndPos -1 of tThisField into tElement
put offset("/V(", tThisField) +2 into tValueStartPos
put offset(")", tThisField, tValueStartPos) + tValueStartPos into tValueEndPos
put char tValueStartPos +1 to tValueEndPos -1 of tThisField into tValue
put tValue into aFDFData ["fields"] [tElement]
end repeat
if theMode = "data" then
-- delete temporary file
delete file theFDFFile
end if
return aFDFData
end fdfToArray2
More information about the use-livecode
mailing list