Encabezados, pie de pagina y conteo de paginas en iText 7

Estándar

Recientemente la librería iText ha liberado su nueva versión la 7.0.2 y en algo que honestamente espero no se haga costumbre (aunque hay mal precedente si recuerda el cambio de la versión 4 a la 5…) las clases y varios de los métodos han sido re escritos desde cero, ¿Como le afecta esto? pues si quiere hacer uso de la versión mas reciente toca hacer una reescritura significativa ya que la versión 5 y 7 no son compatibles entre si y no espere que los ejemplos previos le ayuden.

Esto es particularmente latoso si ya estaba creando encabezado y conteos de pagina como se había descrito en este blog previamente (para la versión 5 de iText), pero no desespere, aquí esta como hacerlo en iText 7

Documento pdf con encabezado y pie de pagina

Documento pdf con encabezado y pie de pagina

En esta entrada veremos como usar iText 7 y el nuevo modelo de eventos para crear un encabezado con un mensaje personalizable y un pie de pagina con el numero de pagina actual, para evitar confundirlo si no a usado iText antes y que esta entrada sea demasiado larga, no se haran comparaciones con la versión anterior y nos enfocaremos en como hacerlo en iText 7.

Agregando iText 7 a su proyecto

Configuración Maven de iText 7

Configuración Maven de iText 7

Para este ejemplo usaremos Maven para agregar las librerias al proyecto, puede usar ya sea el pom.xml o agregar la dependencia itext7-core via NetBeans en este ejemplo usaremos la versión 7.0.2.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>mx.hashSoft</groupId>
    <artifactId>iText7</artifactId>
    <version>1.0</version>
    <packaging>jar</packaging>
    <dependencies>
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext7-core</artifactId>
            <version>7.0.2</version>
            <type>pom</type>
        </dependency>
    </dependencies>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
    </properties>
</project>

Eventos de documento

El ejemplo que usaremos para explicar el uso de iText 7 es bastante sencillo, crea un documento pdf el cual solo contendrá lineas y lineas de “Hola Mundo!” y que tendrá un encabezado con el mensaje “Departamento de Recursos Humanos” y un pie de pagina con el numero de pagina actual.

El pie de pagina y encabezado son creados por una clase que implementa la interfaz IEventHandler esta clase se agrega como manejador de evento al objecto documento y se indica cual evento manejara, de modo que se pueden tener múltiples clases manejando diferentes eventos en el mismo documento.

En este caso particular manejaremos el evento PdfDocumentEvent.END_PAGE el cual se activa cuando se llega al final de la pagina, en este punto agregamos el encabezado, pie de pagina y obtendremos el numero de pagina en el que vamos.

Canvas y rectángulos

Al ver el código de la clase EventoPagina seguramente notara que aparte de las tablas que contienen el texto que deseamos mostrar notara que se crean varios objectos Canvas y Rectangle estos cumplen una función muy simple ya que nos permiten colocar los objectos Table donde queramos, sin mover los demás elementos, el objeto Rectangle indica el área donde colocaremos la tabla y con el objecto Canvas lo dibujaremos en ese lugar.

Código

Ahora si vamos a lo bueno, para este ejemplo usaremos dos clases la ya mencionada EventoPagina la cual manejara el evento PdfDocumentEvent.END_PAGE e iText7 esta clase crea el documento Pdf y su contenido, ambas clases tienen comentarios que espero sean suficientes para hacer comprensible su función.

package mx.hashsoft.itext7;

import com.itextpdf.kernel.events.PdfDocumentEvent;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Paragraph;
import java.io.FileNotFoundException;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author david
 */
public class iText7 {

