Generating PDF’s within java using iText
With PDFs becoming more and more prevalent in todays world, if you are doing any sort of exporting or sales, generating PDFs is probably going to find its way into your program. Using iText, you are given a large amount of functionality in order to create custom PDFs on the fly. This article will be focusing on how to generate an PDF for a sales receipt. With this, I will show how easily you can setup tables, images, barcodes, and links.
First thing as always, lets get the environment setup. Luckily, all you need to do is download the iText jar here. In this example, I just used the itext core jar. Once you add that to your library, you are ready to go. Following that, make sure you are able to get the Hello World example running. which is here. After that, lets get into the tutorial.
We have a lot of things to cover, so here is what we want for our end result.
As you can see, we are building something like an order form. Starting at the top level, we have two main sections, there is a table (called PdfPTable) at the top and a table at the bottom. The first one I have called the header table and the other one is the line item table. Here are going to be the application specific objects.
Customer
public class Customer { private String _name; private String _address; private String _phone; public Customer(String name, String address, String phone) { _name = name; _address = address; _phone = phone; } }
LineItem
public class LineItem { private String _description; private double _price; public LineItem(String description, double price){ _description = description; _price = price; } }
Order
public class Order { private Customer _customer; private List<LineItem> _lineItems; private double _shipping; public Order(Customer customer, List<LineItem> lineItems){ _customer = customer; _lineItems = lineItems; } }
The Customer object should be self explanatory. LineItem represents one row within our receipt. The description will be what is on the left and the price is the cost that item. The Order object will be a both the Customer and a list of what the person bought.
public void generatorPDF() throws Exception{ Document d = new Document(); try{ PdfWriter writer = PdfWriter.getInstance(d, new FileOutputStream("CodeOfDoom.pdf")); d.open(); //generate tables PdfPTable table = generateLineItemTable(_order.getLineItems()); PdfPTable headerTable= generateHeaderTable(_order.getCustomer()); //add Bar Code to the header. addBarcode(writer,headerTable); //add header and line item table d.add(headerTable); d.add(table); Paragraph p = new Paragraph("\n\nFor more, please visit "); Anchor anchor = new Anchor("www.codeofdoom.com/wordpress", FontFactory.getFont(FontFactory.TIMES_ROMAN, 12, Font.UNDERLINE, new Color(0, 0, 255))); p.add(anchor); d.add(p); d.close(); }catch(Exception e){ e.printStackTrace(); } }
When a PDF is started, there are two required parts. The Document and the PdfWriter. The PdfWriter is what is creating the file. The Document is our actual base layout element. This is what we will be addinig the elements to. Before we add anything to our Document, we need to generate our tables.
private PdfPTable generateHeaderTable(Customer c) throws Exception{ //Generic logo PdfPTable headerTable= new PdfPTable(2); Image i = Image.getInstance("resources//logo.jpg"); i.setAlignment(Element.ALIGN_RIGHT); i.scalePercent(25); PdfPCell cell = new PdfPCell(i,false); cell.setBorder(0); headerTable.addCell(cell); cell = borderlessCell("Code of Doom Order Form"); headerTable.addCell(cell); headerTable.addCell(borderlessCell("Customer Name")); headerTable.addCell(borderlessCell(c.getName())); headerTable.addCell(borderlessCell("Address")); headerTable.addCell(borderlessCell(c.getAddress())); headerTable.addCell(borderlessCell("Phone Number")); headerTable.addCell(borderlessCell(c.getPhone())); return headerTable; }
We create our PdfPTable, which takes a integer. This integer represents the number of columns that it will be in the table. After we have our PdfPTable, we then create our Image object and then add that do a PdfPCell. You will notice that in the PdfPCell constructor, it takes an Image and false. The false is extremely important. That parameter is for scaling the image. If you dont pass it, it will scale the image to be as high as possible. In fact, you will notice I use scalePercent on the image since the image I took (some random one) was too big, so I shrunk it down. Even using this, if you dont pass false into the cell, it will ignore the scalePercent on the image.
Next we add our customer information. One thing that sticks out is the borderlessCell function. This is just a private helper function I added to create defaults to a cell.
private PdfPCell borderlessCell(String s){ PdfPCell cell = new PdfPCell(); Font f = new Font(Font.COURIER); cell.setBorder(0); cell.setHorizontalAlignment(Element.ALIGN_LEFT); cell.addElement(new Paragraph(s,f)); return cell; }
Interesting note on adding cells though. When we created our table, I specified that there will be 2 columns in the table. As you noticed, we dont really add ‘rows’ to our table. The way it works is whenever you add a cell, it willl put it in the first available spot. Adding two cells will fill a row. If you want one cell to take two rows, you need to set the cells colspan to 2.
Generating the Line Item table will be similar.
private PdfPTable generateLineItemTable(List<LineItem> listItems){ PdfPTable table = new PdfPTable(2); DecimalFormat df = new DecimalFormat("0.00"); double total = 0; for (LineItem lineItem:_order.getLineItems()){ table.addCell(lineItem.getDescription()); table.addCell("$"+df.format(lineItem.getPrice())); total += lineItem.getPrice(); } table.addCell("Tax\nShipping"); table.addCell("$"+df.format(total*.08)+"\n$4.99"); table.addCell("Applied Coupons"); table.addCell("$0.00"); table.addCell("Total"); table.addCell(df.format(total)); return table; }
Here we are going through each of the line items and just creating cells with the description and the price of that item. I threw in the Coupons thing just for affect. Outside of that, we are just adding cells to the table.
Now we have both of our tables. After we have them, we then add a barcode to this. The built in barcode support did impress me.
private void addBarcode(PdfWriter writer,PdfPTable table){ PdfContentByte cb = writer.getDirectContent(); BarcodeEAN codeEAN = new BarcodeEAN(); codeEAN.setCodeType(Barcode.EAN13); codeEAN.setCode("9780201615883"); Image imageEAN = codeEAN.createImageWithBarcode(cb, null, null); PdfPCell cell = new PdfPCell(imageEAN,false); cell.setPaddingTop(10); cell.setHorizontalAlignment(Element.ALIGN_LEFT); cell.setColspan(2); cell.setBorder(0); table.addCell(cell); }
It is pretty simple to do this. You create your Barcode object, which there is an object for each type of barcode. After that, you just set your code type and code, then create an image out of it. You can just treat it the same way you treated the first image. Add it to the cell and then add that cell to the table.
At this point, we are almost done. Last thing we would like to do is add a link at the bottom of our PDF. I just referred back to the website. Obviously in a real world situation, you would have this link back to maybe their order form or shipping status or something. Here, we are just going to link back to the website. Looking back to our first snip of code, we can see that adding our anchor object is pretty simple.
Paragraph p = new Paragraph("\n\nFor more, please visit "); Anchor anchor = new Anchor("www.codeofdoom.com/wordpress", FontFactory.getFont(FontFactory.TIMES_ROMAN, 12, Font.UNDERLINE, new Color(0, 0, 255))); p.add(anchor); d.add(p);
Here we create a Paragraphy with our text. This will not be part off our link. The Anchor is where we create our link. The first parameter is meant for the address. The next paramter is the defaults to create the blue look that is normally on a link. If you dont, then you are just left with the standard black text. After this, you are all set. Just close the main Document object and you are done.
Creating PDFs on the fly using iText is pretty straight forward, especially if you have any html experience. It did have a little bit of a learning curve. It seems that there are a lot of cases where you need to create helper functions in order to format your cells easier. They did a great job on providing many examples on their website, but I did not really care for the amount of detail, or lack thereof, within the documentation. Even with that though, it was still easy enough to create this whole project within a short amount of time. Outside of this example, there are plenty of addition functionality that comes with iText that I did not cover. It would be worth it to check out their examples section.
Grab the source code here
PS
Since I do a lot of Flex examples, I did want to point this out. AlivePDF is a pure 100% client side PDF generator for Flex. It seems to be in an early alpha stage (Version 0.1.4.8), but it is definitely worth keeping an eye on. Although maybe it further along than I thought since its been in dev since November ‘07. Anyways, check it out.
Hi
I’m going to take this chance to promote the open source Flying Saucer XML/CSS renderer, which can take XHTML (or clean HTML) and CSS and output to PDF (on-screen output via Swing and image rendering available as well). Generating PDFs using FS has become one of the most popular uses of the library, as people can reuse their HTML/CSS skills and tools and get the output they want. If you’re interested, you can find it at http://xhtmlrenderer.dev.java.net.
Cheers
Patrick
FS Team
it’s iText (lowercase “i”), you idiot
@you daddy
Fixed it for you.
Hey, thank you for your article. I learned about it through Twitter; I posted a tweet about it that is forwarded to the front page of http://1t3xt.com/
People eager to learn more about iText may find the keyword and example pages interesting: http://1t3xt.info/tutorials/keywords and http://1t3xt.info/examples
Best regards,
Bruno
Bruno,
Thanks for spreading the word and I’m glad you enjoyed the article
. I’ll definitely check out the examples later on.
Thanks again!
Marcel
good written, complete and helpful, thanks!
@you daddy
you are an a hole
@Marcel
@you daddy, I bet you don’t know much more than how to spell it, do you?!
This is great example for every one ,what a wonderful example for pdf
thanks for ever it is helps more for me