|
Geek-Tutorials.com
|
|
Geek Tutorials Home > Java PDF & Reporting - iText Tutorials > Programming PDF AcroForm with iText and Javascript
An Adobe PDF form (AcroForm) is an electronic-based document that allow user to input data and then back to server via email, HTML, FDF, XFDF or PDF. Adobe Acrobat Professional or Adobe Acrobat Standard can save AcroForm data in its original copy of the form, while Adobe Reader user can only save a blank copy of the PDF form, unless the form author added special usage rights to the PDF form.
A PDF AcroForm can contain form elements such as Button, Check Boxes, Combo box, Digital signature field, Document Message Bar, List box, Radio buttons and Text field. The first example I'm going to show you here contain various styles of TextField in a form with a HTML submit button, we will also spice up the form with some Adobe's Acrobat Javascript. This example make use of PdfPTable as a layout tool to place form elements into PDF, this allow programmer easily change the form layout without explicitly change each form element position. Note that sometimes you might want to set each form element's location manually, we will talk about how to do it in later example of this tutorial. Following example will generate this PDF
package com.geek.tutorial.itext.acroform;
import com.lowagie.text.Document;
import com.lowagie.text.pdf.PdfWriter;
import com.lowagie.text.Element;
import com.lowagie.text.pdf.PdfAction;
import com.lowagie.text.pdf.PdfBorderDictionary;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfFormField;
import com.lowagie.text.pdf.PdfAnnotation;
import com.lowagie.text.pdf.PushbuttonField;
import com.lowagie.text.pdf.TextField;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.PdfPCell;
import com.lowagie.text.pdf.PdfPTable;
import com.lowagie.text.pdf.PdfPCellEvent;
import java.awt.Color;
import java.io.FileOutputStream;
public class TextFieldForm {
public TextFieldForm()throws Exception{
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document,
new FileOutputStream("TextFieldForm.pdf"));
document.open();
PdfPTable table = new PdfPTable(2);
table.getDefaultCell().setPadding(5f); // Code 1
table.setHorizontalAlignment(Element.ALIGN_LEFT);
PdfPCell cell;
// Code 2, add name TextField
table.addCell("Name");
TextField nameField = new TextField(writer,
new Rectangle(0,0,200,10), "nameField");
nameField.setBackgroundColor(Color.WHITE);
nameField.setBorderColor(Color.BLACK);
nameField.setBorderWidth(1);
nameField.setBorderStyle(PdfBorderDictionary.STYLE_SOLID);
nameField.setText("");
nameField.setAlignment(Element.ALIGN_LEFT);
nameField.setOptions(TextField.REQUIRED);
cell = new PdfPCell();
cell.setMinimumHeight(10);
cell.setCellEvent(new FieldCell(nameField.getTextField(),
200, writer));
table.addCell(cell);
// force upper case javascript
writer.addJavaScript(
"var nameField = this.getField('nameField');" +
"nameField.setAction('Keystroke'," +
"'forceUpperCase()');" +
"" +
"function forceUpperCase(){" +
"if(!event.willCommit)event.change = " +
"event.change.toUpperCase();" +
"}");
// Code 3, add empty row
table.addCell("");
table.addCell("");
// Code 4, add age TextField
table.addCell("Age");
TextField ageComb = new TextField(writer, new Rectangle(0,
0, 30, 10), "ageField");
ageComb.setBorderColor(Color.BLACK);
ageComb.setBorderWidth(1);
ageComb.setBorderStyle(PdfBorderDictionary.STYLE_SOLID);
ageComb.setText("12");
ageComb.setAlignment(Element.ALIGN_RIGHT);
ageComb.setMaxCharacterLength(2);
ageComb.setOptions(TextField.COMB |
TextField.DO_NOT_SCROLL);
cell = new PdfPCell();
cell.setMinimumHeight(10);
cell.setCellEvent(new FieldCell(ageComb.getTextField(),
30, writer));
table.addCell(cell);
// validate age javascript
writer.addJavaScript(
"var ageField = this.getField('ageField');" +
"ageField.setAction('Validate','checkAge()');" +
"function checkAge(){" +
"if(event.value < 12){" +
"app.alert('Warning! Applicant\\'s age can not" +
" be younger than 12.');" +
"event.value = 12;" +
"}}");
// add empty row
table.addCell("");
table.addCell("");
// Code 5, add age TextField
table.addCell("Comment");
TextField comment = new TextField(writer,
new Rectangle(0, 0,200, 100), "commentField");
comment.setBorderColor(Color.BLACK);
comment.setBorderWidth(1);
comment.setBorderStyle(PdfBorderDictionary.STYLE_SOLID);
comment.setText("");
comment.setOptions(TextField.MULTILINE |
TextField.DO_NOT_SCROLL);
cell = new PdfPCell();
cell.setMinimumHeight(100);
cell.setCellEvent(new FieldCell(comment.getTextField(),
200, writer));
table.addCell(cell);
// check comment characters length javascript
writer.addJavaScript(
"var commentField = " +
"this.getField('commentField');" +
"commentField" +
".setAction('Keystroke','checkLength()');" +
"function checkLength(){" +
"if(!event.willCommit && " +
"event.value.length > 100){" +
"app.alert('Warning! Comment can not " +
"be more than 100 characters.');" +
"event.change = '';" +
"}}");
// add empty row
table.addCell("");
table.addCell("");
// Code 6, add submit button
PushbuttonField submitBtn = new PushbuttonField(writer,
new Rectangle(0, 0, 35, 15),"submitPOST");
submitBtn.setBackgroundColor(Color.GRAY);
submitBtn.
setBorderStyle(PdfBorderDictionary.STYLE_BEVELED);
submitBtn.setText("POST");
submitBtn.setOptions(PushbuttonField.
VISIBLE_BUT_DOES_NOT_PRINT);
PdfFormField submitField = submitBtn.getField();
submitField.setAction(PdfAction
.createSubmitForm(
"http://www.geek-tutorials.com/java/itext/submit.php",
null, PdfAction.SUBMIT_HTML_FORMAT));
cell = new PdfPCell();
cell.setMinimumHeight(15);
cell.setCellEvent(new FieldCell(submitField, 35, writer));
table.addCell(cell);
// Code 7, add reset button
PushbuttonField resetBtn = new PushbuttonField(writer,
new Rectangle(0, 0, 35, 15), "reset");
resetBtn.setBackgroundColor(Color.GRAY);
resetBtn.setBorderStyle(
PdfBorderDictionary.STYLE_BEVELED);
resetBtn.setText("RESET");
resetBtn
.setOptions(
PushbuttonField.VISIBLE_BUT_DOES_NOT_PRINT);
PdfFormField resetField = resetBtn.getField();
resetField.setAction(PdfAction.createResetForm(null, 0));
cell = new PdfPCell();
cell.setMinimumHeight(15);
cell.setCellEvent(new FieldCell(resetField, 35, writer));
table.addCell(cell);
document.add(table);
document.close();
}
class FieldCell implements PdfPCellEvent{
PdfFormField formField;
PdfWriter writer;
int width;
public FieldCell(PdfFormField formField, int width,
PdfWriter writer){
this.formField = formField;
this.width = width;
this.writer = writer;
}
public void cellLayout(PdfPCell cell, Rectangle rect,
PdfContentByte[] canvas){
try{
// delete cell border
PdfContentByte cb = canvas[PdfPTable
.LINECANVAS];
cb.reset();
formField.setWidget(
new Rectangle(rect.left(),
rect.bottom(),
rect.left()+width,
rect.top()),
PdfAnnotation
.HIGHLIGHT_NONE);
writer.addAnnotation(formField);
}catch(Exception e){
System.out.println(e);
}
}
}
public static void main(String[] args) {
try{
TextFieldForm textFieldForm = new TextFieldForm();
}catch(Exception e){
System.out.println(e);
}
}
}
Code 1 [Locate Code]
Set the empty cell padding. Since we are using PdfPTable to layout the form elements in this example, we need to set the padding space between every rows of fields.
Code 2 [Locate Code]
Create TextField call "nameField" with white background, solid black border and left alignment. The setOptions method can accept a combination of following flags:
First we use cell.setMinimumHeight() to set the height of the row. Then we use PdfPCellEvent to find out the location of the cell allocated by the PdfPTable, so that we can use the cell location to place our form element into the PDF. The reason we doing this work around is because PdfPTable do not support insert of form element directly into table, so we doing a little trick to let the PdfPTable allocate location for us, and then we use the location information to manually place our form element.
A PdfPCellEvent.cellLayout method is called at the end of each cell rendering. It contain the cell instance, position and canvases data of the cell. A perfect object to retrive the cell position for our form element placement! [See the inner class of this example that implement the PdfPCellEvent here]
In above example of cellLayout() method, the following code delete the cell border
PdfContentByte cb = canvas[PdfPTable.LINECANVAS]; cb.reset();
Then this code use the cell rect(position and dimension in a Rectangle object) to set the form element location.
formField.setWidget(new Rectangle(rect.left(), rect.bottom(), rect.left()+width, rect.top()), PdfAnnotation.HIGHLIGHT_NONE);
After that the cellLayout will add the form element into PDF by calling following method
writer.addAnnotation(formField);
At this point the form element is already added to the PDF, but we still need to add the dummy cell to the table to increase the height of the table, so that next form element can be added at location next to it.
table.addCell(cell);
We can spice up the TextField with some Javascript, the following Javascript force entered character to uppercase.
writer.addJavaScript("var nameField = this.getField('nameField');" +
"nameField.setAction('Keystroke'," +
"'forceUpperCase()');" +
"" +
"function forceUpperCase(){" +
"if(!event.willCommit)event.change = " +
"event.change.toUpperCase();" +
"}");
Code 3 [Locate Code]
Add some space in between form elements.
Code 4 [Locate Code]
Sometime form require user to enter limited amount of characters into the field consist boxes. We can accomplish it by setting following property and flags to the TextField. Note that you must set DO_NOT_SCROLL flag, else the COMB field will become multiline COMB field, which is not what we want.
ageComb.setMaxCharacterLength(2); ageComb.setOptions(TextField.COMB | TextField.DO_NOT_SCROLL);
Let's add some Javascript to the field, the following Javascript prevent users from entering age lower than 12 and give warning when they do.
writer.addJavaScript("var ageField = this.getField('ageField');" +
"ageField.setAction('Validate','checkAge()');" +
"function checkAge(){" +
"if(event.value < 12){" +
"app.alert('Warning! Applicant\\'s age can not" +
" be younger than 12.');" +
"event.value = 12;" +
"}}");
Code 5 [Locate Code]
This code create a multiline TextField with Javascript that limiting the amount of characters enter under 100.
Code 6 [Locate Code]
Create a submit button. This code submit form data in format of HTML POST to http://www.geek-tutorials.com/java/itext/submit.php, note that it can be php, jsp, asp or any server-side script that process HTML parameter.
submitField.setAction(PdfAction .createSubmitForm( "http://www.geek-tutorials.com/java/itext/submit.php", null, PdfAction.SUBMIT_HTML_FORMAT));
Acroform can also send data in other formats, see the following flags
Following is the snippet from submit.php will receive form data as HTML parameter.
Name: <?php print $_POST['nameField']; ?> <br/>
Age: <?php print $_POST['ageField']; ?> <br/>
Comment: <?php print $_POST['commentField']; ?> <br/>
You can do the same thing with JSP's request.getParameter("nameField"), I would like to use jsp instead of php to demonstrate here, but I can't afford a JSP supported web-hosting and this PHP web-hosting I'm currenly using is really given me a very large amount of bandwidth and low cost ^^
Code 7 [Locate Code]
Create a reset button that will clear all field data from the form.
Following example show you how to add drop-down and scrollable list to PDF Acroform. I will keep the example simple by omitting a submit button since it is already explain in previous example. I will also show you an alternative way to place the form element on the PDF document besides using PdfPTable. Following example will generate this PDF
package com.geek.tutorial.itext.acroform;
import com.lowagie.text.Document;
import com.lowagie.text.pdf.PdfWriter;
import com.lowagie.text.pdf.PdfAction;
import com.lowagie.text.pdf.PdfBorderDictionary;
import com.lowagie.text.pdf.PdfFormField;
import com.lowagie.text.pdf.PdfAnnotation;
import com.lowagie.text.pdf.PushbuttonField;
import com.lowagie.text.pdf.TextField;
import com.lowagie.text.Rectangle;
import java.awt.Color;
import java.io.FileOutputStream;
public class ListFieldForm {
public ListFieldForm() throws Exception{
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document,
new FileOutputStream("ListFieldForm.pdf"));
document.open();
// Code 1
String options[] = { "PS3", "XBOX 360",
"Wii", "PSP", "NDS", "GBA"};
// Code 2 create drop-down list
PdfFormField dropDown = PdfFormField.createCombo(writer,
true, options, 0);
dropDown.setWidget(new Rectangle(50, 785, 120, 800),
PdfAnnotation.HIGHLIGHT_INVERT);
dropDown.setFieldName("dropDownList");
dropDown.setValueAsString("PS3");
dropDown.setMKBorderColor(Color.BLACK);
writer.addAnnotation(dropDown);
// Code 3 create scrollable list
TextField scrollableList =
new TextField(writer, new Rectangle(150, 740, 250,
800), "scrollableList");
scrollableList.setBackgroundColor(Color.WHITE);
scrollableList.setBorderColor(Color.BLUE);
scrollableList.setBorderWidth(2);
scrollableList.setBorderStyle(
PdfBorderDictionary.STYLE_SOLID);
scrollableList.setFontSize(10);
scrollableList.setChoices(options);
scrollableList.setChoiceSelection(0);
writer.addAnnotation(scrollableList.getListField());
// Code 4 add function and button for showing state
writer.addJavaScript("function showState(){" +
"app.alert('DropDown:'+ this.getField('dropDownList').value +'\\n'+" +
"'Scrollable List:'+this.getField('scrollableList').value);" +
"}");
PushbuttonField push =
new PushbuttonField(writer, new Rectangle(
70, 710, 140, 730), "pushAction");
push.setBackgroundColor(Color.LIGHT_GRAY);
push.setBorderColor(Color.GRAY);
push.setText("Show State");
push.setBorderStyle(PdfBorderDictionary.STYLE_BEVELED);
push.setTextColor(Color.BLACK);
PdfFormField pushbutton = push.getField();
pushbutton.setAction(PdfAction.javaScript("showState()",
writer));
writer.addAnnotation(pushbutton);
document.close();
}
public static void main(String[] args){
try{
ListFieldForm listFieldForm = new ListFieldForm();
}catch(Exception e){
System.out.println(e);
}
}
}
Code 1 [Locate Code]
Initialize a list of String array for both list.
Code 2 [Locate Code]
Create drop-down list with a name "dropDownList" and set initial value to 'PS3'. We use setWidget() to set the position and dimension of the drop-down list.
dropDown.setWidget(new Rectangle(50, 785, 120, 800), PdfAnnotation.HIGHLIGHT_INVERT);
Code 3 [Locate Code]
create scrollable list with a name "scrollableList" and set default selection to first item (0-base index) with setChoiceSelection() method.
Code 4 [Locate Code]
We then add a JavaScript and button to check the state of the drop-down and scrollable list.
This example show you how to create a Radio Button in a group and CheckBoxes Following example will generate this PDF
package com.geek.tutorial.itext.acroform;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Element;
import com.lowagie.text.pdf.BaseFont;
import com.lowagie.text.pdf.PdfWriter;
import com.lowagie.text.pdf.PdfAction;
import com.lowagie.text.pdf.PdfBorderDictionary;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfFormField;
import com.lowagie.text.pdf.PushbuttonField;
import com.lowagie.text.pdf.RadioCheckField;
import com.lowagie.text.Rectangle;
import java.awt.Color;
import java.io.FileOutputStream;
import java.io.IOException;
public class RadioCheckBoxForm {
public RadioCheckBoxForm() throws Exception{
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document,
new FileOutputStream("RadioCheckBoxForm.pdf"));
document.open();
PdfContentByte cb = writer.getDirectContent();
BaseFont bf = BaseFont.createFont(BaseFont.TIMES_ROMAN,
BaseFont.WINANSI, BaseFont.NOT_EMBEDDED);
Rectangle rect;
// Code 1 create radio button
String[] radios = { "Radio1", "Radio2", "Radio3" };
PdfFormField radioField =
PdfFormField.createRadioButton(writer, true);
radioField.setFieldName("radioField");
radioField.setValueAsName(radios[0]);
for (int i = 0; i < radios.length; i++) {
rect = new Rectangle(40, 815 - i * 30,
60, 797 - i * 30);
addRadioButton(writer, rect,
radioField, radios[i], i == 0);
cb.beginText();
cb.setFontAndSize(bf, 12);
cb.showTextAligned(Element.ALIGN_LEFT, radios[i],
70, 802 - i * 30, 0);
cb.endText();
}
writer.addAnnotation(radioField);
// Code 2 create checkbox button
String[] options = {"Check1", "Check2", "Check3"};
for (int i = 0; i < options.length; i++) {
rect = new Rectangle(160, 815 - i * 30,
180, 797 - i * 30);
addCheckbox(writer, rect, options[i]);
cb.beginText();
cb.setFontAndSize(bf, 12);
cb.showTextAligned(Element.ALIGN_LEFT,
options[i], 190, 802 - i * 30, 0);
cb.endText();
}
// Code 3 add function and button for showing state
writer.addJavaScript("function showState(){" +
"app.alert('Radio:'+ this.getField('radioField').value+'\\n\\n'+"+
"'Check1:'+this.getField('Check1').value +'\\n'+" +
"'Check2:'+this.getField('Check2').value +'\\n'+" +
"'Check3:'+this.getField('Check3').value);" +
"}");
PushbuttonField push = new PushbuttonField(writer,
new Rectangle(
80, 710, 150, 730), "pushAction");
push.setBackgroundColor(Color.LIGHT_GRAY);
push.setBorderColor(Color.GRAY);
push.setText("Show State");
push.setBorderStyle(PdfBorderDictionary.STYLE_BEVELED);
push.setTextColor(Color.BLACK);
PdfFormField pushbutton = push.getField();
pushbutton.setAction(PdfAction.javaScript("showState()",
writer));
writer.addAnnotation(pushbutton);
document.close();
}
private static void addRadioButton(PdfWriter writer,
Rectangle rect,
PdfFormField radio, String name, boolean on)
throws IOException, DocumentException {
RadioCheckField check =
new RadioCheckField(writer, rect, null, name);
check.setCheckType(RadioCheckField.TYPE_CHECK);
check.setBorderColor(Color.BLACK);
check.setChecked(on);
radio.addKid(check.getRadioField());
}
private static void addCheckbox(PdfWriter writer, Rectangle rect,
String name) throws IOException, DocumentException {
RadioCheckField check =
new RadioCheckField(writer, rect, name, "On");
check.setCheckType(RadioCheckField.TYPE_CROSS);
check.setBorderColor(Color.BLACK);
writer.addAnnotation(check.getCheckField());
}
public static void main(String[] args){
try{
RadioCheckBoxForm radioCheckForm =
new RadioCheckBoxForm();
}catch(Exception e){
System.out.println(e);
}
}
}
Code 1 [Locate Code]
Create parent of group of radio buttons with a name "radioField", then use for loop to add 3 radio buttons into the group. The method addRadioButton() is called to create radio button and add to the group
private static void addRadioButton(PdfWriter writer,Rectangle rect,
PdfFormField radio, String name, boolean on)
throws IOException,
DocumentException {
RadioCheckField check =
new RadioCheckField(writer, rect, null, name);
check.setCheckType(RadioCheckField.TYPE_CHECK);
check.setBorderColor(Color.BLACK);
check.setChecked(on);
radio.addKid(check.getRadioField());
}
Code 2 [Locate Code]
Create 3 checkboxes, note that these checkboxes do not need parent object. The method addCheckbox() is called in for loop to create checkboxes.
private static void addCheckbox(PdfWriter writer, Rectangle rect,
String name) throws IOException, DocumentException {
RadioCheckField check =
new RadioCheckField(writer, rect, name, "On");
check.setCheckType(RadioCheckField.TYPE_CROSS);
check.setBorderColor(Color.BLACK);
writer.addAnnotation(check.getCheckField());
}
Code 3 [Locate Code]
Add JavaScript and Button to show state of all buttons in the AcroForm.
Your donation will be use for this project's site maintainance and further development of the content. Your support can help us provide higher quality of free tutorials and services to everyone in future
. Download latest source code for this project.