Showing posts with label itext. Show all posts
Showing posts with label itext. Show all posts

Wednesday, 13 April 2011

Jfreechart : Charting tools in java

iText is a wonderful library if you want to generate PDFs in Java. It comes with a huge set of API to create/manage a PDF file. IText can be used in cases like : how to generate a pdf file in itext and also how to merge two pdf  or splitting pdf files using itext.
In this tutorial we will see how to generate Pie charts and Bar charts in Java using iText and jFreeChart library. First a brief note about jFreeChart.
JFreeChart is a free 100% Java chart library that makes it easy for developers to display professional quality charts in their applications. It gives a wide range of API to generate charts and graphs in Java.

Step 1: Download required Jar files

For this example we will need following jar files.
  • iText-2.1.5.jar (download)
  • jcommon-1.0.16.jar
  • jfreechart-1.0.13.jar
Download the jFreeChart jars from: http://sourceforge.net/projects/jfreechart/files/

Step 2: Generating Pie Charts/Bar Graph using jFreeChart

Next we will use jFreeChart library and generate the pie and bar charts.
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.general.DefaultPieDataset;

public class PieChartDemo {
public static void main(String[] args) {
//TODO: Add code to generate PDFs with charts
}

public static JFreeChart generatePieChart() {
DefaultPieDataset dataSet = new DefaultPieDataset();
dataSet.setValue("China", 19.64);
dataSet.setValue("India", 17.3);
dataSet.setValue("United States", 4.54);
dataSet.setValue("Indonesia", 3.4);
dataSet.setValue("Brazil", 2.83);
dataSet.setValue("Pakistan", 2.48);
dataSet.setValue("Bangladesh", 2.38);

JFreeChart chart = ChartFactory.createPieChart(
"World Population by countries", dataSet, true, true, false);

return chart;
}

public static JFreeChart generateBarChart() {
DefaultCategoryDataset dataSet = new DefaultCategoryDataset();
dataSet.setValue(791, "Population", "1750 AD");
dataSet.setValue(978, "Population", "1800 AD");
dataSet.setValue(1262, "Population", "1850 AD");
dataSet.setValue(1650, "Population", "1900 AD");
dataSet.setValue(2519, "Population", "1950 AD");
dataSet.setValue(6070, "Population", "2000 AD");

JFreeChart chart = ChartFactory.createBarChart(
"World Population growth", "Year", "Population in millions",
dataSet, PlotOrientation.VERTICAL, false, true, false);

return chart;
}
}

n above code, we have created two methods that returns JFreeChart object. These methods creates charts using jFreeChart API. Note that we have used dummy data. In real example these values must be dynamically fetched from database or other data source.

Now we can do various stuff with these charts.

Eg. Generating pdf files from these charts.
So change the main method and add following code to above code:

public static void main(String[] args) {
writeChartToPDF(generateBarChart(), 500, 400, "C://barchart.pdf");
writeChartToPDF(generatePieChart(), 500, 400, "C://piechart.pdf");
}
public static void writeChartToPDF(JFreeChart chart, int width, int height, String fileName) {
PdfWriter writer = null;

Document document = new Document();

try {
writer = PdfWriter.getInstance(document, new FileOutputStream(
fileName));
document.open();
PdfContentByte contentByte = writer.getDirectContent();
PdfTemplate template = contentByte.createTemplate(width, height);
Graphics2D graphics2d = template.createGraphics(width, height,
new DefaultFontMapper());
Rectangle2D rectangle2d = new Rectangle2D.Double(0, 0, width,
height);

chart.draw(graphics2d, rectangle2d);

graphics2d.dispose();
contentByte.addTemplate(template, 0, 0);

} catch (Exception e) {
e.printStackTrace();
}
document.close();
}

In above code we have created a method writeChartToPDF() which take few arguments like jFreeChart object, width, height and filename and write a PDF files in that file.
java-bar-chart-pdf
java-pdf-pie-chart
This is ofcourse very preliminary example of adding pie charts in PDF using Java iText/jFreeChart. But atleast it gives basic idea of how to achieve this. Feel free to modify the above code and play around to generate different charts/graphs in PDF.

You can refer to following book for  more reading on jfreechart:

Split PDF files in Java using iText JAR

Consider the following code in java:

