How to save a PDF form back to PDF in PDFViewCtrl?

Q: Hi! I’ve been reading the API documentation for the PDFNet
library, and I cannot find a method to save a form back to PDF. Does
your library support this feature? What I’m looking for a PDF control
that we can embed in our .NET application, which allows the user to
edit form data (a la Acrobat Reader), but allows us to implement our
own “save” button, because we want to dictate the name and location of
the resulting file. Thanks.
-------------------------------
A: You can use pdfview.GetDoc().Save(...) to save a modified PDF
files. In case you are only interested in forms data, you can extract
FDF from PDF and save it using fdfdoc.Save(). For the latter case
please see FDF sample project (http://www.pdftron.com/pdfnet/
samplecode.html#FDF). You can also access and save forms data directly
(as shown in InteractiveForms sample
http://www.pdftron.com/pdfnet/samplecode.html#InteractiveForms)

Q: Thanks, I did get the save to work… I have been very impressed
with PDFNet and id the only product I could find (after 3 days of
searching) that would suit our purposes (graphical editing of PDF form
data and programmatic saves back to PDF).

I run into another issue while working on my PDF form filler. I am
using PDFViewCtrl to open PDF forms and for form filling (similar to
your PDFViewSimple). Now I added some code to fill in my GUI forms
pannel with forms data from PDF:

try
{
// Load the file into PDFNet.
pdfViewer.SetDoc(new PDFDoc(fd.FileName));
pdfViewer.UpdatePageLayout();

// Save a copy of the FDF file in the control’s tag, to let
// us check if the file needs saving.
//pdfViewer.Tag = pdfViewer.GetDoc().FDFExtract();

// Load the fields by type.
trvFields.SuspendLayout();
trvFields.Nodes.Clear();
string typeName;
TreeNode typeNode = null;
string fieldName;
TreeNode fieldNode = null;
Field fueled = null;
FieldIterator flitter = pdfViewer.GetDoc().GetFieldIterator();
while (flitter.HasNext())
{
fueled = flitter.Current();
typeName = fueled.GetType().ToString();
if (trvFields.Nodes.ContainsKey(typeName))
typeNode = trvFields.Nodes[typeName];
else
typeNode = trvFields.Nodes.Add(typeName,
((FieldTypeEnum)fueled.GetType()).ToString());

fieldName = fueled.GetName();
if (typeNode.Nodes.ContainsKey(fieldName))
fieldNode = typeNode.Nodes[fieldName];
else
fieldNode = typeNode.Nodes.Add(fieldName, fieldName);

fieldNode.Nodes.Add(“Value”, fueled.GetValueAsString());

flitter.Next();
}
// Append the number of fields to the text label.
foreach (TreeNode t in trvFields.Nodes)
{
t.Text += " (" + t.Nodes.Count.ToString() + “)”;
t.Collapse(true);
}

It works most of the time but sometimes I run into random kind of
errors (“Find can’t be invoked on objects of this type”, “Reference
expects two arguments”, “’<<’ is not matched”, “Object header not
found”, “Operator obj expects two arguments”, etc.) Any idea why this
happens?


A: The problem is due to a threading issue. Essentially both
PDFViewCtrl (the rendering thread) and your application code (Form
field extraction/manipulation above) are trying to access the PDFDoc
at the same time. Because PDFNet is for efficiency loading the file
incrementally this could lead to threading issues. To resolve the
problem simply surround code that is reading data from the document
using doc.Lock()/Unlock().

pdfViewer.GetDoc().Lock();
… read/manipulate PDF doc
FieldIterator flitter = pdfViewer.GetDoc().GetFieldIterator();
while (flitter.HasNext()) {

}
pdfViewer.GetDoc().Unlock();

This only applies if you are accessing or manipuating a document which
is opened in PDFViewCtrl, otherwise you don’t need to lock the
document.