FDF

Sample C++ code for using Apryse SDK to programmatically merge forms data with the PDF in order to fill forms, or to extract form field data from the PDF. Apryse SDK has full support for Forms Data Format (FDF). Learn more about our Server SDK and PDF Data Extraction SDK Capabilities.

1//---------------------------------------------------------------------------------------
2// Copyright (c) 2001-2024 by Apryse Software Inc. All Rights Reserved.
3// Consult legal.txt regarding legal and license information.
4//---------------------------------------------------------------------------------------
5
6#include <PDF/PDFNet.h>
7#include <PDF/PDFDoc.h>
8#include <PDF/Field.h>
9#include <FDF/FDFDoc.h>
10#include <FDF/FDFField.h>
11#include <iostream>
12#include "../../LicenseKey/CPP/LicenseKey.h"
13
14using namespace std;
15using namespace pdftron;
16using namespace SDF;
17using namespace FDF;
18using namespace PDF;
19
20//---------------------------------------------------------------------------------------
21// PDFNet includes a full support for FDF (Forms Data Format) and capability to merge/extract
22// forms data (FDF) with/from PDF. This sample illustrates basic FDF merge/extract functionality
23// available in PDFNet.
24//---------------------------------------------------------------------------------------
25int main(int argc, char *argv[])
26{
27 int ret = 0;
28 PDFNet::Initialize(LicenseKey);
29
30 // Relative path to the folder containing test files.
31 string input_path = "../../TestFiles/";
32 string output_path = "../../TestFiles/Output/";
33
34
35 // Example 1)
36 // Iterate over all form fields in the document. Display all field names.
37 try
38 {
39 PDFDoc doc((input_path + "form1.pdf").c_str());
40 doc.InitSecurityHandler();
41
42 for(FieldIterator itr = doc.GetFieldIterator(); itr.HasNext(); itr.Next())
43 {
44 cout << "Field name: " << itr.Current().GetName() << endl;
45 cout << "Field partial name: " << itr.Current().GetPartialName() << endl;
46
47 cout << "Field type: ";
48 Field::Type type = itr.Current().GetType();
49 switch(type)
50 {
51 case Field::e_button: cout << "Button" << endl; break;
52 case Field::e_check: cout << "Check" << endl; break;
53 case Field::e_radio: cout << "Radio" << endl; break;
54 case Field::e_text: cout << "Text" << endl; break;
55 case Field::e_choice: cout << "Choice" << endl; break;
56 case Field::e_signature: cout << "Signature" << endl; break;
57 case Field::e_null: cout << "Null" << endl; break;
58 }
59
60 cout << "------------------------------" << endl;
61 }
62
63 cout << "Done." << endl;
64 }
65 catch(Common::Exception& e)
66 {
67 cout << e << endl;
68 ret = 1;
69 }
70 catch(...)
71 {
72 cout << "Unknown Exception" << endl;
73 ret = 1;
74 }
75
76
77 // Example 2) Import XFDF into FDF, then merge data from FDF into PDF
78 try
79 {
80 // XFDF to FDF
81 // form fields
82 cout << "Import form field data from XFDF to FDF." << endl;
83
84 FDFDoc fdf_doc1(FDFDoc::CreateFromXFDF((input_path + "form1_data.xfdf").c_str()));
85 fdf_doc1.Save((output_path + "form1_data.fdf").c_str());
86
87 // annotations
88 cout << "Import annotations from XFDF to FDF." << endl;
89
90 FDFDoc fdf_doc2(FDFDoc::CreateFromXFDF((input_path + "form1_annots.xfdf").c_str()));
91 fdf_doc2.Save((output_path + "form1_annots.fdf").c_str());
92
93 // FDF to PDF
94 // form fields
95 cout << "Merge form field data from FDF." << endl;
96
97 PDFDoc doc((input_path + "form1.pdf").c_str());
98 doc.InitSecurityHandler();
99 doc.FDFMerge(fdf_doc1);
100
101 // Refreshing missing appearances is not required here, but is recommended to make them
102 // visible in PDF viewers with incomplete annotation viewing support. (such as Chrome)
103 doc.RefreshAnnotAppearances();
104
105 doc.Save((output_path + "form1_filled.pdf").c_str(), SDFDoc::e_linearized, 0);
106
107 // annotations
108 cout << "Merge annotations from FDF." << endl;
109
110 doc.FDFMerge(fdf_doc2);
111 // Refreshing missing appearances is not required here, but is recommended to make them
112 // visible in PDF viewers with incomplete annotation viewing support. (such as Chrome)
113 doc.RefreshAnnotAppearances();
114 doc.Save((output_path + "form1_filled_with_annots.pdf").c_str(), SDFDoc::e_linearized, 0);
115 cout << "Done." << endl;
116 }
117 catch (Common::Exception& e)
118 {
119 cout << e << endl;
120 ret = 1;
121 }
122 catch (...)
123 {
124 cout << "Unknown Exception" << endl;
125 ret = 1;
126 }
127
128
129 // Example 3) Extract data from PDF to FDF, then export FDF as XFDF
130 try
131 {
132 // PDF to FDF
133 PDFDoc in_doc((output_path + "form1_filled_with_annots.pdf").c_str());
134 in_doc.InitSecurityHandler();
135
136 // form fields only
137 cout << "Extract form fields data to FDF." << endl;
138
139 FDFDoc doc_fields = in_doc.FDFExtract(PDFDoc::e_forms_only);
140 doc_fields.SetPDFFileName("../form1_filled_with_annots.pdf");
141 doc_fields.Save((output_path + "form1_filled_data.fdf").c_str());
142
143 // annotations only
144 cout << "Extract annotations to FDF." << endl;
145
146 FDFDoc doc_annots = in_doc.FDFExtract(PDFDoc::e_annots_only);
147 doc_annots.SetPDFFileName("../form1_filled_with_annots.pdf");
148 doc_annots.Save((output_path + "form1_filled_annot.fdf").c_str());
149
150 // both form fields and annotations
151 cout << "Extract both form fields and annotations to FDF." << endl;
152
153 FDFDoc doc_both = in_doc.FDFExtract(PDFDoc::e_both);
154 doc_both.SetPDFFileName("../form1_filled_with_annots.pdf");
155 doc_both.Save((output_path + "form1_filled_both.fdf").c_str());
156
157 // FDF to XFDF
158 // form fields
159 cout << "Export form field data from FDF to XFDF." << endl;
160
161 doc_fields.SaveAsXFDF((output_path + "form1_filled_data.xfdf").c_str());
162
163 // annotations
164 cout << "Export annotations from FDF to XFDF." << endl;
165
166 doc_annots.SaveAsXFDF((output_path + "form1_filled_annot.xfdf").c_str());
167
168 // both form fields and annotations
169 cout << "Export both form fields and annotations from FDF to XFDF." << endl;
170
171 doc_both.SaveAsXFDF((output_path + "form1_filled_both.xfdf").c_str());
172
173 cout << "Done." << endl;
174 }
175 catch(Common::Exception& e)
176 {
177 cout << e << endl;
178 ret = 1;
179 }
180 catch(...)
181 {
182 cout << "Unknown Exception" << endl;
183 ret = 1;
184 }
185
186 // Example 4) Merge/Extract XFDF into/from PDF
187 try
188 {
189 // Merge XFDF from string
190 PDFDoc in_doc((input_path + "numbered.pdf").c_str());
191 in_doc.InitSecurityHandler();
192
193 cout << "Merge XFDF string into PDF." << endl;
194
195 string str = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?><xfdf xmlns=\"http://ns.adobe.com/xfdf\" xml:space=\"preserve\"><square subject=\"Rectangle\" page=\"0\" name=\"cf4d2e58-e9c5-2a58-5b4d-9b4b1a330e45\" title=\"user\" creationdate=\"D:20120827112326-07'00'\" date=\"D:20120827112326-07'00'\" rect=\"227.7814207650273,597.6174863387978,437.07103825136608,705.0491803278688\" color=\"#000000\" interior-color=\"#FFFF00\" flags=\"print\" width=\"1\"><popup flags=\"print,nozoom,norotate\" open=\"no\" page=\"0\" rect=\"0,792,0,792\" /></square></xfdf>";
196
197 FDFDoc fdoc(FDFDoc::CreateFromXFDF(str));
198 in_doc.FDFMerge(fdoc);
199 in_doc.Save((output_path + "numbered_modified.pdf").c_str(), SDFDoc::e_linearized, 0);
200 cout << "Merge complete." << endl;
201
202 // Extract XFDF as string
203 cout << "Extract XFDF as a string." << endl;
204
205 FDFDoc fdoc_new = in_doc.FDFExtract(PDFDoc::e_both);
206 UString XFDF_str = fdoc_new.SaveAsXFDF();
207 cout << "Extracted XFDF: " << endl;
208 cout << XFDF_str << endl;
209 cout << "Extract complete." << endl;
210 }
211 catch(Common::Exception& e)
212 {
213 cout << e << endl;
214 ret = 1;
215 }
216 catch(...)
217 {
218 cout << "Unknown Exception" << endl;
219 ret = 1;
220 }
221
222 // Example 5) Read FDF files directly
223 try
224 {
225 FDFDoc doc((output_path + "form1_filled_data.fdf").c_str());
226
227 for(FDFFieldIterator itr = doc.GetFieldIterator(); itr.HasNext(); itr.Next())
228 {
229 cout << "Field name: " << itr.Current().GetName() << endl;
230 cout << "Field partial name: " << itr.Current().GetPartialName() << endl;
231
232 cout << "------------------------------" << endl;
233 }
234
235 cout << "Done." << endl;
236 }
237 catch(Common::Exception& e)
238 {
239 cout << e << endl;
240 ret = 1;
241 }
242 catch(...)
243 {
244 cout << "Unknown Exception" << endl;
245 ret = 1;
246 }
247
248 // Example 6) Direct generation of FDF.
249 try
250 {
251 FDFDoc doc;
252 // Create new fields (i.e. key/value pairs).
253 doc.FieldCreate("Company", PDF::Field::e_text, "PDFTron Systems");
254 doc.FieldCreate("First Name", PDF::Field::e_text, "John");
255 doc.FieldCreate("Last Name", PDF::Field::e_text, "Doe");
256 // ...
257
258 // doc.SetPdfFileName("mydoc.pdf");
259
260 doc.Save((output_path + "sample_output.fdf").c_str());
261 cout << "Done. Results saved in sample_output.fdf" << endl;
262 }
263 catch(Common::Exception& e)
264 {
265 cout << e << endl;
266 ret = 1;
267 }
268 catch(...)
269 {
270 cout << "Unknown Exception" << endl;
271 ret = 1;
272 }
273
274 PDFNet::Terminate();
275 return ret;
276}

Did you find this helpful?

Trial setup questions?

Ask experts on Discord

Need other help?

Contact Support

Pricing or product questions?

Contact Sales