sábado, 24 de agosto de 2013

Creando documentos LaTeX en Eclipse

De los varios entornos para la generación de documentos LaTeX que conozco quizás el que menos esperaba, pero debí de suponer, es el entorno Eclipse.
Esto tiene sentido, dado que LaTeX requiere de el uso de un compilador y un set de herramientas y la arquitectura basada en plug-ins de Eclipse posibilita extenderlo a fines tan inesperados.

Instalación en Fedora Linux
Antes de comenzar con los documentos sera necesario que instale un par de complementos al entorno Eclipse, específicamente el modulo texlipse, el cual proporciona los entornos y utilerias para configurar, preparar y compilar un documento en LaTeX.
Los paquetes que necesitara son los siguientes:
  • texlive
  • eclipse-texlipse
  • texlive-babel-spanish
Figura 1: Paquetes
Figura 1: Paquetes

Si puedo hacer una recomendación sugeriria realizar la instalación desde la linea de comandos con el comando yum install, esto mas que nada debido a las experiencias que he tenido con el administrador de paquetes que parece trabarse cuando se instalan paquetes de gran tamaño, como lo es texlive.

Creando proyecto LaTeX.
Una vez que halla instalado los paquetes indicados y sus dependencias ya podrá
crear un proyecto LaTeX, como observa en la figura 2


Figura 2: Creando proyecto LaTeX
Figura 2: Creando proyecto LaTeX

Esto le presentara un asistente el cual le permitirá nombrar su proyecto seleccionar el formato de salida, las herramientas da usar, el nombre de su archivo .tex y el nombre del archivo resultante, finalmente podrá cambiar como estarán las carpetas del proyecto, eso lo puede ver en las figuras 3 y 4.

Figura 3: Opciones del proyecto
Figura 3: Opciones del proyecto
Figura 4: Organización del proyecto
Figura 4: Organización del proyecto

Una vez que complete los diálogos se le presentara el proyecto ya listo para comenzar su documento, como se ve en la figura 5
Figura 5: Proyecto creado.
Figura 5: Proyecto creado.

Bastara con que haga cualquier modificación para que el proyecto se recompile, lo que generara el archivo pdf (O en el formato de salida que halla seleccionado)
el cual podra visualizar en fácilmente, como se observa en la figura 6.

Figura 6: Resultado.
Figura 6: Resultado.

Espero que esto halla sido útil y nos vemos en la siguiente entrada.

viernes, 9 de agosto de 2013

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

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 <numero de 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 <b>onEndPage</b>, 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:

<encabezado> Pagina <numero de pagina con 10 dígitos> de <total de paginas>

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.

sábado, 3 de agosto de 2013

True Story



Que bueno que las estaciones de servicio tienen malla metálica en las coladeras.

domingo, 21 de julio de 2013

Generando tablas en archivos Pdf con Java e iText

Si he de ser honesto esta es la razón de que halla decidido aprender a mas detalle como se usa
la librería iText, la necesidad de crear tablas para generar reportes de datos, por fortuna el procedimiento es muy sencillo.

Cree un proyecto Java con la librería iText, esto se describió en una entrada anterior, hecho esto cree un paquete tablas y una clase Tablas, en la que ponga el siguiente código, las partes que generan la tabla se describirán después

package tablas;
import com.itextpdf.text.Document;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import java.io.FileOutputStream;

public class Tablas {
    