    static public void main(String[] args) {
        try {
            // Creamos el escritor del archivo pdf
            PdfWriter pdfWriter = new PdfWriter("./ejemplo_itext7.pdf");
            // Creamos el documento PDF que se almacenara via el escritor
            PdfDocument pdfDoc = new PdfDocument(pdfWriter);
            // Creamos el documento pdf en si, con pagina tamaño letra
            Document doc = new Document(pdfDoc, PageSize.LETTER);
            // Creamos el manejador de evento de pagina, el cual agregara
            // el encabezado y pie de pagina
            EventoPagina evento = new EventoPagina(doc);

            // Indicamos que el manejador se encargara del evento END_PAGE
            pdfDoc.addEventHandler(PdfDocumentEvent.END_PAGE, evento);
            
            // Establecemos los margenes
            doc.setMargins(75, 36, 75, 36);

            // Creamos el contenido, por motivos de ejemplo es solo Hola Mundo!
            // una y otra vez
            for (int i = 0; i < 450; i++) {
                doc.add(new Paragraph("Hola Mundo!"));
            }

            // Cerramos el documento
            doc.close();

        } catch (FileNotFoundException ex) {
            Logger.getLogger(iText7.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}
package mx.hashsoft.itext7;

import com.itextpdf.kernel.events.Event;
import com.itextpdf.kernel.events.IEventHandler;
import com.itextpdf.kernel.events.PdfDocumentEvent;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.layout.Canvas;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Table;

/**
 *
 * @author david
 */
public class EventoPagina implements IEventHandler {

    private final Document documento;

    public EventoPagina(Document doc) {
        documento = doc;
    }
    
    /**
     * Crea el rectangulo donde pondremos el encabezado
     * @param docEvent Evento de documento
     * @return Area donde colocaremos el encabezado
     */
    private Rectangle crearRectanguloEncabezado(PdfDocumentEvent docEvent) {
        PdfDocument pdfDoc = docEvent.getDocument();
        PdfPage page = docEvent.getPage();        
        
        float xEncabezado = pdfDoc.getDefaultPageSize().getX() + documento.getLeftMargin();
        float yEncabezado = pdfDoc.getDefaultPageSize().getTop() - documento.getTopMargin();
        float anchoEncabezado = page.getPageSize().getWidth() - 72;
        float altoEncabezado = 50F;

        Rectangle rectanguloEncabezado = new Rectangle(xEncabezado, yEncabezado, anchoEncabezado, altoEncabezado);
        
        return rectanguloEncabezado;        
    }
    
    /**
     * Crea el rectangulo donde pondremos el pie de pagina
     * @param docEvent Evento del documento
     * @return Area donde colocaremos el pie de pagina
     */
    private Rectangle crearRectanguloPie(PdfDocumentEvent docEvent) {
        PdfDocument pdfDoc = docEvent.getDocument();
        PdfPage page = docEvent.getPage();
        
        float xPie = pdfDoc.getDefaultPageSize().getX() + documento.getLeftMargin();
        float yPie = pdfDoc.getDefaultPageSize().getBottom() ;
        float anchoPie = page.getPageSize().getWidth() - 72;
        float altoPie = 50F;

        Rectangle rectanguloPie = new Rectangle(xPie, yPie, anchoPie, altoPie);
        
        return rectanguloPie;
    }
    
    /**
     * Crea la tabla que contendra el mensaje del encabezado
     * @param mensaje Mensaje que desplegaremos
     * @return Tabla con el mensaje de encabezado
     */
    private Table crearTablaEncabezado(String mensaje) {
        float[] anchos = {1F};
        Table tablaEncabezado = new Table(anchos);
        tablaEncabezado.setWidth(527F);

        tablaEncabezado.addCell(mensaje);
        
        return tablaEncabezado;
    }
    
    /**
     * Crea la tabla de pie de pagina, con el numero de pagina
     * @param docEvent Evento del documento
     * @return Pie de pagina con el numero de pagina
     */
    private Table crearTablaPie(PdfDocumentEvent docEvent) {
        PdfPage page = docEvent.getPage();
        float[] anchos = {1F};
        Table tablaPie = new Table(anchos);
        tablaPie.setWidth(527F);
        Integer pageNum = docEvent.getDocument().getPageNumber(page);
        
        tablaPie.addCell("Pagina " + pageNum);
        
        return tablaPie;
    }
    

    /**
     * Manejador del evento de cambio de pagina, agrega el encabezado y pie de pagina
     * @param event Evento de pagina
     */
    @Override
    public void handleEvent(Event event) {
        PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
        PdfDocument pdfDoc = docEvent.getDocument();
        PdfPage page = docEvent.getPage();
        PdfCanvas canvas = new PdfCanvas(page.newContentStreamBefore(), page.getResources(), pdfDoc);        
        
        Table tablaEncabezado = this.crearTablaEncabezado("Departamento de Recursos Humanos");
        Rectangle rectanguloEncabezado = this.crearRectanguloEncabezado(docEvent);        
        Canvas canvasEncabezado = new Canvas(canvas, pdfDoc, rectanguloEncabezado);        
        canvasEncabezado.add(tablaEncabezado);      

        Table tablaNumeracion = this.crearTablaPie(docEvent);
        Rectangle rectanguloPie = this.crearRectanguloPie(docEvent);
        Canvas canvasPie = new Canvas(canvas, pdfDoc, rectanguloPie);        
        canvasPie.add(tablaNumeracion);
    }
}

Espero que esta entrada halla sido de utilidad y nos vemos en la próxima :).

Anuncios

Organización del código de un proyecto iText

Estándar

En uno de los comentarios de la entrada iText, Generación de archivo Pdf en Java se me pregunto si había una forma de no poner todo el código de generación de archivo en un solo método y separarlo en métodos mas concisos y que sigan mejor las practicas y convenciones de Java, esto es perfectamente posible y aquí presentare un ejemplo de como hacerlo aunque cabe mencionar que este es un ejemplo bastante simple, pero tiene como objeto dar una idea de como hacerlo.

Figura 1 - Proyecto iText

Figura 1 – Proyecto iText

Antes de comenzar, como vemos en la Figura 1, es necesario que cree un proyecto en Eclipse que contenga las librerías iText, en entradas anteriores del blog puede encontrar como configurar el proyecto , a su vez necesitara agregar una imagen en la raíz del proyecto, como se ve en la figura 2, con el fin de que el programa pueda agregarla al documento final.

Figura 2 - Archivos del proyecto

Figura 2 – Archivos del proyecto

Ya que tenga la imagen y las librerías listas procederemos con el código, el cual puede ver en la siguiente sección, en este caso el proyecto contiene dos clases, una que se contiene los métodos de creación del documento pdf y otra con el método principal.

Codigo

// Modular.java

package mx.com.hashSoft.iTextModular;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Image;
/**
* Clase de ejemplo de como organizar el uso de la libreria iText
* Generando el archivo desde un punto del programa y agregando los
* elementos desde metodos especializados
*
* Esta clase esta pensada como un ejemplo de como organizar el codigo de un proyecto de iText
* @author david
*/

public class Modular {
      private Document documento;

      /**
      * Incializa el documento iText para agregar elementos, abre el documento por default
      * @param nombreArchivo Ruta del archivo pdf que se creara
      * @throws FileNotFoundException
      * @throws DocumentException
      */
      public Modular(String nombreArchivo) throws FileNotFoundException, DocumentException {
            setDocumento(new Document());

            PdfWriter.getInstance(documento, new FileOutputStream(nombreArchivo));
            documento.open();
      }

      /**
      * Agrega la cadena de texto indicada como un parrafo
      * @param parrafo Texto del parafo
      * @throws DocumentException
      */
      public void agregarParrafo(String parrafo) throws DocumentException {
            Paragraph par = new Paragraph(parrafo);
            documento.add(par);
      }

      /**
      * Agrega una imagen al documento
      * @param rutaImagen Ruta de la imagen a agregar
      * @throws MalformedURLException
      * @throws IOException
      * @throws DocumentException
      */
      public void agregarImagen(String rutaImagen) throws MalformedURLException, IOException, DocumentException {
            Image imagen = Image.getInstance(rutaImagen);
            documento.add(imagen);
      }

      /**
      * Cierra el documento
      */
      public void cerrarDocumento() {
            documento.close();
      }

      public Document getDocumento() {
            return documento;
      }

      public void setDocumento(Document documento) {
            this.documento = documento;
      }

}

/// Main.java

package mx.com.hashSoft.iTextModular;

import java.io.IOException;
import com.itextpdf.text.DocumentException;

public class Main {
      static public void main(String[] args) {
            Modular test;

            // Dentro del bloque try-catch creamos el archivo

            try {
                  test = new Modular(“archivo.pdf”);

                  // Agremaos un parrafo
                  test.agregarParrafo(“Parrafo de ejemplo del documento, despues de este agregaremos una imagen con el metodo agregarImagen”);

                  // una imagen, recuerde cambiar el nombre de la imagen por la que halla puesto en el directorio del proyecto
                  test.agregarImagen(“mickey_mouse.png”);

                  // Otro parrafo
                  test.agregarParrafo(“Segundo parrafo, ambos agregados con una llamada al metodo agregarParrafo”);

                  // Y finalmente cerramos el documento
                  test.cerrarDocumento();

            } catch (DocumentException | IOException e) {
                  System.out.println(“Error generando el archivo pdf.”);
                  e.printStackTrace();
            }
      }
}

Al ejecutar el programa debería aparecer un nuevo archivo pdf con el nombre indicado con el código en el directorio, como se ve en la figura 3

Figura 3 - Resultado del programa

Figura 3 – Resultado del programa

Y al abrir el archivo pdf veremos lo que hallamos escrito en los párrafos, como se ve en la figura 4

Figura 4 - Salida

Figura 4 – Salida

En este caso contare que la documentación agregada en el propio código detalla que hacen cada método, pero como puede observar los diferentes métodos que la librería iText pueden ser puestos en metodos separados, lo que nos da un código mas limpio y ordenado y dándonos la posibilidad de pasarles argumentos haciéndolos mas reusables, como vemos en el método main.

Espero que esta entrada halla sido de utilidad y nos vemos en la proxima :D.

Acceder a imagenes desde el .JAR con iText

Estándar

Al momento de crear un programa en java, es posible que desee hacerlo lo mas auto contenido posible, de modo que la instalación sea tan sencilla como copiar el archivo de una computadora a otra.

Una de las cosas que tienden a evitar que se pueda hacer esto son las imágenes que se usan para los documentos que el programa vaya a generar, usualmente el logotipo de la empresa, sin embargo es perfectamente posible almacenar el archivo *dentro* de nuestro archivo .JAR y que los documentos creados con iText puedan acceder a dicha imagen y presentarla en el documento.

Estructura del proyecto.

Para este ejemplo necesitara crear un proyecto en Eclipse donde agregue las librerías iText, puede tomar el proyecto como ejemplo, ya que halla agregado las librerias al proyecto cree el paquete mx.hashSoft.inJar como se ve la figura 1, no cree ninguna clase aun.

Figura 1 - Proyecto

Figura 1 – Proyecto

Ubicación de la imagen en el proyecto.

Como seguramente ya sabrá, un paquete de Java es una representación de una estructura de carpetas las cuales contienen el código del programa, pero también pueden contener cualquier tipo de archivos, como recursos, imágenes o archivos de propiedades.

Con este conocimiento en mano vaya a la carpeta inJar y copie ahi la imagen que desea usar en su documento, como puede ver en la figura 2

Figura 2 - Imagen

Figura 2 – Imagen

 Accediendo a recursos dentro del proyecto.

Si a tenido oportunidad de leer la documentación de la clase Image de iText, posiblemente halla notado que el constructor toma como argumento una cadena de texto que contenga el URL (Localizador de recurso uniforme) de la imagen que desea mostrar, bueno este lo podemos obtener gracias a la clase URL del paquete java.net lo cual nos da la información necesaria para acceder a la imagen.

Código.

Ya habiendo tocado la teoría, procederemos al ejemplo practico, en su proyecto de “Actualizar” al proyecto (lo que hará que el archivo de la imagen aparezca en el paquete inJar) y cree una nueva clase llamada InJar en la cual debe poner el código mostrado a continuación:

Figura 3 - Contenido del proyecto

Figura 3 – Contenido del proyecto

package mx.org.hashSoft.inJAR;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import com.itextpdf.text.Image;
import java.io.FileOutputStream;
import com.itextpdf.text.Element;
import com.itextpdf.text.Document;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.DocumentException;

public class InJar {
    
    public void crearPdf(String filename) throws MalformedURLException, IOException, DocumentException {
        Document document = new Document(PageSize.LETTER, 36, 36, 54, 36);
        Paragraph parrafo;
        String nombreLogo = “logo.png”;
        Image imagen;
        
        URL resUrl = this.getClass().getResource(nombreLogo);
        
        imagen = Image.getInstance(resUrl);
        
        PdfWriter.getInstance(document, new FileOutputStream(filename));

        document.open();

        parrafo = new Paragraph(“La imagen esta contenida en el archivo .JAR”);
        parrafo.setAlignment(Element.ALIGN_CENTER);
        imagen.setAlignment(Element.ALIGN_CENTER);

        document.add(parrafo);
        document.add(imagen);
        
        document.close();
    }
    
    static public void main(String[] args) {
        InJar doc = new InJar();

        try {
            // Creamos el documento Pdf
            doc.crearPdf(“documento.pdf”);

        } catch (DocumentException ed) {
            System.err.println(“Error al crear el documento Pdf”);
        } catch (IOException ex) {
            System.err.println(“Error General de Entrada/Salida”);
        }
    }
}

Como ya es costumbre, las lineas en rojo son las principales y su función se describirá a continuación.

import java.net.MalformedURLException;
import java.net.URL;   Importamos los paquetes necesarios para hacer uso de la clase URL

String nombreLogo = “logo.png”; Indicamos el nombre de la imagen que deseamos cargar, puede especificar la ruta relativa o absoluta desde la raiz del proyecto

URL resUrl = this.getClass().getResource(nombreLogo); Obtenemos el URL de la imagen con relación a la clase en la que estamos

imagen = Image.getInstance(resUrl); Abrimos la imagen y creamos el objecto que la referencia

doc.crearPdf(“documento.pdf”); Llamamos a los metodos para crear el documento y lo almacenamos en el directorio donde ejecutemos el programa

Ahora para demostrar todo exportamos el proyecto como un archivo Jar Ejecutable, como se ve en la figura 4

Figura 4 - Exportar

Figura 4 – Exportar

Recuerde exportar las librerías junto con el resto del proyecto, ahora mueva el archivo a la ubicación que desee en el sistema, como se ve en la figura 5 y ejecutelo, si esta en windows bastara un doble click, en linux necesitara la linea de comando, vera que se crea un nuevo archivo llamado “documento.pdf”, Figura 6

Figura 5 - Archivo .jar

Figura 5 – Archivo .jar

Figura 6 - Documento creado

Figura 6 – Documento creado

Y al abrir el documento vera que la imagen como se ve en la figura 7

Figura 7 - Resultado

Figura 7 – Resultado

Espero que esta entrada haya sido de ayuda y nos vemos en la próxima

Agregando enlaces a paginas Web a archivos Pdf con iText

Estándar

Al momento de crear un archivo Pdf con iText puede darse el caso que necesite o desee agregar un enlace a una pagina web, por ejemplo la pagina web de su empresa, esto es perfectamente realizable desde iText y es bastante sencillo.

Preparando el proyecto.

Si ya a leído entradas previas de este blog ya sabrá como agregar la liberia iText a un proyecto en Eclipse, en caso de no conocer el procedimiento puede consultarlo a detalle en esta entrada: https://hashblogeando.wordpress.com/2013/07/14/itext-generacion-de-archivo-pdf-en-java/ en la que se detalla como configurar el proyecto y donde descargar la libreria iText, una vez que tenga generado el proyecto podemos proseguir.

Proyecto en Eclipse

Como puede ver en la figura 1, el proyecto de ejemplo consiste en una sola clase en el paquete mx.com.hashSoft.

Figura 1 - Proyecto en Eclipse

Figura 1 – Proyecto en Eclipse

El código de la clase Hiperenlace se presenta a continuación, las partes importantes para generar el enlace aparecen resaltadas en rojo.

package mx.com.hashSoft;

import com.itextpdf.text.Anchor;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Font;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.PdfWriter;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;

/**
 * Crea un documento Pdf con hiperenlaces a Internet, estos enlaces
 * aparecen con letras azules y subrayados
 *
 * Referencias:
 * http://tutorials.jenkov.com/java-itext/anchor.html
 * http://geek-tutorials.com/java/itext/itext_bookmark_anchor.php
 * @author david
 */

public class HiperEnlace {
    
    static public void main(String[] args) {
        
        Document documento = new Document();
        Font fuente = new Font();
        Paragraph parrafo = new Paragraph();
        Anchor enlace = null;
        
        // Creamos el documento
        
        try{
            
            PdfWriter.getInstance(documento, new FileOutputStream(“HyperEnlace.pdf”));
            
            documento.open();
            
            // Usaremos esta fuente para los enlaces
            // Se establece el color azul
            fuente.setColor( BaseColor.BLUE);
            // Y el subrayado
            fuente.setStyle(Font.UNDERLINE);            
            
            // Agregamos un parrefo
            parrafo.add(new Phrase(
                    “Este es un ejemplo de como generar hiperenlaces, los cuales al darles click abren “
                    + “una pagina en el navegador. Como puede observar dando click al siguiente\n”));
            
            // Texto que se mostrara en el documento
            enlace = new Anchor(“http://tutorials.jenkov.com/java-itext/anchor.html&#8221;, fuente);
            
            // direccion URL a la que apunta el enlace
            enlace.setReference(“http://tutorials.jenkov.com/java-itext/anchor.html&#8221;);
            
            // Agregamos el enlace
            parrafo.add(enlace);            
            
            // Agregamos otro parrafo
            parrafo.add(new Phrase(“\nNotara que el pulsar el enlace abrio la pagina de una de las ” +
            “Referencias de la entrada”));
            
            documento.add(parrafo);           
            documento.close();           
            
        }catch(DocumentException e) {
            System.err.println(“*********** Error al crear Documento”);
            e.printStackTrace();
        }catch(FileNotFoundException d) {
            System.err.println(“*********** Error al abrir archivo”);
            d.printStackTrace();
        }        
    }
}

Font fuente = new Font(); Creamos un objecto Font, de modo que podamos crear una fuente personalizada, esto es necesario ya que por defecto los enlaces lucirán igual que el resto del texto, algo que seguramente no desea

Anchor enlace = null; Creamos un objecto que representa un enlace en el documento, por el momento no esta inicializado, pero eso cambiara en corto.

fuente.setColor( BaseColor.BLUE);  Indicamos al nuestro objecto Font que deseamos el texto que use esta fuente sea del color indicado, en este caso Azul, indicado por la constante BaseColor.BLUE

fuente.setStyle(Font.UNDERLINE); Indicamos a nuestro objecto Font que el texto que use esta fuente debe de esta subrayado, esto junto a la instrucción anterior le dará a los enlaces el look clasico de texto azul subrayado

enlace = new Anchor(“http://tutorials.jenkov.com/java-itext/anchor.html&#8221;, fuente); Creamos el objecto Anchor el cual se presentara como un enlace en el documento, en esta versión en particular del constructor indicamos el texto que deseamos aparezca y la fuente con la que deseamos se escriba, aquí viene a la mano la fuente que definimos de modo que los enlaces resalten en el documento.

 enlace.setReference(“http://tutorials.jenkov.com/java-itext/anchor.html&#8221;); La linea principal del enlace, con el método setReference indicamos a que URL nos debe dirigir el enlace al momento de pulsarlo

 parrafo.add(enlace); Agrega el enlace al parrafo indicado.

Salida del programa

Una vez que ejecute el programa, en el directorio raiz del proyecto encontrara un archivo HyperEnlace.pdf que lucirá como la figura 2

Figura 2 - Salida

Figura 2 – Salida

Y si pulsa el enlace lo llevara a una de las referencias que me ayudaron a crear esta entrada.

Figura 3 - Destino

Figura 3 – Destino

Espero que esta entrada halla sido de utilidad y nos vemos en la próxima.

Agregando un membrete a un documento Pdf con iText

Estándar

Ya en entradas anteriores se mostraron dos capacidades proporcionadas por la libreria
iText, la posibilidad de agregar imagenes y generar encabezados de pagina en documentos Pdf.

No deberia de extrañar que sea posible combinar ambas capacidades y agregar un membrete de tipo procesional a los documentos Pdf que necesite generar.

Sobre los margenes y el posicionamiento absoluto.

Antes de comenzar hay dos aspectos sobre iText que es necesario comprender para poder generar este membrete, que es la posibilidad que nos da iText de colocar imágenes y tablas en la posición que nos plazca, esto es importante puesto que el método add del objecto Document normalmente colocaría estos elementos después de los que ya estén en uso lo que obviamente no deseamos pase con el membrete de la pagina.

Ya para comenzar hay un par de conocimientos previos con los que necesitara estar familiarizado que son:

En dichas entradas previas puede encontrar información mas detallada de lo que se necesitara para generar el membrete.

Dicho esto podemos comenzar.

Creando manejador de eventos de pagina.

Para comenzar debe de crear un proyecto en Eclipse que incluya la libreria iText y colocar la imagen que desee utilizar en el directorio raiz del proyecto, como muestran las figuras 1 y 2 respectivamente

Figura 1 - Proyecto en Eclipse

Figura 1 – Proyecto en Eclipse

Figura 2 - Directorio raiz del proyecto

Figura 2 – Directorio raiz del proyecto

Hechas ambas cosas cree una clase FormatoDocumento que extienda la clase PdfPageEventHelper, esto nos permitirá usar un objecto de la clase que hemos creado para manejar los eventos de pagina, como lo es el evento onEndPage, desde el cual podemos preparar la siguiente pagina del documento, el codigo de esta clase se presenta a continuación:

package mx.com.hashSoft;
import com.itextpdf.text.Document;
import com.itextpdf.text.Image;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Rectangle;
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 FormatoDocumento extends PdfPageEventHelper
{    
    private Image imagen;
    PdfPTable table = new PdfPTable(2);
        
    /**
     * Constructor de la clase, inicializa la imagen que se utilizara en el membrete
     */
    public FormatoDocumento()
    {
        try
        {
            PdfPCell celda1 = new PdfPCell(new Phrase(“Industrias OverPass”));
            PdfPCell celda2 = new PdfPCell(new Phrase(“Departamento de RH”));
            
            imagen = Image.getInstance(“logo.png”);
            imagen.setAbsolutePosition(10, 650f);           
            
            celda1.setBorder(Rectangle.BOTTOM);
            celda2.setBorder(Rectangle.BOTTOM);
            celda2.setBorder(Rectangle.BOTTOM | Rectangle.RIGHT);
            
            table.addCell(celda1);
            table.addCell(celda2);            
            
            table.setTotalWidth(350f);            
            
        }catch(Exception r)
        {
            System.err.println(“Error al leer la imagen”);
        }    
    }
    
    /**
     * Manejador del evento onEndPage, usado para generar el encabezado
     */
    public void onEndPage(PdfWriter writer, Document document) {

        try{            
            document.add(imagen);
            table.writeSelectedRows(0, -1, 140f, 700f, writer.getDirectContent());
            
         }catch(Exception doc)
         {
             doc.printStackTrace();
         }        
     }
}

Las lineas mas relevantes de esta clase, marcadas con naranja, se detallaran a continuación:

public class FormatoDocumento extends PdfPageEventHelper

La parte mas importante de esta linea, la declaración de clase, es el extends PdfPageEventHelper, esto en necesario, pues nos permite redefinir el método onEndPage, de modo que podamos controlar que se hará al momento de preparar la siguiente pagina

public FormatoDocumento()

El constructor de la clase, donde indicamos la posición absoluta del objecto Imagen y creamos la tabla donde colocaremos el texto, a la vez que indicamos que margenes de la tabla deseamos se muestran, mas que nada por motivos esteticos.

public void onEndPage(PdfWriter writer, Document document) {

El método principal que necesitamos, este se llamara automáticamente al momento de preparar la siguiente pagina

document.add(imagen);

Al momento de crear una nueva pagina agregamos la imagen, a esta se le definió una posición absoluta en la pagina, por lo que al agregar esta con add la ubica donde necesitamos

table.writeSelectedRows(0, -1, 140f, 700f, writer.getDirectContent());

Esta linea le indica al objecto tabla donde deseamos que aparezca, esto es necesario pues a una tabla no se le puede indicar una posición absoluta de otro modo y usar add pondrá la tabla después de los elementos de la pagina, que no es lo que deseamos

Ahora necesitamos crear una clase desde donde creemos el documento y mas importante aun indicar los margenes del documento, esto lo realizaremos desde la clase Membrete, cuyo código se presenta a continuación.

package mx.com.hashSoft;

import java.io.FileOutputStream;
import java.io.IOException;

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

public class Membrete {
    /**
     * Crea un documento con encabezado y conteo de
     * paginas, para este ejemplo se crean 50 paginas
     * @param filename Nombre del archivo
     */
    public void createPdf(String filename) throws IOException, DocumentException
    {        
        Document document = new Document(PageSize.LETTER, 36, 36, 140, 36);
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(filename));
        FormatoDocumento encabezado = new FormatoDocumento();
        Paragraph parrafo;
        int i;
        
        // indicamos que objecto manejara los eventos al escribir el Pdf
        writer.setPageEvent(encabezado);
        
        document.open();
        
        //Creamos una cantidad significativa de paginas para probar el encabezado
        
        for(i=0; i < 50; i++)
        {
            parrafo = new Paragraph(“Esta es una de las paginas de prueba de nuestro programa, es la pagina numero 0x” + String.format(“%03X”, i+42));            
            parrafo.setAlignment(Element.ALIGN_CENTER);
            
            document.add(parrafo);
            document.newPage();
        }
        
        document.close();        
    }
    
    static public void main(String[] args)
    {
        Membrete doc = new Membrete();
        
        try{
            // Creamos el documento Pdf
            System.out.println(“Creando documento…”);
            doc.createPdf(“documento.pdf”);
            System.out.println(“Documento creado.”);
            
        }catch(DocumentException ed)
        {
            System.err.println(“Error al crear el documento Pdf”);
        }
        catch(IOException ex)
        {
            System.err.println(“Error General de Entrada/Salida”);
        }
    }
}

Las lineas mas relevantes se detallan a continuación:

Document document = new Document(PageSize.LETTER, 36, 36, 140, 36);

Esta linea es crucial, pues no solo crea el documento sino que nos permite especificar el tamaño de la fuente y mas importante nos permite especificar los margenes del documento, el tercer argumento indica el margen superior, este es vital para la creación del membrete, pues nos permite “reservar” el espacio donde este ira de modo que los objectos que agreguemos con add (con la excepción de la imagen con posicionamiento absoluto) no entren en dicha área.

FormatoDocumento encabezado = new FormatoDocumento();

Creamos un objecto de la clase que creamos para manejar los eventos de pagina

writer.setPageEvent(encabezado);

Indicamos que objecto debe manejar los eventos de pagina, de modo que cada vez que ocurra uno se llame al método adecuado de dicha clase

El resto de la clase Membrete es idéntico en funcionalidad al ejemplo de la entrada sobre encabezados y numeración de pagina.

Una vez que ejecute este ejemplo, asegurándose de tener una imagen logo.png en la raiz del proyecto obtendrá un resultado similar a la figura 3.

Figura 3 - Resultado

Figura 3 – Resultado

Notara que aparece en todas las paginas y que modificando la clase FormatoDocumento puede alterar la apariencia y texto.

Espero que esta entrada halla sido de utilidad y nos vemos en la próxima entrada.

Agregar Imagenes a documentos Pdf con iText

Estándar

Otra de las posibilidades que proporciona la librería iText es agregar imágenes a los documentos pdf que nuestra aplicación o sistema vayan a generar, algo por demás útil, ya sea para agregar imágenes e ilustraciones o para generar un membrete personalizado.

Lo mejor del caso es lo bastante sencillo que es realizar esto, no es necesario ningún tipo de pre-conversión, paso a mapa de bit binario ni cosas por el estilo, basta que tenga la imagen a la mano.

Como en entradas anteriores la forma de hacer esto se explicara con un ejemplo, del cual se comentaran a detalle las lineas claves, su significado e implicaciones, antes de comenzar necesita preparar un proyecto en Java el cual incluya la libreria iText, si esta utilizando el entorno Eclipse y no sabe como hacer esto puedo recomendar una entrada anterior de este blog, donde se describe el proceso a detalle: iText, Generación de archivo Pdf en Java, ya que este listo el proyecto podemos comenzar.

Figura 1 - Proyecto con iText

Figura 1 – Proyecto con iText

Antes de comenzar debe recordar un detalle importante sobre la forma en que Eclipse ejecuta los programas (esto es si usa el botón ejecutar del entorno), los programas se ejecutan en el directorio raíz del proyecto, de modo que si no planea poner una ruta absoluta a la imagen, lo mas sencillo, y similar al ejemplo que se manejara es ubicar la imagen en el directorio raíz del proyecto, como se ve en la figura 2.

Figura 2 - Directorio Raíz del proyecto

Figura 2 – Directorio Raíz del proyecto

La clase Image.

He aquí el código que usaremos como ejemplo, con énfasis en las lineas mas relevantes, este generara un documento de tres paginas, mostrando detalles sobre posicionamiento y alineación de la imagen, como las figuras mostraran:

package mx.com.hashSoft;

import java.io.FileOutputStream;
import java.io.IOException;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfWriter;

public class Imagen {
    
    /**
     * Crea un documento con encabezado y conteo de
     * paginas, para este ejemplo se crean 100 paginas
     * @param filename Nombre del archivo
     */
    public void createPdf(String filename) throws IOException, DocumentException
    {        
        Document document = new Document(PageSize.LETTER , 36, 36, 54, 36);
        Paragraph parrafo, parrafo2, parrafo3;
        Image imagen = Image.getInstance(“hash_avatar.png”);       
        
        PdfWriter.getInstance(document, new FileOutputStream(“Image.pdf”));

        document.open();
        
        //Creamos una cantidad significativa de paginas para probar el encabezado
        parrafo = new Paragraph(“Esta es una de las paginas de prueba de nuestro programa, Vemos que la imagen queda *despues* de este texto.”);
        parrafo.setAlignment(Element.ALIGN_CENTER);

        imagen.setAlignment(Element.ALIGN_CENTER);

        document.add(parrafo);
        document.add(imagen);
        
        document.newPage();
        parrafo2 = new Paragraph(“En esta pagina estamos usando posicionamiento absoluto, por lo que el texto queda encima de la imagen”);
        
        imagen.setAbsolutePosition(150f, 650f);
        document.add(imagen);
        document.add(parrafo2);    
        
        document.newPage();
        parrafo3 = new Paragraph(“Aqui podemos observar el origen del sistema de cordenadas que iText usa para los posicionamientos absolutos”);
        imagen.setAbsolutePosition(0f, 0f);

        document.add(imagen);
        document.add(parrafo3);       
        document.close();        
    }

    static public void main(String[] args)
    {
        Imagen doc = new Imagen();
        
        try{
            // Creamos el documento Pdf
            doc.createPdf(“documento.pdf”);
            
        }catch(DocumentException ed)
        {
            System.err.println(“Error al crear el documento Pdf”);
        }
        catch(IOException ex)
        {
            System.err.println(“Error General de Entrada/Salida”);
        }
    }   
}

Notara que se creo un objecto Image por medio del método getInstance de la forma:

Image imagen = Image.getInstance(“hash_avatar.png”);  

Esta es la función clave aquí, pues con ella le indicamos al programa que deseamos crear una referencia a la imagen en la ruta indicada como argumento de modo que podemos agregar esa imagen a nuestro documento con solo usar el método add del objecto Document, como muestra la linea.

document.add(imagen);

Y listo solo con eso ya tendrá una imagen agregada a su documento, algo que destacar es que, de igual modo que los párrafos, puede indicar la alineación que desea tenga la imagen, ya sea a la izquierda, centrado o a la derecha por medio del método setAlignment, como se ve en la linea, en la Figura 3 puede observar el resultado de usar imagen.setAlignment(Element.ALIGN_CENTER);

Figura 3 - Usando etAlignment(Element.ALIGN_CENTER)

Figura 3 – Usando etAlignment(Element.ALIGN_CENTER)

Posicionamiento manual

También podría ser deseable indicar con precisión donde desea que aparezca la imagen e incluso que no siga el orden de los demás elementos del documento e incluso halla empalmes con estos, esto también puede lograrse por medio del método setAbsolutePosition como se ve en la linea:

imagen.setAbsolutePosition(150f, 650f);

Esta nos permite indicar la posición en pixeles, como podrá ver en la Figura 4

Figura 4 - Posicionamiento manual

Figura 4 – Posicionamiento manual

Cuando se trata del posicionamiento manual iText maneja un sistema de coordenadas cuyo origen se ubica en la esquina inferior izquierda del documento, esto se ejemplifica con la linea

imagen.setAbsolutePosition(0f, 0f);

La cual coloca la imagen en la posición mostrada en la figura 5

Figura 5 - Origen de las coordenadas

Figura 5 – Origen de las coordenadas

Y claro esto es solo una pequeña parte de las posibilidades proporcionadas por la librería iText (Tambien es posible generar transparencias y rotar la imagen), por lo pronto esto sera todo, espero que la entrada halla sido de utilidad y nos vemos pronto.

Referencias

Java IText: Image – http://tutorials.jenkov.com/java-itext/image.html

Creando encabezados y conteo de paginas en archivos Pdf con Java e iText.

Estándar

(Nota el código aquí presentado es para la versón 5 de iText, si desea usar la versión 7 puede consultar la siguiente entrada: Encabezados, pie de pagina y conteo de paginas en iText 7)

Siguiendo con la idea de usar iText para generar reportes y recibos, hay dos características que seguramente son deseables, especialmente si es posible el reporte tome mas de una pagina, agregar un encabezado con algún mensaje y numerar las paginas indicando la cantidad total de estas.

Como era de esperar esto es perfectamente realizable desde iText dándonos la flexibilidad necesaria para generar un encabezado de la forma en que deseemos, para el ejemplo actual lo mantendremos lo mas simple posible, la idea es que sea fácil de comprender el funcionamiento básico y que métodos son los que se llaman.

Figura 1 – Proyecto encabezado

Teoría de Eventos.

La forma en que se realiza el conteo de pagina y la generación de encabezados es muy similar a la forma en que se manejan los eventos en la librería Swing, esto significa que una vez que ocurra una situación o evento especifico, como el cambio de pagina, se invoca un método especifico de un objecto indicado.

La limitante de esto es que dicho objecto debe ser una instancia de una clase descendiente de la clase que la librería usa para manejar los eventos esto, aunque parezca, arbitrario es necesario para garantizar que nunca se llame un método inexistente.

Ya tras esta breve introducción a como se manejan los eventos de pagina podemos pasar a implementar la clase que manejara los eventos de pagina de nuestro documento.

Manejando eventos de pagina.

Comenzaremos creando una nueva clase para manejar los dos eventos de pagina que nos interesan en este momento, el evento onDocumentOpen onEndPage y onCloseDocument, los cuales se activan al abrirse el  documento, completarse una pagina y cerrar el documento, respectivamente.

El código de la clase puede verse a continuación, tras lo cual se explicaran que hace y como funciona cada función.

package mx.com.hashSoft;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.ExceptionConverter;
import com.itextpdf.text.Image;
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.PdfTemplate;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.Phrase;

/**
 * Clase que maneja los eventos de pagina necesarios para agregar un encabezado y  conteo de paginas a un documento.
 * El encabezado, definido en onEndPage, consiste en una tabla con 3 celdas que contienen:
 * Frase del encabezado | pagina de | total de paginas, con una linea horizontal separando el
 * encabezado del texto
 *
 * Referencia: http://itextpdf.com/examples/iia.php?id=104
 *
 * @author David
 */

public class Cabecera extends PdfPageEventHelper {
    private String encabezado;
    PdfTemplate total;
    
    /**
     * Crea el objecto PdfTemplate el cual contiene el numero total de
     * paginas en el documento
     */
    public void onOpenDocument(PdfWriter writer, Document document) {
        total = writer.getDirectContent().createTemplate(30, 16);
    }
    
    /**
     * Esta es el metodo a llamar cuando ocurra el evento onEndPage, es en este evento
     * donde crearemos el encabeazado de la pagina con los elementos indicados.
     */
    public void onEndPage(PdfWriter writer, Document document) {
        PdfPTable table = new PdfPTable(3);
        try {
            // Se determina el ancho y altura de la tabla
            table.setWidths(new int[]{24, 24, 2});
            table.setTotalWidth(527);
            table.setLockedWidth(true);
            table.getDefaultCell().setFixedHeight(20);
            
            // Borde de la celda
            table.getDefaultCell().setBorder(Rectangle.BOTTOM);
            
            table.addCell(encabezado);
            table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_RIGHT);
            
            table.addCell(String.format(“Pagina %010d de”, writer.getPageNumber()));
            
            PdfPCell cell = new PdfPCell(Image.getInstance(total));
            
            cell.setBorder(Rectangle.BOTTOM);
            
            table.addCell(cell);
            // Esta linea escribe la tabla como encabezado
            table.writeSelectedRows(0, -1, 34, 803, writer.getDirectContent());
        }
        catch(DocumentException de) {
            throw new ExceptionConverter(de);
        }
    }
    
    
    /**
     * Realiza el conteo de paginas al momento de cerrar el documento
     */
    public void onCloseDocument(PdfWriter writer, Document document) {
        ColumnText.showTextAligned(total, Element.ALIGN_LEFT, new Phrase(String.valueOf(writer.getPageNumber() – 1)), 2, 2, 0);
    }    
    
    // Getter and Setters
    
    public String getEncabezado() {
        return encabezado;
    }
    public void setEncabezado(String encabezado) {
        this.encabezado = encabezado;
    }
}

Notara un objecto PdfTemplate en la clase, junto con los métodos get y set respectivos, este es el objecto usado para poder realizar el conteo de paginas.

onOpenDocument
Esta función inicializa el objecto PdfTemplate, no hacen falta mas detalles sobre esta.

onEndPage
Esta función se llama *después* de que se a completado una pagina, permitiendo preparar la siguiente.
En este caso deseamos que las paginas tengan un encabezado con las forma:

Pagina de

Para lograr esto crearemos una tabla de 1 x 3 en la cual se colocara cada uno de los elementos de la cabecera, esto se hace con el objecto table y las múltiples llamadas al método addCell

Notara tres métodos que no se han visto en la entrada de tablas, setBorder, setHorizontalAligment y writeSelectedRows, lo que hacen estas funciones es indicar el borde de la tabla que deseamos se dibuje, como deseamos que se alinen los elementos de la tabla y que se escriba directamente respectivamente.

Ya con esto se generara el encabezado deseado.

onCloseDocument
Es desde esta función donde se realiza el calculo de paginas

get/setEncabezado
Indica Que frase deseamos en el encabezado

Seguro podría parecerle raro que algunas funciones tengan nombres en ingles, específicamente las que comienzan con on, esto no es solo por alguna convención, de hecho es vital para el funcionamiento, lo que se esta haciendo es redefinir los métodos on de la superclase PdfPageEventHelper, esto es necesario para que sea posible usar esta clase para manejar los eventos, como veremos en la siguiente clase.

Creando Documento

Ahora mostraremos como se usa la clase que acabamos de crear con ayuda de esta clase, cuya función es generar un documento de 100 paginas, de modo que se demuestre que la numeración si se lleva a cabo de forma correcta.

A continuación puede verse el código de dicha clase:

package mx.com.hashSoft;

import java.io.FileOutputStream;
import java.io.IOException;

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

public class Documento {
    
    /**
     * Crea un documento con encabezado y conteo de
     * paginas, para este ejemplo se crean 100 paginas
     * @param filename Nombre del archivo
     */
    public void createPdf(String filename) throws IOException, DocumentException
    {        
        Document document = new Document(PageSize.A4, 36, 36, 54, 36);
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(filename));
        Cabecera encabezado = new Cabecera();
        Paragraph parrafo;
        int i;
        
        encabezado.setEncabezado(“Prueba de encabezado en iText”);
        
        // indicamos que objecto manejara los eventos al escribir el Pdf
        writer.setPageEvent(encabezado);
        
        document.open();
        
        //Creamos una cantidad significativa de paginas para probar el encabezado
        
        for(i=0; i < 100; i++)
        {
            parrafo = new Paragraph(“Esta es una de las paginas de prueba de nuestro programa, es la pagina numero 0x” + String.format(“%03X”, i+42));            
            parrafo.setAlignment(Element.ALIGN_CENTER);
            
            document.add(parrafo);
            document.newPage();
        }
        
        document.close();        
    }

    static public void main(String[] args)
    {
        Documento doc = new Documento();
        
        try{
            // Creamos el documento Pdf
            doc.createPdf(“documento.pdf”);
            
        }catch(DocumentException ed)
        {
            System.err.println(“Error al crear el documento Pdf”);
        }
        catch(IOException ex)
        {
            System.err.println(“Error General de Entrada/Salida”);
        }
    }   
}

Ya que la función main se limita unicamente a llamar a createPdf y capturar cualquier error nos enfocaremos en este ultimo método.

Notara que el método createPdf crea e inicializa un objecto PdfWriter, como se realizo en los ejemplos de entradas anteriores, pero esta vez se llama a un método muy particular pasandole como argumento un objecto de la clase Cabecera que creamos anteriormente.

writer.setPageEvent(encabezado);

Esta linea es la clave de todo, en esta le indicamos al objecto writer que objecto se encargara de manejar los eventos, este método toma por argumento un objecto tipo PdfPageEventHelper o un *descendiente* de esta clase y llama a los métodos en el momento adecuando.

Tras esto el flujo del método es bastante simple una vez abierto el documento, lo cual es el evento onOpenDocument, hacemos un ciclo de 100 repeticiones agregando un párrafo a la pagina e indicamos que deseamos comience una nueva pagina con document.newPage, lo que a su vez es genera el evento onPageEnd y llama a la función adecuada del objecto que maneja los eventos.

Al concluir cerramos el documento, causando el evento onCloseDocument.

Solo para aclarar las llamadas a los métodos de la clase Cabecera se realizan automáticamente cuando se llega a la condición adecuada.

Si corre el programa, recordando preparar el proyecto como se mostró en la entrada iText, Generación de archivo Pdf en Java , obtendrá una salida como la figura 2

Imagen

Figura 2 – Documento resultante

Notara que el mensaje tiene la numeración en hexadecimal y desfasada con respecto al conteo de paginas, mas que nada para demostrar que el contenido y la numeración de pagina son independientes uno de otro.

Con esto puede ver que, si bien su uso no es del todo intuitivo, las posibilidades de los eventos de pagina de iText ciertamente valen el esfuerzo ya que, así como creamos un encabezado, no me extrañaría que se pudiera agregar algo mas elaborado, como imágenes o fechas o datos mucho mas elaborados.

Espero que esta información fuera de utilidad y nos vemos en otra entrada.