Sample C# code for using Apryse SDK with interactive forms (also known as AcroForms). Capabilities include programatically creating new fields and widget annotations, form filling, modifying existing field values, form templating, and flattening form fields. Learn more about our UWP SDK and PDF Data Extraction SDK Capabilities.
1//
2// Copyright (c) 2001-2020 by PDFTron Systems Inc. All Rights Reserved.
3//
4
5using System;
6using System.IO;
7using System.Threading.Tasks;
8using Windows.Foundation;
9
10using pdftron.PDF;
11using pdftron.SDF;
12
13using PDFNetUniversalSamples.ViewModels;
14using System.Collections.Generic;
15using pdftron.PDF.Annots;
16
17namespace PDFNetSamples
18{
19 public sealed class InteractiveFormsTest : Sample
20 {
21 public InteractiveFormsTest() :
22 base("InteractiveForms", "The sample illustrates some basic PDFNet capabilities related to interactive forms (also known as AcroForms).")
23 {
24 }
25
26 public override IAsyncAction RunAsync()
27 {
28 return Task.Run(new System.Action(async () => {
29 WriteLine("--------------------------------");
30 WriteLine("Starting InteractiveForms Test...");
31 WriteLine("--------------------------------\n");
32
33 // The vector used to store the name and count of all fields.
34 // This is used later on to clone the fields
35 Dictionary<string, int> fieldNames = new Dictionary<string, int>();
36 bool error = false;
37
38 //----------------------------------------------------------------------------------
39 // Example 1: Programatically create new Form Fields and Widget Annotations.
40 //----------------------------------------------------------------------------------
41 try
42 {
43 PDFDoc document = new PDFDoc();
44
45 // Create a blank new page and add some form fields.
46 Page blankPage = document.PageCreate();
47
48 // Text Widget Creation
49 // Create an empty text widget with black text.
50 TextWidget text1 = TextWidget.Create(document, new pdftron.PDF.Rect(110, 700, 380, 730));
51 text1.SetText("Basic Text Field");
52 text1.RefreshAppearance();
53 blankPage.AnnotPushBack(text1);
54 // Create a vertical text widget with blue text and a yellow background.
55 TextWidget text2 = TextWidget.Create(document, new pdftron.PDF.Rect(50, 400, 90, 730));
56 text2.SetRotation(90);
57 // Set the text content.
58 text2.SetText(" ****Lucky Stars!****");
59 // Set the font type, text color, font size, border color and background color.
60 text2.SetFont(Font.Create(document, FontStandardType1Font.e_helvetica_oblique));
61 text2.SetFontSize(28);
62 text2.SetTextColor(new ColorPt(0, 0, 1), 3);
63 text2.SetBorderColor(new ColorPt(0, 0, 0), 3);
64 text2.SetBackgroundColor(new ColorPt(1, 1, 0), 3);
65 text2.RefreshAppearance();
66 // Add the annotation to the page.
67 blankPage.AnnotPushBack(text2);
68 // Create two new text widget with Field names employee.name.first and employee.name.last
69 // This logic shows how these widgets can be created using either a field name string or
70 // a Field object
71 TextWidget text3 = TextWidget.Create(document, new pdftron.PDF.Rect(110, 660, 380, 690), "employee.name.first");
72 text3.SetText("Levi");
73 text3.SetFont(Font.Create(document, FontStandardType1Font.e_times_bold));
74 text3.RefreshAppearance();
75 blankPage.AnnotPushBack(text3);
76 Field employeeLastName = document.FieldCreate("employee.name.last", FieldType.e_text, "Ackerman");
77 TextWidget text4 = TextWidget.Create(document, new pdftron.PDF.Rect(110, 620, 380, 650), employeeLastName);
78 text4.SetFont(Font.Create(document, FontStandardType1Font.e_times_bold));
79 text4.RefreshAppearance();
80 blankPage.AnnotPushBack(text4);
81
82 // Signature Widget Creation (unsigned)
83 SignatureWidget signature1 = SignatureWidget.Create(document, new pdftron.PDF.Rect(110, 560, 260, 610));
84 signature1.RefreshAppearance();
85 blankPage.AnnotPushBack(signature1);
86
87 // CheckBox Widget Creation
88 // Create a check box widget that is not checked.
89 CheckBoxWidget check1 = CheckBoxWidget.Create(document, new pdftron.PDF.Rect(140, 490, 170, 520));
90 check1.RefreshAppearance();
91 blankPage.AnnotPushBack(check1);
92 // Create a check box widget that is checked.
93 CheckBoxWidget check2 = CheckBoxWidget.Create(document, new pdftron.PDF.Rect(190, 490, 250, 540), "employee.name.check1");
94 check2.SetBackgroundColor(new ColorPt(1, 1, 1), 3);
95 check2.SetBorderColor(new ColorPt(0, 0, 0), 3);
96 // Check the widget (by default it is unchecked).
97 check2.SetChecked(true);
98 check2.RefreshAppearance();
99 blankPage.AnnotPushBack(check2);
100
101 // PushButton Widget Creation
102 PushButtonWidget pushbutton1 = PushButtonWidget.Create(document, new pdftron.PDF.Rect(380, 490, 520, 540));
103 pushbutton1.SetTextColor(new ColorPt(1, 1, 1), 3);
104 pushbutton1.SetFontSize(36);
105 pushbutton1.SetBackgroundColor(new ColorPt(0, 0, 0), 3);
106 // Add a caption for the pushbutton.
107 pushbutton1.SetStaticCaptionText("PushButton");
108 pushbutton1.RefreshAppearance();
109 blankPage.AnnotPushBack(pushbutton1);
110
111 // ComboBox Widget Creation
112 ComboBoxWidget combo1 = ComboBoxWidget.Create(document, new pdftron.PDF.Rect(280, 560, 580, 610));
113 // Add options to the combobox widget.
114 combo1.AddOption("Combo Box No.1");
115 combo1.AddOption("Combo Box No.2");
116 combo1.AddOption("Combo Box No.3");
117 // Make one of the options in the combo box selected by default.
118 combo1.SetSelectedOption("Combo Box No.2");
119 combo1.SetTextColor(new ColorPt(1, 0, 0), 3);
120 combo1.SetFontSize(28);
121 combo1.RefreshAppearance();
122 blankPage.AnnotPushBack(combo1);
123
124 // ListBox Widget Creation
125 ListBoxWidget list1 = ListBoxWidget.Create(document, new pdftron.PDF.Rect(400, 620, 580, 730));
126 // Add one option to the listbox widget.
127 list1.AddOption("List Box No.1");
128 // Add multiple options to the listbox widget in a batch.
129 string[] listOptions = new string[2] { "List Box No.2", "List Box No.3" };
130 list1.AddOptions(listOptions);
131 // Select some of the options in list box as default options
132 list1.SetSelectedOptions(listOptions);
133 // Enable list box to have multi-select when editing.
134 list1.GetField().SetFlag(FieldFlag.e_multiselect, true);
135 list1.SetFont(Font.Create(document, FontStandardType1Font.e_times_italic));
136 list1.SetTextColor(new ColorPt(1, 0, 0), 3);
137 list1.SetFontSize(28);
138 list1.SetBackgroundColor(new ColorPt(1, 1, 1), 3);
139 list1.RefreshAppearance();
140 blankPage.AnnotPushBack(list1);
141
142 // RadioButton Widget Creation
143 // Create a radio button group and add three radio buttons in it.
144 RadioButtonGroup radioGroup = RadioButtonGroup.Create(document, "RadioGroup");
145 RadioButtonWidget radioButton1 = radioGroup.Add(new pdftron.PDF.Rect(140, 410, 190, 460));
146 radioButton1.SetBackgroundColor(new ColorPt(1, 1, 0), 3);
147 radioButton1.RefreshAppearance();
148 RadioButtonWidget radiobutton2 = radioGroup.Add(new pdftron.PDF.Rect(310, 410, 360, 460));
149 radiobutton2.SetBackgroundColor(new ColorPt(0, 1, 0), 3);
150 radiobutton2.RefreshAppearance();
151 RadioButtonWidget radiobutton3 = radioGroup.Add(new pdftron.PDF.Rect(480, 410, 530, 460));
152 // Enable the third radio button. By default the first one is selected
153 radiobutton3.EnableButton();
154 radiobutton3.SetBackgroundColor(new ColorPt(0, 1, 1), 3);
155 radiobutton3.RefreshAppearance();
156 radioGroup.AddGroupButtonsToPage(blankPage);
157
158 // Custom push button annotation creation
159 PushButtonWidget customPushButton1 = PushButtonWidget.Create(document, new pdftron.PDF.Rect(260, 320, 360, 360));
160 // Set the annotation appearance.
161 customPushButton1.SetAppearance(CreateCustomButtonAppearance(document, false), AnnotAnnotationState.e_normal);
162 // Create 'SubmitForm' action. The action will be linked to the button.
163 FileSpec url = FileSpec.CreateURL(document.GetSDFDoc(), "http://www.pdftron.com");
164 pdftron.PDF.Action buttonAction = pdftron.PDF.Action.CreateSubmitForm(url);
165 // Associate the above action with 'Down' event in annotations action dictionary.
166 Obj annotAction = customPushButton1.GetSDFObj().PutDict("AA");
167 annotAction.Put("D", buttonAction.GetSDFObj());
168 blankPage.AnnotPushBack(customPushButton1);
169
170 // Add the page as the last page in the document.
171 document.PagePushBack(blankPage);
172
173 // If you are not satisfied with the look of default auto-generated appearance
174 // streams you can delete "AP" entry from the Widget annotation and set
175 // "NeedAppearances" flag in AcroForm dictionary:
176 // doc.GetAcroForm().PutBool("NeedAppearances", true);
177 // This will force the viewer application to auto-generate new appearance streams
178 // every time the document is opened.
179 //
180 // Alternatively you can generate custom annotation appearance using ElementWriter
181 // and then set the "AP" entry in the widget dictionary to the new appearance
182 // stream.
183 //
184 // Yet another option is to pre-populate field entries with dummy text. When
185 // you edit the field values using PDFNet the new field appearances will match
186 // the old ones.
187 document.RefreshFieldAppearances();
188
189 await document.SaveAsync(Path.Combine(OutputPath, "forms_test1.pdf"), 0);
190 await AddFileToOutputList(Path.Combine(OutputPath, "forms_test1.pdf")).ConfigureAwait(false);
191
192 WriteLine("Done.");
193 }
194 catch (Exception e)
195 {
196 WriteLine(GetExceptionMessage(e));
197 error = true;
198 }
199
200 //----------------------------------------------------------------------------------
201 // Example 2:
202 // Fill-in forms / Modify values of existing fields.
203 // Traverse all form fields in the document (and print out their names).
204 // Search for specific fields in the document.
205 //----------------------------------------------------------------------------------
206 try
207 {
208 PDFDoc document = new PDFDoc(Path.Combine(OutputPath, "forms_test1.pdf"));
209 document.InitSecurityHandler();
210
211 FieldIterator iterator;
212 Field field;
213 for (iterator = document.GetFieldIterator(); iterator.HasNext(); iterator.Next())
214 {
215 field = iterator.Current();
216 string currentFieldName = field.GetName();
217 // Add one to the count for this field name for later processing
218 fieldNames[currentFieldName] = (fieldNames.ContainsKey(currentFieldName) ? fieldNames[currentFieldName] + 1 : 1);
219
220 WriteLine("Field name: " + field.GetName());
221 WriteLine("Field partial name: " + field.GetPartialName());
222 string stringValue = field.GetValueAsString();
223
224 Write("Field type: ");
225 FieldType type = field.GetType();
226 switch (type)
227 {
228 case FieldType.e_button:
229 WriteLine("Button");
230 break;
231 case FieldType.e_radio:
232 WriteLine("Radio button: Value = " + stringValue);
233 break;
234 case FieldType.e_check:
235 field.SetValue(true);
236 WriteLine("Check box: Value = " + stringValue);
237 break;
238 case FieldType.e_text:
239 {
240 WriteLine("Text");
241
242 // Edit all variable text in the document
243 string oldValue = "none";
244 if (field.GetValue() != null)
245 {
246 oldValue = field.GetValue().GetAsPDFText();
247 }
248
249 field.SetValue("This is a new value. The old one was: " + oldValue);
250 }
251 break;
252 case FieldType.e_choice:
253 WriteLine("Choice");
254 break;
255 case FieldType.e_signature:
256 WriteLine("Signature");
257 break;
258 }
259
260 WriteLine("------------------------------");
261 }
262
263 // Search for a specific field
264 field = document.GetField("employee.name.first");
265 if (field != null)
266 {
267 WriteLine("Field search for {0} was successful " + field.GetName());
268 }
269 else
270 {
271 WriteLine("Field search failed.");
272 }
273
274 // Regenerate field appearances.
275 document.RefreshFieldAppearances();
276 await document.SaveAsync(Path.Combine(OutputPath, "forms_test_edit.pdf"), 0);
277 await AddFileToOutputList(Path.Combine(OutputPath, "forms_test_edit.pdf")).ConfigureAwait(false);
278 WriteLine("Done.");
279 }
280 catch (Exception e)
281 {
282 WriteLine(GetExceptionMessage(e));
283 error = true;
284 }
285
286 //----------------------------------------------------------------------------------
287 // Sample: Form templating
288 // Replicate pages and form data within a document. Then rename field names to make
289 // them unique.
290 //----------------------------------------------------------------------------------
291 try
292 {
293 // Sample: Copying the page with forms within the same document
294 PDFDoc document = new PDFDoc(Path.Combine(OutputPath, "forms_test1.pdf"));
295
296 document.InitSecurityHandler();
297
298 Page sourcePage = document.GetPage(1);
299 document.PagePushBack(sourcePage); // Append several copies of the second page
300 document.PagePushBack(sourcePage); // Note that forms are successfully copied
301 document.PagePushBack(sourcePage);
302 document.PagePushBack(sourcePage);
303
304 // Now we rename fields in order to make every field unique.
305 // You can use this technique for dynamic template filling where you have a 'master'
306 // form page that should be replicated, but with unique field names on every page.
307 foreach (KeyValuePair<string, int> currentField in fieldNames)
308 {
309 RenameAllFields(document, currentField.Key, currentField.Value);
310 }
311
312 await document.SaveAsync(Path.Combine(OutputPath, "forms_test1_cloned.pdf"), 0);
313 await AddFileToOutputList(Path.Combine(OutputPath, "forms_test1_cloned.pdf")).ConfigureAwait(false);
314 WriteLine("Done.");
315 }
316 catch (Exception e)
317 {
318 WriteLine(GetExceptionMessage(e));
319 error = true;
320 }
321
322 //----------------------------------------------------------------------------------
323 // Sample:
324 // Flatten all form fields in a document.
325 // Note that this sample is intended to show that it is possible to flatten
326 // individual fields. PDFNet provides a utility function PDFDoc.FlattenAnnotations()
327 // that will automatically flatten all fields.
328 //----------------------------------------------------------------------------------
329 try
330 {
331 PDFDoc document = new PDFDoc(Path.Combine(OutputPath, "forms_test1.pdf"));
332
333 document.InitSecurityHandler();
334
335 bool auto = true;
336 if (auto)
337 {
338 document.FlattenAnnotations();
339 }
340 else // Manual flattening
341 {
342 // Traverse all pages
343 PageIterator pageIterator = document.GetPageIterator();
344 for (; pageIterator.HasNext(); pageIterator.Next())
345 {
346 Page page = pageIterator.Current();
347 for (int i = page.GetNumAnnots() - 1; i >= 0; --i)
348 {
349 IAnnot annot = page.GetAnnot(i);
350 if (annot.GetAnnotType() == AnnotType.e_Widget)
351 {
352 annot.Flatten(page);
353 }
354 }
355 }
356 }
357
358 await document.SaveAsync(Path.Combine(OutputPath, "forms_test1_flattened.pdf"), 0);
359 await AddFileToOutputList(Path.Combine(OutputPath, "forms_test1_flattened.pdf")).ConfigureAwait(false);
360 WriteLine("Done.");
361 }
362 catch (Exception e)
363 {
364 WriteLine(GetExceptionMessage(e));
365 error = true;
366 }
367
368 //////////////////// End of tests. ////////////////////
369 if (error)
370 {
371 WriteLine("Tests FAILED!!!\n==========");
372 }
373 else
374 {
375 WriteLine("Tests successful.\n==========");
376 }
377
378 WriteLine("\n--------------------------------");
379 WriteLine("Done InteractiveForms Test.");
380 WriteLine("--------------------------------\n");
381 })).AsAsyncAction();
382 }
383
384 // fieldNumber has to be greater than 0.
385 static void RenameAllFields(PDFDoc document, string name, int fieldNumber = 1)
386 {
387 Field field = document.GetField(name);
388 for (int counter = 1; field != null; ++counter)
389 {
390 string fieldNewName = name;
391 int updateCount = System.Convert.ToInt32(Math.Ceiling(counter / System.Convert.ToDouble(fieldNumber)));
392 field.Rename(name + "-" + updateCount.ToString());
393 field = document.GetField(name);
394 }
395 }
396
397 static Obj CreateCustomButtonAppearance(PDFDoc document, bool buttonDown)
398 {
399 // Create a button appearance stream ------------------------------------
400 using (ElementBuilder builder = new ElementBuilder())
401 using (ElementWriter writer = new ElementWriter())
402 {
403 writer.Begin(document.GetSDFDoc());
404
405 // Draw background
406 Element element = builder.CreateRect(0, 0, 101, 37);
407 element.SetPathFill(true);
408 element.SetPathStroke(false);
409 element.GetGState().SetFillColorSpace(ColorSpace.CreateDeviceGray());
410 element.GetGState().SetFillColor(new ColorPt(0.75, 0.0, 0.0));
411 writer.WriteElement(element);
412
413 // Draw 'Submit' text
414 writer.WriteElement(builder.CreateTextBegin());
415
416 element = builder.CreateTextRun("Submit", Font.Create(document, FontStandardType1Font.e_helvetica_bold), 12);
417 element.GetGState().SetFillColor(new ColorPt(0, 0, 0));
418
419 if (buttonDown)
420 {
421 element.SetTextMatrix(1, 0, 0, 1, 33, 10);
422 }
423 else
424 {
425 element.SetTextMatrix(1, 0, 0, 1, 30, 13);
426 }
427
428 writer.WriteElement(element);
429 writer.WriteElement(builder.CreateTextEnd());
430
431 Obj buttonAppearanceStream = writer.End();
432
433 // Set the bounding box
434 buttonAppearanceStream.PutRect("BBox", 0, 0, 101, 37);
435 buttonAppearanceStream.PutName("Subtype", "Form");
436 return buttonAppearanceStream;
437 }
438 }
439 }
440}
Did you find this helpful?
Trial setup questions?
Ask experts on DiscordNeed other help?
Contact SupportPricing or product questions?
Contact Sales