public static void splitPDF(InputStream inputStream,
OutputStream outputStream, int fromPage, int toPage) {
Document document = new Document();
try {
PdfReader inputPDF = new PdfReader(inputStream);

int totalPages = inputPDF.getNumberOfPages();

//make fromPage equals to toPage if it is greater
if(fromPage > toPage ) {
fromPage = toPage;
}
if(toPage > totalPages) {
toPage = totalPages;
}

// Create a writer for the outputstream
PdfWriter writer = PdfWriter.getInstance(document, outputStream);

document.open();
PdfContentByte cb = writer.getDirectContent(); // Holds the PDF data
PdfImportedPage page;

while(fromPage <= toPage) {
document.newPage();
page = writer.getImportedPage(inputPDF, fromPage);
cb.addTemplate(page, 0, 0);
fromPage++;
}
outputStream.flush();
document.close();
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (document.isOpen())
document.close();
try {
if (outputStream != null)
outputStream.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}

In above code, we have created a method splitPDF () that can be used to extracts pages out of a PDF and write it into another PDF. The code is pretty much self explanatory and is similar to the one to merge PDF files.
Thus, if you need to split an input.pdf (having 20 pages) into output1.pdf (1-12 pages of input.pdf) and output2.pdf (13-20 of input.pdf), you can call the above method as follow:

public static void main(String[] args) {
try {
MergePDF.splitPDF(new FileInputStream("C:\\input.pdf"),
new FileOutputStream("C:\\output1.pdf"), 1, 12);
MergePDF.splitPDF(new FileInputStream("C:\\input.pdf"),
new FileOutputStream("C:\\output2.pdf"), 13, 20);

} catch (Exception e) {
e.printStackTrace();
}
}

iText tutorial:Merge PDF files using iText JAR

Previous article Generating PDF files using iText JAR had described a nice and basic way of generating PDF files in Java using iTest JAR. It is a great starter tutorial for those who wants to start working with iText.
In one of the requirement, I had to merge two or more PDF files and generate a single PDF file out of it. I thought of implementing the functionality from scratch in iText, but then thought to google it and see if already someone have written code for what I was looking for. As expected, I got a nice implementation of java code that merges 2 or more PDF files using iText jar. I thought of dissecting the code in this post and give credit to original author of the post.

  1. Create a PdfReader for each input PDF file
    PdfReader pdfReader = new PdfReader(pdf);
  2. Create a document object to represent the PDF.
    Document document = new Document();
  3. Create a PdfWriter for the target OutputStream
    PdfWriter writer = PdfWriter.getInstance(document, outputStream);
  4. Select a font with which the page numbers will be written
    BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
  5. Create a a PdfContentByte object to hold the data of the merged PDF
    PdfContentByte cb = writer.getDirectContent();
  6. Add individual pages from the source to the target.
    document.newPage();
    pageOfCurrentReaderPDF++;
    currentPageNumber++;
    page1 = writer.getImportedPage(pdfReader, pageOfCurrentReaderPDF);
    cb.addTemplate(page1, 0, 0);
  7. Add page text at the bottom of the page
    cb.beginText();
    cb.setFontAndSize(bf, 9);
    cb.showTextAligned(PdfContentByte.ALIGN_CENTER, "Page " + currentPageNumber + " of " + totalPages, 520, 5, 0);
    cb.endText();
public class MergePDF {
public static void main(String[] args) {
try {
List<InputStream> pdfs = new ArrayList<InputStream>();
pdfs.add(new FileInputStream("c:\\pdf\\2.pdf"));
pdfs.add(new FileInputStream("c:\\pdf\\3.pdf"));
OutputStream output = new FileOutputStream("c:\\pdf\\merge.pdf");
MergePDF.concatPDFs(pdfs, output, true);
} catch (Exception e) {
e.printStackTrace();
}
}

public static void concatPDFs(List<InputStream> streamOfPDFFiles, OutputStream outputStream, boolean paginate) {

Document document = new Document();
try {
List<InputStream> pdfs = streamOfPDFFiles;
List<PdfReader> readers = new ArrayList<PdfReader>();
int totalPages = 0;
Iterator<InputStream> iteratorPDFs = pdfs.iterator();

// Create Readers for the pdfs.
while (iteratorPDFs.hasNext()) {
InputStream pdf = iteratorPDFs.next();
PdfReader pdfReader = new PdfReader(pdf);
readers.add(pdfReader);
totalPages += pdfReader.getNumberOfPages();
}
// Create a writer for the outputstream
PdfWriter writer = PdfWriter.getInstance(document, outputStream);

document.open();
BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
PdfContentByte cb = writer.getDirectContent(); // Holds the PDF
// data

PdfImportedPage page;
int currentPageNumber = 0;
int pageOfCurrentReaderPDF = 0;
Iterator<PdfReader> iteratorPDFReader = readers.iterator();

// Loop through the PDF files and add to the output.
while (iteratorPDFReader.hasNext()) {
PdfReader pdfReader = iteratorPDFReader.next();

// Create a new page in the target for each source page.
while (pageOfCurrentReaderPDF < pdfReader.getNumberOfPages()) {
document.newPage();
pageOfCurrentReaderPDF++;
currentPageNumber++;
page = writer.getImportedPage(pdfReader, pageOfCurrentReaderPDF);
cb.addTemplate(page, 0, 0);

// Code for pagination.
if (paginate) {
cb.beginText();
cb.setFontAndSize(bf, 9);
cb.showTextAligned(PdfContentByte.ALIGN_CENTER, "" + currentPageNumber + " of " + totalPages, 520, 5, 0);
cb.endText();
}
}
pageOfCurrentReaderPDF = 0;
}
outputStream.flush();
document.close();
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (document.isOpen())
document.close();
try {
if (outputStream != null)
outputStream.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
}

Thanks.

Setting attributes of PDF using itext

While you generate a PDF, you may want to set its different attribute like: author name, title, file description etc. iText jar can help you to set different attributes of a PDF file. Document object provide different methods to add various attributes to a PDF file.

document.addAuthor("Vaani");
document.addCreationDate();
document.addCreator("iText library");
document.addTitle("Hello World PDF");

Generate PDF as Output Stream in HTTP request using itext

Sometime we may want to add the PDF generation functionality to a web application, where user on clicking some link or button is served with PDF output. Hence the PDF should be generated on fly and sent to client browser.
Consider following simple action class for Struts which uses this mechanism to generate a dummy PDF and sent the output to browser.

import java.util.Date;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import com.lowagie.text.Document;
import com.lowagie.text.Paragraph;
import com.lowagie.text.pdf.PdfWriter;


public class PdfHelloWorldAction extends Action{

public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {

Document document = new Document();
try{
response.setContentType("application/pdf");
PdfWriter.getInstance(document, response.getOutputStream());
document.open();
document.add(new Paragraph("Hello vaani"));
document.add(new Paragraph(new Date().toString()));
}catch(Exception e){
e.printStackTrace();
}
document.close();
return null;

}
}

Notice that, we have passed response.getOutputStream() object to getInstance() method. Thus the output generated by iText will be sent directly to the response. Also don’t forget to set the content type of the response to application/pdf.

PDF Generation in Java using iText JAR

Generating PDF files in today’s enterprise applications is quite common. Doing this with Java is not an easy task as Java does not gives default api’s to handle PDF files. No worries, iText jar is for you.
iText is a free Java-PDF library that allows you to generate PDF files on the fly (dynamically). iText is an ideal library for developers looking to enhance web- and other applications with dynamic PDF document generation and/or manipulation. iText is not an end-user tool. Typically you won’t use it on your Desktop as you would use Acrobat or any other PDF application. Rather, you’ll build iText into your own applications so that you can automate the PDF creation and manipulation process.

iText (Java-PDF Library) can be used to:

  1. Serve PDF to a browser
  2. Generate dynamic documents from XML files or databases
  3. Use PDF’s many interactive features
  4. Add bookmarks, page numbers, watermarks, etc.
  5. Split, concatenate, and manipulate PDF pages
  6. Automate filling out of PDF forms
  7. Add digital signatures to a PDF file

Technical Requirements to use iText

You should have JDK 1.4 or later to integrate iText PDF generation in your application.

Getting iText

Download iText jar from its home page http://www.lowagie.com/iText/download.html
iText core: iText-2.1.5.jar

Generate simple PDF in Java using free Java-PDF library

It is very easy to generate a simple PDF file in Java using iText. All you have to do is to put itext.jar in your class path and paste following code in GeneratePDF.java class and compile and execute it. After you execute this, a file Test.pdf will be created in C: drive (If you are using Linux, you may want to have /usr/test.pdf as path).

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.Date;

import com.lowagie.text.Document;
import com.lowagie.text.Paragraph;
import com.lowagie.text.pdf.PdfWriter;

//Now in some class write this function
public static void generatePDF () {
try {
OutputStream file = new FileOutputStream(new File("C:\\Test.pdf"));

Document document = new Document();
PdfWriter.getInstance(document, file);
document.open();
document.add(new Paragraph("Hello Kiran"));
document.add(new Paragraph(new Date().toString()));

document.close();
file.close();

} catch (Exception e) {

e.printStackTrace();
}
}

In above code snippet we have created Document object which represents our PDF document. Also, by supplying OutputStream object to getInstance() method sends the output to OutputStream. Thus in our case we have created a output file and sent output to it.