    static public void main(String[] args)
    {
        Document document = new Document();
        
        try{
            PdfWriter.getInstance(document, new FileOutputStream("tablas.pdf"));
            document.open();
            
            // Este codigo genera una tabla de 3 columnas
            PdfPTable table = new PdfPTable(3);                
            
            // addCell() agrega una celda a la tabla, el cambio de fila
            // ocurre automaticamente al llenar la fila
            table.addCell("Celda 1");
            table.addCell("Celda 2");
            table.addCell("Celda 3");
            
            table.addCell("Celda 4");
            table.addCell("Celda 5");
            table.addCell("Celda 6");
            
            table.addCell("Celda 7");
            table.addCell("Celda 8");
            table.addCell("Celda 9");
            
            // Si desea crear una celda de mas de una columna
            // Cree un objecto Cell y cambie su propiedad span
            
            PdfPCell celdaFinal = new PdfPCell(new Paragraph("Final de la tabla"));
            
            // Indicamos cuantas columnas ocupa la celda
            celdaFinal.setColspan(3);
            table.addCell(celdaFinal);
            
            // Agregamos la tabla al documento            
            document.add(table);
            
            document.close();
            
        }catch(Exception e)
        {
            System.err.println("Ocurrio un error al crear el archivo");
            System.exit(-1);
        }
    }
}
El archivo resultado tablas.pdf lucirá de este modo:

Imagen
Figura 1 - Resultado


Los comentarios indican donde esta el código notable, el cual describiremos a continuación:

PdfPTable table = new PdfPTable(3);
Genera un objecto PdfPTable , el constructor nos permite indicar el numero de *columnas* que
tendrá la tabla.

table.addCell("Celda 1");
Agrega una celda a la tabla, permite agregar varios objectos, en este caso una cadena de texto
Notara que no hay mención de un salto de columna o similar, esto no es necesario, ya que la función
automáticamente realiza el salto de fila.

PdfPCell celdaFinal = new PdfPCell(new Paragraph("Final de la tabla"));
Esta linea de código crea un objecto PdfPCell, el cual representa una celda en la tabla, posiblemente
se pregunte por que fue necesario crear este objecto aparte, la razón es sencilla para acceder a sus
propiedades, como lo es setColSpan.

celdaFinal.setColspan(3);
Esta propiedad de los objectos PdfPCell nos permite indicar cuantas columnas debe de abarcar la celda muy útil para la generación de títulos, o como en este caso pies de la tabla.

table.addCell(celdaFinal);
Esta sobrecarga del método addCell agrega la celda que acabamos de crear a la tabla.

Esto cubre lo básico del uso de iText, seguramente notara lo sencillo que seria usar estas funciones con ciclos para poder generar una tabla de reporte bastante completa

Espero que esta información halla sido de utilidad y nos vemos en otra entrada.
Referencias:

sábado, 13 de julio de 2013

iText, Generación de archivo Pdf en Java

Durante la realización de algún programa es posible que llegue a necesitar crear algún tipo de recibo y/o reporte con el fin de tener una confirmación mas solida de las operaciones realizadas, la fecha en que se realizaron, o simplemente que se desee imprimir un comprobante de las mismas.

En estos casos el formato en el que normalmente se solicita es un archivo Pdf.

No es de extrañar por tanto que exista una librería en Java con la cual se puedan crear documentos en dicho formato de una forma bastante sencilla, que a su vez nos permite hacer uso de las funciones de formateo y localización que vienen incluidas con el formato.

Por esto se presenta este tutorial el cual cubre como dar de alta dicha librería para su uso en un proyecto del IDE Eclipse, mas un ejemplo sencillo de un programa

Antes de comenzar quisiera agradecer a Geek-tutorials.com que es donde encontré el tutorial que sirve de base para este, enlace al mismo que puede encontraste en la sección de referencias [1]

Creando el proyecto

Se asumirá ya se tiene instalado en entorno Eclipse, por lo que se comenzara con crear un nuevo proyecto, con el nombre ReciboPDF y presionamos finalizar

Creando el proyecto
Figura 1 - Creando el proyecto de ejemplo
Notara que en el explorador de paquetes ahora esta nuestro nuevo proyecto, de clic sobre el signo + y notara la estructura del proyecto como se ve en la figura 2

Figura 2 - Estructura del proyecto
Figura 2 - Estructura del proyecto


