This post is a quick reference on how to create a PDF document using the iText library. If this is written correctly, you should be able to create a PDF document in minutes. This entry is based on Bruno Lowagie’s book, iText in Action.
This post explains the details of how to create the sample document linked here. For the complete code that generated the sample document, check the entry Sample Business Document Created with the iText Library.
References
Setup
Download the latest version of the itext jar from itextpdf.com and add it to your project’s build path.
Things to remember
Units. iText uses point as the typographic unit of measure. One inch is equivallent to 72 points. One cm is equivallent to 28.35 points.
Steps
The Document object is a representation of the PDF file. The PdfWriter simply listens for events in the document object. Most of the work involves adding elements or content to the document object. The PdfWriter will interpret these document events to create the PDF file. When you close the document the PdfWriter flushes all the changes to the PDF file itself.
Create a Document object
The following code creates a new document. After this code executes you have no pages to write on (You need to add pages to the document).
// create a document object Document document = new Document(PageSize.LETTER); // set margins before opening the document document.setMargins(36f, 36f, 36f, 36f);
Instantiate a PdfWriter and open the document
PdfWriter.getInstance(document, new FileOutputStream("c:\\myDir\\myDocument.pdf"));
document.open();
Adding Content to the Document
The iText library is quite extensive, but you should be able to create any type of business document by using just the following classes:
Font and FontFactory from com.itextpdf.text:
Since fonts are used frequently throughout a document, it makes sense to set them up as instance variables and initialize them in a constructor, such as:
private DocumentService() {
arial = FontFactory.getFont("Arial", 8);
arial.setStyle(Font.BOLD);
arialSmall = FontFactory.getFont("Arial", 6);
arialSmall.setStyle(Font.BOLD);
courier = FontFactory.getFont("Courier", 10);
arialMini = FontFactory.getFont("Arial", 5);
}
Phrase and Paragraph from com.itextpdf.text:
A Paragraph can be instantiated with a String and a Font:
private Element textElement() {
Paragraph element = new Paragraph("Some Text for the paragraph.", this.arial);
return element;
}
You can also use Phrases to compose a Paragraph:
private Element someElement() {
float leading = 9f;
Phrase label = new Phrase("Label ", this.arial);
Phrase value = new Phrase("1234567890", courier);
Paragraph info = new Paragraph();
info.setLeading(leading);
info.add(label);
info.add(value);
info.setAlignment(Element.ALIGN_RIGHT);
return info;
}
Notice that the Element interface provides alignment constants. Leading is used to define the space between lines within the paragraph.
Image from com.itextpdf.text:
Assuming that you have an image file, the image object is created as follows:
private Element fourthLogoElement() {
String path = "I:\\trash\\logo.jpg";
Image image = null;
try {
image = Image.getInstance(path);
} catch (BadElementException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return image;
}
If you want to place the image in a PdfPCell, you will have to use the image as an argument for the PdfPCell constructor. If you first instantiate the PdfPCell and then add the image, the image will be stretched.
element = this.fourthLogoElement(); // You need to pass the image to the constructor. // If you add the image, it will be stretched to fill the cell. cell = new PdfPCell((Image)element); cell.setPadding(2); cell.setHorizontalAlignment(Element.ALIGN_CENTER); cell.setVerticalAlignment(Element.ALIGN_CENTER); cell.setBorderWidth(0.3f); table.addCell(cell);
PdfPTable and PdfPCell from com.itextpdf.text.pdf
Tables will be used for layout purposes, the same way you would use them in html. You can also use nested tables as you would in html.
A table can be instantiated by indicating the number of columns–in which case all columns would have the same width– or by using an array of float values that indicate the relative width of the columns:
// two columns, same width
PdfPTable table = new PdfPTable(2);
table.setWidthPercentage(100f);
// 7 columns, multiple widths
float[] widths = {3f,6f,6f,6f,6f,9f,25f};
PdfPTable table = new PdfPTable(widths);
table.setWidthPercentage(100f);
PdfPCells added to the table are automatically positioned from left to right. You can modify the rowspan and colspan as needed:
private Element anotherElement() {
float leading = 9f;
// 2 columns
PdfPTable table = new PdfPTable(2);
table.setWidthPercentage(100f);
PdfPCell cell;
cell = new PdfPCell(new Paragraph("This is a label", arialSmall));
cell.setGrayFill(0.85f);
cell.setBorderWidth(0.3f);
// A cell that spans 2 columns
cell.setColspan(2);
// add the cell to the table
table.addCell(cell);
cell = new PdfPCell();
cell.setBorderWidth(0.3f);
// to define the cell height
cell.setFixedHeight(36f);
cell.setColspan(2);
Paragraph info = new Paragraph("Info will go here\nMore here\nMore here",
courier);
info.setLeading(leading);
cell.addElement(info);
table.addCell(cell);
cell = new PdfPCell(new Paragraph("Another label", arialSmall));
cell.setPadding(2);
cell.setGrayFill(0.85f);
cell.setBorderWidth(0.3f);
table.addCell(cell);
cell = new PdfPCell(new Paragraph("Last Label", arialSmall));
cell.setPadding(2);
cell.setGrayFill(0.85f);
cell.setBorderWidth(0.3f);
table.addCell(cell);
cell = new PdfPCell();
cell.setPadding(2);
cell.setBorderWidth(0.3f);
Paragraph someInfo = new Paragraph("99-9-9999", courier);
someInfo.setLeading(leading);
cell.addElement(someInfo);
table.addCell(cell);
cell = new PdfPCell();
cell.setPadding(2);
cell.setBorderWidth(0.3f);
Paragraph acctInfo = new Paragraph("888888888", courier);
acctInfo.setLeading(leading);
cell.addElement(acctInfo);
table.addCell(cell);
return table;
}
The following PdfPCell methods are very usefull:
// grey cell gackground: cell.setGrayFill(0.85f); // to set the border width: cell.setBorderWidth(0.3f); // A cell that spans 2 columns cell.setColspan(2); // to define the cell height cell.setFixedHeight(36f); // to add an element to the cell cell.addElement(info); // padding: the cell margins cell.setPadding(2); // set vertical alignment cell.setVerticalAlignment(Element.ALIGN_BOTTOM); // set horizontal alignment cell.setHorizontalAlignment(Element.ALIGN_CENTER);
You can add any implementation of Element to a cell, including a PdfPTable (a nested table). However, for nested tables to render as expected, you should use the table as a constructor parameter as follows:
PdfPTable wTable = (PdfPTable) this.descriptionElement(); cell = new PdfPCell(wTable); cell.setColspan(2); cell.setBorderWidth(0.3f); table.addCell(cell);
Working with Tables
You can build an entire document in a single method, but your code will be cleaner if you divide the document in sections and you build each one of those sections using tables. The following guidelines are useful:
Here’s what the createDocument method looks like:
public void createDocument(DomainObject domainObject) {
this.domainObject = domainObject;
try {
Document document = new Document(PageSize.LETTER);
document.setMargins(36f, 36f, 36f, 36f);
FileOutputStream fos;
fos = new FileOutputStream("C:\\outputDir\\fileName.pdf");
PdfWriter.getInstance(document, fos);
document.open();
document.newPage();
// mainElement returns a PdfPTable
Element mainElement = mainElement();
document.add(mainElement);
document.close();
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
catch (DocumentException e) {
e.printStackTrace();
}
catch (Exception e) {
e.printStackTrace();
}
}
