INTRODUCCIÓN:

En Java, a la hora de crear documentos PDF, existen múltiples librerias que nos ayudan a generarlos, en este articulo vamos a hablar sobre la librería ITEXT.

ITEXT a parte de ser una buena librería para generar PDFs tiene la ventaja de que se integra facilmente con SPRING a la hora de desarrollar aplicaciones Web.

Los datos pueden ser escritos a un fichero o, por ejemplo, desde un servlet a un navegador web.

CARACTERÍSTICAS PRINCIPALES:

- Generación de documentos PDF (parrafos, tablas, imágenes, encabezados y pies de pagina…)

- Generar documentos dinámicos a partir de archivos XML o bases de datos

- Agregar marcadores de libros, números de página, marcas de agua, etc

- Split, concatenar, y manipular las páginas PDF

- Automatizar el llenado de formularios PDF

- Agregar firma digital a un archivo PDF

INSTALACIÓN:

Para empezar veamos donde descargarnos la librería

Esta es la web de la librería, aquí se puede ver la API, ejemplos y tutoriales:

http://itextpdf.com/

Una vez que seleccionamos descargrnos la version para Java nos redirecciona a esta otra página:

http://sourceforge.net/projects/itext/files/

Actualmente la versión más reciente es la 5.0.2

Una vez nos hemos descargado la librería, la añadimos al CLASSPATH de nuestro proyecto Java para poder utilizarla

EJEMPLO:

Este ejemplo abarca la creación de un documento PDF simple, para ver ejemplos mas complejos nos podemos descargar de la propia página muchos ejemplos que abarcan toda la funcionalidad de esta libreria:

http://www.itextpdf.com/examples/index.php

CÓDIGO:

import java.io.FileOutputStream;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.FontFactory;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.Font.FontFamily;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfPageEventHelper;
import com.itextpdf.text.pdf.PdfWriter;

public class Test {
 
 //Nombre del fichero PDF Resultante de la ejecucion
 public static final String RESULT = “Ejemplo1.pdf”;
 //Titulos
 public static final String CHUNK = “CHUNK”;
 public static final String PHRASE = “PHRASE”;
 public static final String PARAGRAPH = “PARAGRAPH”;
 public static final String TABLE = “TABLE”;
 public static final String IMAGE = “IMAGE”;
 //Textos
 public static final String SEPARADOR = “———————————————————————————————————————-”;
 public static final String CHUNK1 = “This is the smallest significant part of text that can be added to a document.”;
 public static final String CHUNK2 = “Most elements can be divided in one or more Chunks. A chunk is a String with a certain Font. All other layout parameters should be defined in the object to which this chunk of text is added.”;
 public static final String PHRASE1 = “A Phrase is a series of Chunks.”;
 public static final String CHUNKPHRASE21 = “A Phrase has a main Font,”;
 public static final String CHUNKPHRASE22 = ” but some chunks within the phrase can have a Font that differs from the main Font.”;
 public static final String CHUNKPHRASE23 = ” All the Chunks in a Phrase  have the same leading.”;
 public static final String PARAGRAPH1 = “A Paragraph is a series of Chunks and/or Phrases.”;
 public static final String PARAGRAPH2 = “A Paragraph has the same qualities of a Phrase, but also some additional layout-parameters: The indentation AND The alignment of the text”;