Ahora presione el botón derecho del ratón sobre el proyecto y vaya a nueva->carpeta y cree una carpeta llamada lib

Figura 3 - Nueva carpeta


Lib
Figura 4 - Carpeta para las librerías


Esta carpeta la usaremos para poner la librería iText, no es esencial del todo, pero es buena practica mantener las librerías en su propia carpeta.

Ahora descargue la librería desde http://sourceforge.net/projects/itext/ descargara un archivo itext-5.4.2.zip cuyo contenido se observa en la figura 5

05_contenido
Figura 5 - Contenidos de itext-5.4.2.zip


De ese archivo zip extraiga itextpdf-5.4.2.jar a la carpeta lib del proyecto

Ahora regrese a eclipse y presione F5 o a renovar en el menú contextual, con eso obtendrá algo como la figura 6, con el archivo jar ahora en la carpeta lib

06_lib_agregada
Figura 6 - Librería detectada


Si bien la librería ya se encuentra en el directorio del proyecto aun falta agregarla a la ruta de construcción del proyecto, para esto presione con el botón derecho del raton sobre el nombre del proyecto y vaya a propiedades

07_via_de_construccion
Figura 7 - Via de Construcción Java


En el dialogo de propiedades seleccione "Via de Construcción Java" y vaya a la pestaña de propiedades como se ve en la figura 7

Ahí presione el boton añadir archivos Jar y seleccione itextpdf-5.4.2.jar como se ve en la figura 8 y presione aceptar

08_librerias
Figura 8 - Librerías
Vera que iText ahora aparece entre las librerías del proyecto, como muestra la figura 9

09_agregar_librerias
Figura 9 - Librerías del proyecto

Con esto ya podra usar la librería desde el proyecto, para prueba cree un paquete pruebaPDF y una nueva clase llamada PruebaPDF con el código:

package pruebaPDF;

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

import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Calendar;

public class PruebaPDF {
    
    public void ITextHelloWorld() throws Exception{
        Document document = new Document();        
        Calendar cal = Calendar.getInstance();
        Date fecha = new Date( cal.getTimeInMillis() );
        SimpleDateFormat formato = new SimpleDateFormat("dd/MM/yyyy");
        
        String parrafo = "Usaremos este parrafo como ejemplo de lo sencillo que es el uso de la libreria, pues como podria observar en el codigo esta cadena no lleva saltos de linea, mismos que la libreria agrego.";
        
        String parrafo2 = "A su vez podemos agregar datos con una simple concatenación, como ejemplo ponemos la fecha del dia en el formato deseado: " + formato.format(fecha) + " y como podemos ver tambien hacer uso de las diversas funciones de formateo de fecha y numeros, incluso formatos personalidades.";
        
        PdfWriter.getInstance(document, new FileOutputStream("recibo.pdf"));
        document.open();
        document.add(new Paragraph(parrafo));
        document.add(new Paragraph(parrafo2));
        document.close();
            
    }
    
    public static void main(String args[]){
        try{
            PruebaPDF p = new PruebaPDF();
            
            p.ITextHelloWorld();
            
        }catch(Exception e){
            System.out.println(e);
        }
    }
}
Si ejecuta el programa en el directorio raíz del proyecto encontrara un archivo recibo.pdf con el contenido mostrado en la figura 10


10_resultado
Figura 10 - Resultado

Con esto ya tiene un ejemplo sencillo de como usar la libreria, en futuras entradas veremos mas sobre el formateo de datos y de fechas.

Espero que esto ayude a los que deseen usar la librería y nos vemos en otra entrada

Referencias:
1 - Setup iText for project & Hello World - http://www.geek-tutorials.com/java/itext/setup_itext.php
2 - iText®, a JAVA-PDF library - http://sourceforge.net/projects/itext/

jueves, 13 de junio de 2013

Señal Wi-Fi

En ratos así hay que buscar la señal de Internet
Señal de Internet