Sample Java 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 Android SDK and PDF Data Extraction SDK Capabilities.
1//---------------------------------------------------------------------------------------
2// Copyright (c) 2001-2019 by PDFTron Systems Inc. All Rights Reserved.
3// Consult legal.txt regarding legal and license information.
4//---------------------------------------------------------------------------------------
5
6package com.pdftron.android.pdfnetsdksamples.samples;
7
8import com.pdftron.android.pdfnetsdksamples.OutputListener;
9import com.pdftron.android.pdfnetsdksamples.PDFNetSample;
10import com.pdftron.android.pdfnetsdksamples.R;
11import com.pdftron.android.pdfnetsdksamples.util.Utils;
12import com.pdftron.common.PDFNetException;
13import com.pdftron.pdf.Action;
14import com.pdftron.pdf.Annot;
15import com.pdftron.pdf.ColorPt;
16import com.pdftron.pdf.ColorSpace;
17import com.pdftron.pdf.Element;
18import com.pdftron.pdf.ElementBuilder;
19import com.pdftron.pdf.ElementWriter;
20import com.pdftron.pdf.Field;
21import com.pdftron.pdf.FieldIterator;
22import com.pdftron.pdf.FileSpec;
23import com.pdftron.pdf.Font;
24import com.pdftron.pdf.PDFDoc;
25import com.pdftron.pdf.Page;
26import com.pdftron.pdf.PageIterator;
27import com.pdftron.pdf.Rect;
28import com.pdftron.pdf.annots.CheckBoxWidget;
29import com.pdftron.pdf.annots.ComboBoxWidget;
30import com.pdftron.pdf.annots.ListBoxWidget;
31import com.pdftron.pdf.annots.PushButtonWidget;
32import com.pdftron.pdf.annots.RadioButtonGroup;
33import com.pdftron.pdf.annots.RadioButtonWidget;
34import com.pdftron.pdf.annots.SignatureWidget;
35import com.pdftron.pdf.annots.TextWidget;
36import com.pdftron.sdf.Obj;
37import com.pdftron.sdf.SDFDoc;
38
39import java.util.ArrayList;
40import java.util.HashMap;
41import java.util.Map;
42
43//---------------------------------------------------------------------------------------
44//This sample illustrates basic PDFNet capabilities related to interactive
45//forms (also known as AcroForms).
46//---------------------------------------------------------------------------------------
47
48public class InteractiveFormsTest extends PDFNetSample {
49
50 private static OutputListener mOutputListener;
51
52 private static ArrayList<String> mFileList = new ArrayList<>();
53
54 public InteractiveFormsTest() {
55 setTitle(R.string.sample_interactiveforms_title);
56 setDescription(R.string.sample_interactiveforms_description);
57 }
58
59 @Override
60 public void run(OutputListener outputListener) {
61 super.run(outputListener);
62 mOutputListener = outputListener;
63 mFileList.clear();
64 printHeader(outputListener);
65
66 // string input_path = "../../TestFiles/";
67
68 // The vector used to store the name and count of all fields.
69 // This is used later on to clone the fields
70 Map<String, Integer> field_names = new HashMap<String, Integer>();
71
72 //----------------------------------------------------------------------------------
73 // Example 1: Programatically create new Form Fields and Widget Annotations.
74 //----------------------------------------------------------------------------------
75 try (PDFDoc doc = new PDFDoc()) {
76 // Create a blank new page and add some form fields.
77 Page blank_page = doc.pageCreate();
78
79 // Text Widget Creation
80 // Create an empty text widget with black text.
81 TextWidget text1 = TextWidget.create(doc, new Rect(110, 700, 380, 730));
82 text1.setText("Basic Text Field");
83 text1.refreshAppearance();
84 blank_page.annotPushBack(text1);
85 // Create a vertical text widget with blue text and a yellow background.
86 TextWidget text2 = TextWidget.create(doc, new Rect(50, 400, 90, 730));
87 text2.setRotation(90);
88 // Set the text content.
89 text2.setText(" ****Lucky Stars!****");
90 // Set the font type, text color, font size, border color and background color.
91 text2.setFont(Font.create(doc, Font.e_helvetica_oblique));
92 text2.setFontSize(28);
93 text2.setTextColor(new ColorPt(0, 0, 1), 3);
94 text2.setBorderColor(new ColorPt(0, 0, 0), 3);
95 text2.setBackgroundColor(new ColorPt(1, 1, 0), 3);
96 text2.refreshAppearance();
97 // Add the annotation to the page.
98 blank_page.annotPushBack(text2);
99 // Create two new text widget with Field names employee.name.first and employee.name.last
100 // This logic shows how these widgets can be created using either a field name string or
101 // a Field object
102 TextWidget text3 = TextWidget.create(doc, new Rect(110, 660, 380, 690), "employee.name.first");
103 text3.setText("Levi");
104 text3.setFont(Font.create(doc, Font.e_times_bold));
105 text3.refreshAppearance();
106 blank_page.annotPushBack(text3);
107 Field emp_last_name = doc.fieldCreate("employee.name.last", Field.e_text, "Ackerman");
108 TextWidget text4 = TextWidget.create(doc, new Rect(110, 620, 380, 650), emp_last_name);
109 text4.setFont(Font.create(doc, Font.e_times_bold));
110 text4.refreshAppearance();
111 blank_page.annotPushBack(text4);
112
113 // Signature Widget Creation (unsigned)
114 SignatureWidget signature1 = SignatureWidget.create(doc, new Rect(110, 560, 260, 610));
115 signature1.refreshAppearance();
116 blank_page.annotPushBack(signature1);
117
118 // CheckBox Widget Creation
119 // Create a check box widget that is not checked.
120 CheckBoxWidget check1 = CheckBoxWidget.create(doc, new Rect(140, 490, 170, 520));
121 check1.refreshAppearance();
122 blank_page.annotPushBack(check1);
123 // Create a check box widget that is checked.
124 CheckBoxWidget check2 = CheckBoxWidget.create(doc, new Rect(190, 490, 250, 540), "employee.name.check1");
125 check2.setBackgroundColor(new ColorPt(1, 1, 1), 3);
126 check2.setBorderColor(new ColorPt(0, 0, 0), 3);
127 // Check the widget (by default it is unchecked).
128 check2.setChecked(true);
129 check2.refreshAppearance();
130 blank_page.annotPushBack(check2);
131
132 // PushButton Widget Creation
133 PushButtonWidget pushbutton1 = PushButtonWidget.create(doc, new Rect(380, 490, 520, 540));
134 pushbutton1.setTextColor(new ColorPt(1, 1, 1), 3);
135 pushbutton1.setFontSize(36);
136 pushbutton1.setBackgroundColor(new ColorPt(0, 0, 0), 3);
137 // Add a caption for the pushbutton.
138 pushbutton1.setStaticCaptionText("PushButton");
139 pushbutton1.refreshAppearance();
140 blank_page.annotPushBack(pushbutton1);
141
142 // ComboBox Widget Creation
143 ComboBoxWidget combo1 = ComboBoxWidget.create(doc, new Rect(280, 560, 580, 610));
144 // Add options to the combobox widget.
145 combo1.addOption("Combo Box No.1");
146 combo1.addOption("Combo Box No.2");
147 combo1.addOption("Combo Box No.3");
148 // Make one of the options in the combo box selected by default.
149 combo1.setSelectedOption("Combo Box No.2");
150 combo1.setTextColor(new ColorPt(1, 0, 0), 3);
151 combo1.setFontSize(28);
152 combo1.refreshAppearance();
153 blank_page.annotPushBack(combo1);
154
155 // ListBox Widget Creation
156 ListBoxWidget list1 = ListBoxWidget.create(doc, new Rect(400, 620, 580, 730));
157 // Add one option to the listbox widget.
158 list1.addOption("List Box No.1");
159 // Add multiple options to the listbox widget in a batch.
160 String[] list_options = new String[] { "List Box No.2", "List Box No.3" };
161 list1.addOptions(list_options);
162 // Select some of the options in list box as default options
163 list1.setSelectedOptions(list_options);
164 // Enable list box to have multi-select when editing.
165 list1.getField().setFlag(Field.e_multiselect, true);
166 list1.setFont(Font.create(doc,Font.e_times_italic));
167 list1.setTextColor(new ColorPt(1, 0, 0), 3);
168 list1.setFontSize(28);
169 list1.setBackgroundColor(new ColorPt(1, 1, 1), 3);
170 list1.refreshAppearance();
171 blank_page.annotPushBack(list1);
172
173 // RadioButton Widget Creation
174 // Create a radio button group and add three radio buttons in it.
175 RadioButtonGroup radio_group = RadioButtonGroup.create(doc, "RadioGroup");
176 RadioButtonWidget radiobutton1 = radio_group.add(new Rect(140, 410, 190, 460));
177 radiobutton1.setBackgroundColor(new ColorPt(1, 1, 0), 3);
178 radiobutton1.refreshAppearance();
179 RadioButtonWidget radiobutton2 = radio_group.add(new Rect(310, 410, 360, 460));
180 radiobutton2.setBackgroundColor(new ColorPt(0, 1, 0), 3);
181 radiobutton2.refreshAppearance();
182 RadioButtonWidget radiobutton3 = radio_group.add(new Rect(480, 410, 530, 460));
183 // Enable the third radio button. By default the first one is selected
184 radiobutton3.enableButton();
185 radiobutton3.setBackgroundColor(new ColorPt(0, 1, 1), 3);
186 radiobutton3.refreshAppearance();
187 radio_group.addGroupButtonsToPage(blank_page);
188
189 // Custom push button annotation creation
190 PushButtonWidget custom_pushbutton1 = PushButtonWidget.create(doc, new Rect(260, 320, 360, 360));
191 // Set the annotation appearance.
192 custom_pushbutton1.setAppearance(createCustomButtonAppearance(doc, false), Annot.e_normal);
193 // Create 'SubmitForm' action. The action will be linked to the button.
194 FileSpec url = FileSpec.createURL(doc, "http://www.pdftron.com");
195 Action button_action = Action.createSubmitForm(url);
196 // Associate the above action with 'Down' event in annotations action dictionary.
197 Obj annot_action = custom_pushbutton1.getSDFObj().putDict("AA");
198 annot_action.put("D", button_action.getSDFObj());
199 blank_page.annotPushBack(custom_pushbutton1);
200
201 // Add the page as the last page in the document.
202 doc.pagePushBack(blank_page);
203
204 // If you are not satisfied with the look of default auto-generated appearance
205 // streams you can delete "AP" entry from the Widget annotation and set
206 // "NeedAppearances" flag in AcroForm dictionary:
207 // doc.GetAcroForm().PutBool("NeedAppearances", true);
208 // This will force the viewer application to auto-generate new appearance streams
209 // every time the document is opened.
210 //
211 // Alternatively you can generate custom annotation appearance using ElementWriter
212 // and then set the "AP" entry in the widget dictionary to the new appearance
213 // stream.
214 //
215 // Yet another option is to pre-populate field entries with dummy text. When
216 // you edit the field values using PDFNet the new field appearances will match
217 // the old ones.
218
219 //doc.GetAcroForm().Put("NeedAppearances", new Bool(true));
220 doc.refreshFieldAppearances();
221
222 doc.save(Utils.createExternalFile("forms_test1.pdf", mFileList).getAbsolutePath(), SDFDoc.SaveMode.NO_FLAGS, null);
223 mOutputListener.println("Done.");
224 } catch (Exception e) {
225 mOutputListener.printError(e.getStackTrace());
226 }
227
228 //----------------------------------------------------------------------------------
229 // Example 2:
230 // Fill-in forms / Modify values of existing fields.
231 // Traverse all form fields in the document (and print out their names).
232 // Search for specific fields in the document.
233 //----------------------------------------------------------------------------------
234 try (PDFDoc doc = new PDFDoc((Utils.createExternalFile("forms_test1.pdf", mFileList).getAbsolutePath()))) {
235 doc.initSecurityHandler();
236
237 FieldIterator itr = doc.getFieldIterator();
238 while (itr.hasNext()) {
239 Field current = itr.next();
240 String cur_field_name = current.getName();
241 // Add one to the count for this field name for later processing
242 if (field_names.containsKey(cur_field_name)) {
243 field_names.put(cur_field_name, field_names.get(cur_field_name) + 1);
244 }
245 else {
246 field_names.put(cur_field_name, 1);
247 }
248
249 mOutputListener.println("Field name: " + current.getName());
250 mOutputListener.println("Field partial name: " + current.getPartialName());
251
252 mOutputListener.print("Field type: ");
253 int type = current.getType();
254 String str_val = current.getValueAsString();
255 switch (type) {
256 case Field.e_button:
257 mOutputListener.println("Button");
258 break;
259 case Field.e_radio:
260 mOutputListener.println("Radio button: Value = " + str_val);
261 break;
262 case Field.e_check:
263 current.setValue(true);
264 mOutputListener.println("Check box: Value = " + str_val);
265 break;
266 case Field.e_text: {
267 mOutputListener.println("Text");
268 // Edit all variable text in the document
269 String old_value;
270 if (current.getValue() != null) {
271 old_value = current.getValueAsString();
272 current.setValue("This is a new value. The old one was: " + old_value);
273 }
274 }
275 break;
276 case Field.e_choice:
277 mOutputListener.println("Choice");
278 break;
279 case Field.e_signature:
280 mOutputListener.println("Signature");
281 break;
282 }
283
284 mOutputListener.println("------------------------------");
285 }
286
287 // Search for a specific field
288 Field f = doc.getField("employee.name.first");
289 if (f != null) {
290 mOutputListener.println("Field search for " + f.getName() + " was successful");
291 } else {
292 mOutputListener.println("Field search failed");
293 }
294
295 // Regenerate field appearances.
296 doc.refreshFieldAppearances();
297 doc.save((Utils.createExternalFile("forms_test_edit.pdf", mFileList).getAbsolutePath()), SDFDoc.SaveMode.NO_FLAGS, null);
298 mOutputListener.println("Done.");
299 } catch (Exception e) {
300 mOutputListener.printError(e.getStackTrace());
301 }
302
303 //----------------------------------------------------------------------------------
304 // Sample: Form templating
305 // Replicate pages and form data within a document. Then rename field names to make
306 // them unique.
307 //----------------------------------------------------------------------------------
308 try (PDFDoc doc = new PDFDoc((Utils.createExternalFile("forms_test1.pdf", mFileList).getAbsolutePath()))) {
309 // Sample: Copying the page with forms within the same document
310 doc.initSecurityHandler();
311
312 Page src_page = (Page) (doc.getPage(1));
313 doc.pagePushBack(src_page); // Append several copies of the first page
314 doc.pagePushBack(src_page); // Note that forms are successfully copied
315 doc.pagePushBack(src_page);
316 doc.pagePushBack(src_page);
317
318 // Now we rename fields in order to make every field unique.
319 // You can use this technique for dynamic template filling where you have a 'master'
320 // form page that should be replicated, but with unique field names on every page.
321 for (String cur_field : field_names.keySet()) {
322 renameAllFields(doc, cur_field, field_names.get(cur_field));
323 }
324
325 doc.save(Utils.createExternalFile("forms_test1_cloned.pdf", mFileList).getAbsolutePath(), SDFDoc.SaveMode.NO_FLAGS, null);
326 mOutputListener.println("Done.");
327 } catch (Exception e) {
328 mOutputListener.printError(e.getStackTrace());
329 }
330
331 //----------------------------------------------------------------------------------
332 // Sample:
333 // Flatten all form fields in a document.
334 // Note that this sample is intended to show that it is possible to flatten
335 // individual fields. PDFNet provides a utility function PDFDoc.flattenAnnotations()
336 // that will automatically flatten all fields.
337 //----------------------------------------------------------------------------------
338 try (PDFDoc doc = new PDFDoc((Utils.createExternalFile("forms_test1.pdf", mFileList).getAbsolutePath()))) {
339 doc.initSecurityHandler();
340
341 // Traverse all pages
342 if (true) {
343 doc.flattenAnnotations();
344 } else // Manual flattening
345 {
346
347 for (PageIterator pitr = doc.getPageIterator(); pitr.hasNext(); ) {
348 Page page = pitr.next();
349 for (int i = page.getNumAnnots() - 1; i >= 0; --i) {
350 Annot annot = page.getAnnot(i);
351 if (annot.getType() == Annot.e_Widget)
352 {
353 annot.flatten(page);
354 }
355 }
356 }
357 }
358
359 doc.save(Utils.createExternalFile("forms_test1_flattened.pdf", mFileList).getAbsolutePath(), SDFDoc.SaveMode.NO_FLAGS, null);
360 mOutputListener.println("Done.");
361 } catch (Exception e) {
362 mOutputListener.printError(e.getStackTrace());
363 }
364
365 for (String file : mFileList) {
366 addToFileList(file);
367 }
368 printFooter(outputListener);
369 }
370
371 // field_nums has to be greater than 0.
372 static void renameAllFields(PDFDoc doc, String name, int field_nums) throws PDFNetException {
373 FieldIterator itr = doc.getFieldIterator(name);
374 for (int counter = 1; itr.hasNext(); itr = doc.getFieldIterator(name), ++counter) {
375 Field f = itr.next();
376 int update_count = (int)java.lang.Math.ceil(counter/(double)field_nums);
377 f.rename(name + "-" + update_count);
378 }
379 }
380
381 static Obj createCustomButtonAppearance(PDFDoc doc, boolean button_down) throws PDFNetException {
382 // Create a button appearance stream ------------------------------------
383 ElementBuilder build = new ElementBuilder();
384 ElementWriter writer = new ElementWriter();
385 writer.begin(doc);
386
387 // Draw background
388 Element element = build.createRect(0, 0, 101, 37);
389 element.setPathFill(true);
390 element.setPathStroke(false);
391 element.getGState().setFillColorSpace(ColorSpace.createDeviceGray());
392 element.getGState().setFillColor(new ColorPt(0.75, 0, 0));
393 writer.writeElement(element);
394
395 // Draw 'Submit' text
396 writer.writeElement(build.createTextBegin());
397 {
398 String text = "Submit";
399 element = build.createTextRun(text, Font.create(doc, Font.e_helvetica_bold), 12);
400 element.getGState().setFillColor(new ColorPt(0, 0, 0));
401
402 if (button_down)
403 element.setTextMatrix(1, 0, 0, 1, 33, 10);
404 else
405 element.setTextMatrix(1, 0, 0, 1, 30, 13);
406 writer.writeElement(element);
407 }
408 writer.writeElement(build.createTextEnd());
409
410 Obj stm = writer.end();
411
412 // Set the bounding box
413 stm.putRect("BBox", 0, 0, 101, 37);
414 stm.putName("Subtype", "Form");
415 return stm;
416 }
417
418}
1//---------------------------------------------------------------------------------------
2// Copyright (c) 2001-2019 by PDFTron Systems Inc. All Rights Reserved.
3// Consult legal.txt regarding legal and license information.
4//---------------------------------------------------------------------------------------
5
6package com.pdftron.android.pdfnetsdksamples.samples
7
8import com.pdftron.android.pdfnetsdksamples.OutputListener
9import com.pdftron.android.pdfnetsdksamples.PDFNetSample
10import com.pdftron.android.pdfnetsdksamples.R
11import com.pdftron.android.pdfnetsdksamples.util.Utils
12import com.pdftron.common.PDFNetException
13import com.pdftron.pdf.*
14import com.pdftron.pdf.annots.*
15import com.pdftron.sdf.Obj
16import com.pdftron.sdf.SDFDoc
17import java.util.*
18
19//---------------------------------------------------------------------------------------
20//This sample illustrates basic PDFNet capabilities related to interactive
21//forms (also known as AcroForms).
22//---------------------------------------------------------------------------------------
23
24class InteractiveFormsTest : PDFNetSample() {
25 init {
26 setTitle(R.string.sample_interactiveforms_title)
27 setDescription(R.string.sample_interactiveforms_description)
28 }
29
30 override fun run(outputListener: OutputListener?) {
31 super.run(outputListener)
32 mOutputListener = outputListener
33 mFileList.clear()
34 printHeader(outputListener!!)
35
36 // string input_path = "../../TestFiles/";
37
38 // The vector used to store the name and count of all fields.
39 // This is used later on to clone the fields
40 val field_names = HashMap<String, Int>()
41
42 //----------------------------------------------------------------------------------
43 // Example 1: Programatically create new Form Fields and Widget Annotations.
44 //----------------------------------------------------------------------------------
45 try {
46 PDFDoc().use { doc ->
47 // Create a blank new page and add some form fields.
48 val blank_page = doc.pageCreate()
49
50 // Text Widget Creation
51 // Create an empty text widget with black text.
52 val text1 = TextWidget.create(doc, Rect(110.0, 700.0, 380.0, 730.0))
53 text1.text = "Basic Text Field"
54 text1.refreshAppearance()
55 blank_page.annotPushBack(text1)
56 // Create a vertical text widget with blue text and a yellow background.
57 val text2 = TextWidget.create(doc, Rect(50.0, 400.0, 90.0, 730.0))
58 text2.rotation = 90
59 // Set the text content.
60 text2.text = " ****Lucky Stars!****"
61 // Set the font type, text color, font size, border color and background color.
62 text2.font = Font.create(doc, Font.e_helvetica_oblique)
63 text2.fontSize = 28.0
64 text2.setTextColor(ColorPt(0.0, 0.0, 1.0), 3)
65 text2.setBorderColor(ColorPt(0.0, 0.0, 0.0), 3)
66 text2.setBackgroundColor(ColorPt(1.0, 1.0, 0.0), 3)
67 text2.refreshAppearance()
68 // Add the annotation to the page.
69 blank_page.annotPushBack(text2)
70 // Create two new text widget with Field names employee.name.first and employee.name.last
71 // This logic shows how these widgets can be created using either a field name string or
72 // a Field object
73 val text3 = TextWidget.create(doc, Rect(110.0, 660.0, 380.0, 690.0), "employee.name.first")
74 text3.text = "Levi"
75 text3.font = Font.create(doc, Font.e_times_bold)
76 text3.refreshAppearance()
77 blank_page.annotPushBack(text3)
78 val emp_last_name = doc.fieldCreate("employee.name.last", Field.e_text, "Ackerman")
79 val text4 = TextWidget.create(doc, Rect(110.0, 620.0, 380.0, 650.0), emp_last_name)
80 text4.font = Font.create(doc, Font.e_times_bold)
81 text4.refreshAppearance()
82 blank_page.annotPushBack(text4)
83
84 // Signature Widget Creation (unsigned)
85 val signature1 = SignatureWidget.create(doc, Rect(110.0, 560.0, 260.0, 610.0))
86 signature1.refreshAppearance()
87 blank_page.annotPushBack(signature1)
88
89 // CheckBox Widget Creation
90 // Create a check box widget that is not checked.
91 val check1 = CheckBoxWidget.create(doc, Rect(140.0, 490.0, 170.0, 520.0))
92 check1.refreshAppearance()
93 blank_page.annotPushBack(check1)
94 // Create a check box widget that is checked.
95 val check2 = CheckBoxWidget.create(doc, Rect(190.0, 490.0, 250.0, 540.0), "employee.name.check1")
96 check2.setBackgroundColor(ColorPt(1.0, 1.0, 1.0), 3)
97 check2.setBorderColor(ColorPt(0.0, 0.0, 0.0), 3)
98 // Check the widget (by default it is unchecked).
99 check2.isChecked = true
100 check2.refreshAppearance()
101 blank_page.annotPushBack(check2)
102
103 // PushButton Widget Creation
104 val pushbutton1 = PushButtonWidget.create(doc, Rect(380.0, 490.0, 520.0, 540.0))
105 pushbutton1.setTextColor(ColorPt(1.0, 1.0, 1.0), 3)
106 pushbutton1.fontSize = 36.0
107 pushbutton1.setBackgroundColor(ColorPt(0.0, 0.0, 0.0), 3)
108 // Add a caption for the pushbutton.
109 pushbutton1.staticCaptionText = "PushButton"
110 pushbutton1.refreshAppearance()
111 blank_page.annotPushBack(pushbutton1)
112
113 // ComboBox Widget Creation
114 val combo1 = ComboBoxWidget.create(doc, Rect(280.0, 560.0, 580.0, 610.0))
115 // Add options to the combobox widget.
116 combo1.addOption("Combo Box No.1")
117 combo1.addOption("Combo Box No.2")
118 combo1.addOption("Combo Box No.3")
119 // Make one of the options in the combo box selected by default.
120 combo1.selectedOption = "Combo Box No.2"
121 combo1.setTextColor(ColorPt(1.0, 0.0, 0.0), 3)
122 combo1.fontSize = 28.0
123 combo1.refreshAppearance()
124 blank_page.annotPushBack(combo1)
125
126 // ListBox Widget Creation
127 val list1 = ListBoxWidget.create(doc, Rect(400.0, 620.0, 580.0, 730.0))
128 // Add one option to the listbox widget.
129 list1.addOption("List Box No.1")
130 // Add multiple options to the listbox widget in a batch.
131 val list_options = arrayOf("List Box No.2", "List Box No.3")
132 list1.addOptions(list_options)
133 // Select some of the options in list box as default options
134 list1.selectedOptions = list_options
135 // Enable list box to have multi-select when editing.
136 list1.field.setFlag(Field.e_multiselect, true)
137 list1.font = Font.create(doc, Font.e_times_italic)
138 list1.setTextColor(ColorPt(1.0, 0.0, 0.0), 3)
139 list1.fontSize = 28.0
140 list1.setBackgroundColor(ColorPt(1.0, 1.0, 1.0), 3)
141 list1.refreshAppearance()
142 blank_page.annotPushBack(list1)
143
144 // RadioButton Widget Creation
145 // Create a radio button group and add three radio buttons in it.
146 val radio_group = RadioButtonGroup.create(doc, "RadioGroup")
147 val radiobutton1 = radio_group.add(Rect(140.0, 410.0, 190.0, 460.0))
148 radiobutton1.setBackgroundColor(ColorPt(1.0, 1.0, 0.0), 3)
149 radiobutton1.refreshAppearance()
150 val radiobutton2 = radio_group.add(Rect(310.0, 410.0, 360.0, 460.0))
151 radiobutton2.setBackgroundColor(ColorPt(0.0, 1.0, 0.0), 3)
152 radiobutton2.refreshAppearance()
153 val radiobutton3 = radio_group.add(Rect(480.0, 410.0, 530.0, 460.0))
154 // Enable the third radio button. By default the first one is selected
155 radiobutton3.enableButton()
156 radiobutton3.setBackgroundColor(ColorPt(0.0, 1.0, 1.0), 3)
157 radiobutton3.refreshAppearance()
158 radio_group.addGroupButtonsToPage(blank_page)
159
160 // Custom push button annotation creation
161 val custom_pushbutton1 = PushButtonWidget.create(doc, Rect(260.0, 320.0, 360.0, 360.0))
162 // Set the annotation appearance.
163 custom_pushbutton1.setAppearance(createCustomButtonAppearance(doc, false), Annot.e_normal)
164 // Create 'SubmitForm' action. The action will be linked to the button.
165 val url = FileSpec.createURL(doc, "http://www.pdftron.com")
166 val button_action = Action.createSubmitForm(url)
167 // Associate the above action with 'Down' event in annotations action dictionary.
168 val annot_action = custom_pushbutton1.sdfObj.putDict("AA")
169 annot_action.put("D", button_action.sdfObj)
170 blank_page.annotPushBack(custom_pushbutton1)
171
172 // Add the page as the last page in the document.
173 doc.pagePushBack(blank_page)
174
175 // If you are not satisfied with the look of default auto-generated appearance
176 // streams you can delete "AP" entry from the Widget annotation and set
177 // "NeedAppearances" flag in AcroForm dictionary:
178 // doc.GetAcroForm().PutBool("NeedAppearances", true);
179 // This will force the viewer application to auto-generate new appearance streams
180 // every time the document is opened.
181 //
182 // Alternatively you can generate custom annotation appearance using ElementWriter
183 // and then set the "AP" entry in the widget dictionary to the new appearance
184 // stream.
185 //
186 // Yet another option is to pre-populate field entries with dummy text. When
187 // you edit the field values using PDFNet the new field appearances will match
188 // the old ones.
189
190 //doc.GetAcroForm().Put("NeedAppearances", new Bool(true));
191 doc.refreshFieldAppearances()
192
193 doc.save(Utils.createExternalFile("forms_test1.pdf", mFileList).absolutePath, SDFDoc.SaveMode.NO_FLAGS, null)
194 mOutputListener!!.println("Done.")
195 }
196 } catch (e: Exception) {
197 mOutputListener!!.printError(e.stackTrace)
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 PDFDoc(Utils.createExternalFile("forms_test1.pdf", mFileList).absolutePath).use { doc ->
208 doc.initSecurityHandler()
209
210 val itr = doc.fieldIterator
211 while (itr.hasNext()) {
212 val current = itr.next()!!
213 val cur_field_name = current.getName()
214 // Add one to the count for this field name for later processing
215 if (field_names.containsKey(cur_field_name)) {
216 field_names[cur_field_name] = field_names[cur_field_name]!! + 1
217 } else {
218 field_names[cur_field_name] = 1
219 }
220
221 mOutputListener!!.println("Field name: " + current.getName())
222 mOutputListener!!.println("Field partial name: " + current.getPartialName())
223
224 mOutputListener!!.print("Field type: ")
225 val type = current.getType()
226 val str_val = current.getValueAsString()
227 when (type) {
228 Field.e_button -> mOutputListener!!.println("Button")
229 Field.e_radio -> mOutputListener!!.println("Radio button: Value = $str_val")
230 Field.e_check -> {
231 current.setValue(true)
232 mOutputListener!!.println("Check box: Value = $str_val")
233 }
234 Field.e_text -> {
235 mOutputListener!!.println("Text")
236 // Edit all variable text in the document
237 val old_value: String
238 if (current.getValue() != null) {
239 old_value = current.getValueAsString()
240 current.setValue("This is a new value. The old one was: $old_value")
241 }
242 }
243 Field.e_choice -> mOutputListener!!.println("Choice")
244 Field.e_signature -> mOutputListener!!.println("Signature")
245 }
246
247 mOutputListener!!.println("------------------------------")
248 }
249
250 // Search for a specific field
251 val f = doc.getField("employee.name.first")
252 if (f != null) {
253 mOutputListener!!.println("Field search for " + f.name + " was successful")
254 } else {
255 mOutputListener!!.println("Field search failed")
256 }
257
258 // Regenerate field appearances.
259 doc.refreshFieldAppearances()
260 doc.save(Utils.createExternalFile("forms_test_edit.pdf", mFileList).absolutePath, SDFDoc.SaveMode.NO_FLAGS, null)
261 mOutputListener!!.println("Done.")
262 }
263 } catch (e: Exception) {
264 mOutputListener!!.printError(e.stackTrace)
265 }
266
267 //----------------------------------------------------------------------------------
268 // Sample: Form templating
269 // Replicate pages and form data within a document. Then rename field names to make
270 // them unique.
271 //----------------------------------------------------------------------------------
272 try {
273 PDFDoc(Utils.createExternalFile("forms_test1.pdf", mFileList).absolutePath).use { doc ->
274 // Sample: Copying the page with forms within the same document
275 doc.initSecurityHandler()
276
277 val src_page = doc.getPage(1) as Page
278 doc.pagePushBack(src_page) // Append several copies of the first page
279 doc.pagePushBack(src_page) // Note that forms are successfully copied
280 doc.pagePushBack(src_page)
281 doc.pagePushBack(src_page)
282
283 // Now we rename fields in order to make every field unique.
284 // You can use this technique for dynamic template filling where you have a 'master'
285 // form page that should be replicated, but with unique field names on every page.
286 for (cur_field in field_names.keys) {
287 renameAllFields(doc, cur_field, field_names[cur_field]!!)
288 }
289
290 doc.save(Utils.createExternalFile("forms_test1_cloned.pdf", mFileList).absolutePath, SDFDoc.SaveMode.NO_FLAGS, null)
291 mOutputListener!!.println("Done.")
292 }
293
294 } catch (e: Exception) {
295 mOutputListener!!.printError(e.stackTrace)
296 }
297
298 //----------------------------------------------------------------------------------
299 // Sample:
300 // Flatten all form fields in a document.
301 // Note that this sample is intended to show that it is possible to flatten
302 // individual fields. PDFNet provides a utility function PDFDoc.flattenAnnotations()
303 // that will automatically flatten all fields.
304 //----------------------------------------------------------------------------------
305 try {
306 PDFDoc(Utils.createExternalFile("forms_test1.pdf", mFileList).absolutePath).use { doc ->
307 doc.initSecurityHandler()
308
309 // Traverse all pages
310 if (true) {
311 doc.flattenAnnotations()
312 } else
313 // Manual flattening
314 {
315
316 val pitr = doc.pageIterator
317 while (pitr.hasNext()) {
318 val page = pitr.next()!!
319 for (i in page.getNumAnnots() - 1 downTo 0) {
320 val annot = page.getAnnot(i)
321 if (annot.type == Annot.e_Widget) {
322 annot.flatten(page)
323 }
324 }
325 }
326 }
327
328 doc.save(Utils.createExternalFile("forms_test1_flattened.pdf", mFileList).absolutePath, SDFDoc.SaveMode.NO_FLAGS, null)
329 mOutputListener!!.println("Done.")
330 }
331 } catch (e: Exception) {
332 mOutputListener!!.printError(e.stackTrace)
333 }
334
335 for (file in mFileList) {
336 addToFileList(file)
337 }
338 printFooter(outputListener)
339 }
340
341 companion object {
342
343 private var mOutputListener: OutputListener? = null
344
345 private val mFileList = ArrayList<String>()
346
347 // field_nums has to be greater than 0.
348 @Throws(PDFNetException::class)
349 internal fun renameAllFields(doc: PDFDoc, name: String, field_nums: Int) {
350 var itr = doc.getFieldIterator(name)
351 var counter = 1
352 while (itr.hasNext()) {
353 val f = itr.next()!!
354 val update_count = java.lang.Math.ceil(counter / field_nums.toDouble()).toInt()
355 f.rename("$name-$update_count")
356 itr = doc.getFieldIterator(name)
357 ++counter
358 }
359 }
360
361 @Throws(PDFNetException::class)
362 internal fun createCustomButtonAppearance(doc: PDFDoc, button_down: Boolean): Obj {
363 // Create a button appearance stream ------------------------------------
364 val build = ElementBuilder()
365 val writer = ElementWriter()
366 writer.begin(doc)
367
368 // Draw background
369 var element = build.createRect(0.0, 0.0, 101.0, 37.0)
370 element.setPathFill(true)
371 element.setPathStroke(false)
372 element.gState.fillColorSpace = ColorSpace.createDeviceGray()
373 element.gState.fillColor = ColorPt(0.75, 0.0, 0.0)
374 writer.writeElement(element)
375
376 // Draw 'Submit' text
377 writer.writeElement(build.createTextBegin())
378 run {
379 val text = "Submit"
380 element = build.createTextRun(text, Font.create(doc, Font.e_helvetica_bold), 12.0)
381 element.gState.fillColor = ColorPt(0.0, 0.0, 0.0)
382
383 if (button_down)
384 element.setTextMatrix(1.0, 0.0, 0.0, 1.0, 33.0, 10.0)
385 else
386 element.setTextMatrix(1.0, 0.0, 0.0, 1.0, 30.0, 13.0)
387 writer.writeElement(element)
388 }
389 writer.writeElement(build.createTextEnd())
390
391 val stm = writer.end()
392
393 // Set the bounding box
394 stm.putRect("BBox", 0.0, 0.0, 101.0, 37.0)
395 stm.putName("Subtype", "Form")
396 return stm
397 }
398 }
399
400}
Did you find this helpful?
Trial setup questions?
Ask experts on DiscordNeed other help?
Contact SupportPricing or product questions?
Contact Sales