    public static void main (String[] args) {
     try
     {
      //Creacion del documento con un tamaño y unos margenes predeterminados
      Document document = new Document(PageSize.A4, 50, 50, 50, 50);
      //Al documento se le puede añadir cierta metaInformacion
      document.addAuthor(“FJHO”);
      document.addTitle(“EJEMPLO1″);

      //A DocWriter class for PDF.
      //When this PdfWriter is added to a certain PdfDocument,
      //the PDF representation of every Element added to this Document will be written to the outputstream.
      PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(RESULT));
         //LEADING = separacion entre lineas del documento
         writer.setInitialLeading(16);
         Rectangle rct = new Rectangle(36, 54, 559, 788);
         //Definimos un nombre y un tamaño para el PageBox los nombres posibles son: “crop”, “trim”, “art” and “bleed”.
         writer.setBoxSize(“art”, rct);
        
         //Se crea una instancia de la clase que pinta la cabecera y el pie de pagina y se le asignan los eventos que ocurran en el PDF
         //La en la clase HeaderFooter se capturarar el evento onEndPage para pintarlos
            HeaderFooter event = new HeaderFooter();
            writer.setPageEvent(event);
           
         //Opens the document.
            //You have to open the document before you can begin to add content to the body of the document.
         document.open();
         //Ejemplos de CHUNKS
          //Creamos el CHUNK definiendo su tipo de letra, tamaño…
          Chunk titulo = new Chunk(CHUNK, FontFactory.getFont(FontFactory.COURIER, 20, Font.UNDERLINE, BaseColor.BLACK));
          //Lo añadimos al documento
          document.add(titulo);
          //CHUNK predefinido, es un salto de linea
          document.add(Chunk.NEWLINE);
          Chunk chunkSeparador =  new Chunk(SEPARADOR);
          Chunk chunkNormal = new Chunk(CHUNK1);
          document.add(chunkNormal);
          document.add(Chunk.NEWLINE);
          document.add(Chunk.NEWLINE);
          Chunk chunkTunning = new Chunk(CHUNK2,FontFactory.getFont(FontFactory.COURIER, 20, Font.ITALIC, BaseColor.GREEN));
          document.add(chunkTunning);
          document.add(Chunk.NEWLINE);
          document.add(Chunk.NEWLINE);
          Chunk chunkTunning2 = new Chunk(CHUNK2,new Font(FontFamily.HELVETICA, 6, Font.BOLD, BaseColor.WHITE));
          chunkTunning2.setBackground(BaseColor.BLACK, 10f, 10f, 10f, 10f);
          document.add(chunkTunning2);
          document.add(Chunk.NEWLINE);
          document.add(Chunk.NEWLINE);
          document.add(Chunk.NEWLINE);
          document.add(chunkSeparador);         
         //FIN Ejemplos de CHUNKS      
         //**************************************************************
         //Ejemplos de PHRASES
          titulo = new Chunk(PHRASE, FontFactory.getFont(FontFactory.COURIER, 20, Font.UNDERLINE, BaseColor.BLACK));
          document.add(titulo);
          document.add(Chunk.NEWLINE);
          Phrase phraseNormal = new Phrase(PHRASE1);
          document.add(phraseNormal);
          document.add(Chunk.NEWLINE);
          document.add(Chunk.NEWLINE);
          Phrase phraseTunning = new Phrase(new Chunk(CHUNKPHRASE21));
          phraseTunning.add(new Chunk(CHUNKPHRASE22, FontFactory.getFont(FontFactory.COURIER, 5, Font.ITALIC, BaseColor.GREEN)));
          phraseTunning.add(new Chunk(CHUNKPHRASE23, FontFactory.getFont(FontFactory.TIMES_ROMAN, 15, Font.BOLD, BaseColor.ORANGE)));
          document.add(phraseTunning);
          document.add(Chunk.NEWLINE);
          document.add(Chunk.NEWLINE);
          Phrase phraseConLeading = new Phrase(30, “Todo es la misma frase LEADING de esta PHRASE=100, Todo es la misma frase LEADING de esta PHRASE=100, Todo es la misma frase LEADING de esta PHRASE=100″);
          document.add(phraseConLeading);
          document.add(Chunk.NEWLINE);
          document.add(chunkSeparador);         
         //FIN Ejemplos de PHRASES
         //**************************************************************
         //Ejemplos de PARAGRAPH
          titulo = new Chunk(PARAGRAPH, FontFactory.getFont(FontFactory.COURIER, 20, Font.UNDERLINE, BaseColor.BLACK));
          document.add(titulo);
          document.add(Chunk.NEWLINE);
          // Añadir parrafo sin formato
          document.add(new Paragraph(PARAGRAPH1));
          Paragraph par = new Paragraph(PARAGRAPH2);
          par.setIndentationLeft(200);
          document.add(par);
          par = new Paragraph(PARAGRAPH2);
          par.setIndentationRight(300);
          document.add(par);
          // Añadir parrafo en Negrita           
          par = new Paragraph(PARAGRAPH2);
             par.getFont().setStyle(Font.BOLD);
             par.setAlignment(Element.ALIGN_CENTER);
             document.add(par);
          // Añadir parrafo en Cursiva
             par = new Paragraph(PARAGRAPH2);
             par.getFont().setStyle(Font.ITALIC);
             par.setAlignment(Element.ALIGN_RIGHT);
             document.add(par);
             // Añadir parrafo tunning
             par = new Paragraph(PARAGRAPH2,
         FontFactory.getFont(“arial”,   // fuente
              16,                    // tamaño
              Font.ITALIC,           // estilo
              BaseColor.RED));       // color
             document.add(par);
             par.setAlignment(Element.ALIGN_LEFT);
             document.add(chunkSeparador); 
             document.add(Chunk.NEWLINE);
             document.add(Chunk.NEWLINE);
         //FIN Ejemplos de PARAGRAPH
         //**************************************************************            
         //Ejemplos de TABLE
             titulo = new Chunk(TABLE, FontFactory.getFont(FontFactory.COURIER, 20, Font.UNDERLINE, BaseColor.BLACK));
          document.add(titulo);
             //Añadir tabla 5 columnas
             PdfPTable table = new PdfPTable(5);
            //Añadir CABECERA
             PdfPCell cell = new PdfPCell(new Phrase(“CABECERA”));
             cell.setColspan(5);
             cell.setBackgroundColor(BaseColor.GREEN);
             table.addCell(cell);
             //Añadir dos filas de celdas sin formato
             table.addCell(“1.1″);
             table.addCell(“1.2″);
             table.addCell(“1.3″);
             table.addCell(“1.4″);
             table.addCell(“1.5″);
             table.addCell(“2.1″);
             table.addCell(“2.2″);
             table.addCell(“2.3″);
             table.addCell(“2.4″);
             table.addCell(“2.5″);
             //tunning de Celdas
             cell = new PdfPCell(new Phrase(“Alto 3 celdas”));
             cell.setRowspan(2);
             cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
             table.addCell(cell);
             table.addCell(“3.1″);
             table.addCell(“3.2″);
             table.addCell(“3.3″);
             table.addCell(“3.4″);
             table.addCell(“4.1″);
             table.addCell(“4.2″);
             table.addCell(“4.3″);
             table.addCell(“4.4″);
             table.addCell(“5.1″);
             cell = new PdfPCell(new Phrase(“Ancho 4 celdas”));
             cell.setHorizontalAlignment(Element.ALIGN_CENTER);
             cell.setColspan(4);
             table.addCell(cell);
             document.add(table);
             document.add(chunkSeparador);
         //FIN Ejemplos de TABLE
      //**************************************************************   
         //Ejemplos de IMAGE
             titulo = new Chunk(IMAGE, FontFactory.getFont(FontFactory.COURIER, 20, Font.UNDERLINE, BaseColor.BLACK));
          document.add(titulo);
       Image foto = Image.getInstance(“resources/ferrari.jpg”);
       foto.scaleToFit(100, 100);
       foto.setAlignment(Chunk.ALIGN_MIDDLE);
       document.add(foto);
      //FIN Ejemplos de IMAGE      
      //**************************************************************
      // Cierre del documento
         document.close();
     } catch (Exception ex) {
         System.out.println(ex.getMessage());
     }
    }
   
    static class HeaderFooter extends PdfPageEventHelper {

        public void onEndPage (PdfWriter writer, Document document) {
            Rectangle rect = writer.getBoxSize(“art”);
            //CABECERA
            ColumnText.showTextAligned(writer.getDirectContent(),
                    Element.ALIGN_RIGHT, new Phrase(“LaMandarinaMecanica”),
                    rect.getRight(), rect.getTop(), 0);
            //PIE
            ColumnText.showTextAligned(writer.getDirectContent(),
                    Element.ALIGN_CENTER, new Phrase(String.format(“page %d”, writer.getPageNumber())),
                    (rect.getLeft() + rect.getRight()) / 2, rect.getBottom() – 18, 0);
        }
    }

WEB:

Si lo que necesitamos es generar documentos PDF dinamicamente que se le abran al usuario directamente al interactuar con una página web (pinchar botones, links…), podemos crear un servlet que reciba las peticiones de creacion de ficheros PDF

CÓDIGO:

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;

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

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfWriter;

public class Demo extends HttpServlet {

 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  doPost(request, response);
 }
 
 public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
  
  /*GENERACION AL VUELO DE PDF*/
  try {
            // Texto que va a ser añadido al PDF
            String text = “Generacion al Vuelo de un PDF”;
           
            // Paso 1: Creamos el documento
            Document document = new Document();
            // Paso 2: Creamos un ByteArrayOutputStream
            // todo lo que se escriba en el documento
            // se escribe tambien en el ByteArrayOutputStream
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            PdfWriter.getInstance(document, baos);
            // Abrimos el documento
            document.open();
            // Escribimos
            document.add(new Paragraph(text));
            // Cerramos
            document.close();
           
            // Hay que configurar las cabeceras para que
            //el navegador detecte que es un PDF
            response.setHeader(“Expires”, “0″);
            response.setHeader(“Cache-Control”,
                “must-revalidate, post-check=0, pre-check=0″);
            response.setHeader(“Pragma”, “public”);
            // Configuramos el content type
            response.setContentType(“application/pdf”);
            // Tamaño
            response.setContentLength(baos.size());
            // Esccribir el ByteArrayOutputStream a el ServletOutputStream
            OutputStream os = response.getOutputStream();
            baos.writeTo(os);
            os.flush();
            os.close();
        }
        catch(com.itextpdf.text.DocumentException e) {
            throw new IOException(e.getMessage());
        }
    }
}