Creando archivos Excel en Java, Un ejemplo MÁS práctico

Estándar

En un comentario se me mencionó algo que ya sospechaba, que el ejemplo que puse en la entrada Creando archivos Excel desde Java con Apache POI es demasiado simple y no particularmente práctico :P, por lo que llegó el momento de corregir eso con un ejemplo que muestre algunos de los “detalles” con los que hay que lidiar al momento de usar las librerías Apache POI.

Para este ejemplo haremos algo más elaborado, simularemos un reporte anual que nos presenta el siguiente formato:

  • La primera columna nos debe mostrar los nombres de los doce meses del año
  • La primera fila debe mostrar la numeración del 1 al 31 de modo que sepamos a qué día corresponde cada valor
  • Las filas 2 en adelante nos deben mostrar los porcentajes de cada día de ese mes

Y para que quede más claro veamos como se verá el resultado.

 

2016-08-24 (1)

Como se vería nuestro reporte

Antes de pasar al código recuerde agregar las librerías de Apache POI a su proyecto, pues de lo contrario no tendrá las clases necesarias y no compilara, dicho esto vamos al código, espero que los comentarios dejen en claro que hace cada sección.

package ejemploexcel;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;

import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;

/**
 *
 * @author David
 */
public class EjemploExcel {

    /**
     * Programa de ejemplo para la creacion de un archivo de excel
     * 
     * El programa simulara un reporte anual mostrando los porcentajes de cada
     * dia del año (simulados via numeros aleatorios) en el formato:
     * 
     * <nombre mes> <dia 1> <dia 2> <dia 3>...
     * 
     * Cada fila tendra el largo correspondiente a los dias de dicho posicion
     * 
     * @param args
     */
    public static void main(String[] args) {
        // Creamos nuestro libro de excel
        HSSFWorkbook workbook = new HSSFWorkbook();
        
        // Creamos una hoja de calculo llama "Reporte" en dicho libro de excel
        HSSFSheet sheet = workbook.createSheet("Reporte");
        
        // Un arreglo con los nombres de los meses del año
        String[] meses = {"Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"};
        // Un arreglo con la duración de cada mes
        Integer[] diasMes = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
        
        // Creamos un formato para las celdas
        HSSFCellStyle style = workbook.createCellStyle();        
        // Especificamente que *siempre* muestre dos digitos enteros y dos decimales
        style.setDataFormat(workbook.createDataFormat().getFormat("00.00"));
        
        // En la primera fila ponemos el numero del dia
        Row encabezado = sheet.createRow(0);
        // i empieza en 1 para alinear el numero de dias con los datos ya que
        // la columna 0 se usara para el nombre del posicion
        for (int i = 1; i < 32; i++) {
            Cell celda = encabezado.createCell(i);
            celda.setCellValue(i);
        }
        
        
        // Este ciclo ira creando las *filas*, una por cada mes del año
        // la variable posicion indicara en que fila nos encontramos, mientras que mes
        // selecionara el nombre del mes.
        // posicion comienza en 1 para compensar que ya usarmos la fila 0 para
        // poner los dias
        for(int posicion = 1, mes=0; mes < meses.length; posicion++, mes++) {
            // Creamos una fila en la posicion indicada por el contador del ciclo
            Row fila = sheet.createRow(posicion);
            
            // Creamos la celda para el nombre del mes, en la primera posicion de la fila
            Cell celdaMes = fila.createCell(0);
            // Indicamos que valor debe tener
            celdaMes.setCellValue(meses[mes]);
            
            // Este ciclo ira llenando las *celdas* en la fila que acabamos de
            // crear, llenando solo el numero de celdas indicado por el numero
            // de dias
            
            // Empezamos en 1 y le sumamos 1 a los dias del posicion para compensar
            // que la celda 0 la usamos para el nombre del posicion
            
            for (int dia = 1; dia < diasMes[mes] + 1; dia++) {
                // Creamos una celda en posicion indicada de la fila en la que
                // estamos trabajando
                Cell celda = fila.createCell(dia);
                // Indicamos el formato que la celda usara
                celda.setCellStyle(style);
                // Creamos el porcentaje de ese dia
                Double porcentaje = Math.random() * 100;
                // Almacenamos el porcentaje en la celda del dia
                celda.setCellValue(porcentaje);                
                
            }  
            // Al momento que el ciclo de otra vuelta el valor de posicion se incrementara
            // de modo que al crear una nueva fila, esta estara ubicada en la
            // *siguiente* fila y no sobre escribira la que hemos creado
        }
        
        // Ahora almacenaremos el archivo en disco
        try {
            File archivo = new File("ejemplo.xls");
            FileOutputStream out = new FileOutputStream(archivo);
            workbook.write(out);
            out.close();
        } catch (IOException e) {
            System.err.println("ERROR AL CREAR EL ARCHIVO!");
            e.printStackTrace();
        }
        
        System.out.println("Reporte generado");
        
    }
    
}

Creando archivos Excel en formato .xlsx desde Java

Estándar
2016_01_30_actualizacion

Hora de actualizar.

Desde Microsoft Office 2007 el formato para almacenar los archivos a recibido una actualización mas que significativa pasando del viejo formato binario a un formato XML mejor detallado y estandarizado el Office Open XML y desde Office 2010 este es el formato en el que se guardan los archivos por defecto por lo que es muy posible que su organización ya lo este usando, por lo que es util poder generar este tipo de archivos.

Como ya se menciono en una entrada anterior las librerias Apache POI nos proporcionan las clases y metodos necesarios para crear archivos de Office asi que no es de sorprender que se puedan crear archivos en el formato mas nuevo.

XSSF
Si hace algo de memoria o revisa la entrada antes mencionada recordara que las clases para manejar los archivos Excel .xls, en especifico el libro de Excel y la hoja de trabajo se encontraban en el paquete org.apache.poi.hssf.usermodel, para manejar los archivos .xlsx las clases necesarias se localizan en org.apache.poi.xssf.usermodel y la clase HSSFWorkbook es remplazada por XSSFWorkbook, todo esto quedara mas claro en el ejemplo.

Dependencias
A diferencia del formato anterior, donde solo necesitaba agregar el archivo poi-<numero_version>.jar al proyecto, para hacer uso de los formatos OOXML necesitara agregar las librerias poi, poi-ooxml, poi-ooxml-schemas y xmlbeans, estas se localizan en el archivo jar que puede descargar desde la pagina de apache POI, ya que xmlbeans esta un poco escondido en el archivo .jar (esta en la carpeta ooxml-lib) en las siguientes imagenes podra ver que archivos necesita.

01-libs

Figura 1 – Librerias POI

02-xmllib

Figura 2 – Libreria xmlbeans

Ya que las agrege al proyecto como se ha visto en previas entradas anteriores, el resultado lucira como la figura 3

03-libs_netbeans

Figura 3 – Librerias agregadas.

 

package newexcel;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class ExcelOOXML {
    
    private static final Logger LOGGER = Logger.getLogger("newexcel.ExcelOOXML");
    
    public static void main(String[] args) {
        // Creamos el archivo donde almacenaremos la hoja
        // de calculo, recuerde usar la extension correcta,
        // en este caso .xlsx
        File archivo = new File("reporte.xlsx");
        
        // Creamos el libro de trabajo de Excel formato OOXML
        Workbook workbook = new XSSFWorkbook(); 
        
        // La hoja donde pondremos los datos
        Sheet pagina = workbook.createSheet("Reporte de productos");
        
        // Creamos el estilo paga las celdas del encabezado
        CellStyle style = workbook.createCellStyle();
        // Indicamos que tendra un fondo azul aqua
        // con patron solido del color indicado
        style.setFillForegroundColor(IndexedColors.AQUA.getIndex());
        style.setFillPattern(CellStyle.SOLID_FOREGROUND);
        
        String[] titulos = {"Identificador", "Consumos", 
                            "Precio Venta", "Precio Compra" };
        Double[] datos = {1.0, 10.0, 45.5, 25.50};        
        
        // Creamos una fila en la hoja en la posicion 0
        Row fila = pagina.createRow(0);
        
        // Creamos el encabezado
        for(int i = 0; i < titulos.length; i++) {
            // Creamos una celda en esa fila, en la posicion 
            // indicada por el contador del ciclo
            Cell celda = fila.createCell(i);
            
            // Indicamos el estilo que deseamos 
            // usar en la celda, en este caso el unico 
            // que hemos creado
            celda.setCellStyle(style); 
            celda.setCellValue(titulos[i]);
        }
        
        // Ahora creamos una fila en la posicion 1
        fila = pagina.createRow(1);
        
        // Y colocamos los datos en esa fila
        for(int i = 0; i < datos.length; i++) {
            // Creamos una celda en esa fila, en la
            // posicion indicada por el contador del ciclo
            Cell celda = fila.createCell(i);
            
            celda.setCellValue( datos[i] );        
        }
        
        // Ahora guardaremos el archivo
        try {
            // Creamos el flujo de salida de datos,
            // apuntando al archivo donde queremos 
            // almacenar el libro de Excel
            FileOutputStream salida = new FileOutputStream(archivo);
            
            // Almacenamos el libro de 
            // Excel via ese 
            // flujo de datos
            workbook.write(salida);
            
            // Cerramos el libro para concluir operaciones
            workbook.close();
            
            LOGGER.log(Level.INFO, "Archivo creado existosamente en {0}", archivo.getAbsolutePath());
            
        } catch (FileNotFoundException ex) {
            LOGGER.log(Level.SEVERE, "Archivo no localizable en sistema de archivos");
        } catch (IOException ex) {
            LOGGER.log(Level.SEVERE, "Error de entrada/salida");
        }
    }    
}

El resultado del programa se vera como la Figura 4

04-resultado

Figfura 4 – Resultado.

Si hace memoria notara que el ejemplo es el mismo de la entrada pasada sobre archivos Excel y notara que la estructura del código es en extremo similar de modo que actualizar un programa para hacer uso del nuevo formato no requerira demasiado esfuerzo.

Espero que esta entrada fuera de uso y nos vemos en la proxima.

Creando archivos Excel desde Java con Apache POI

Estándar

Como parte de un proyecto que maneje datos monetarios, como lo son precios es posible que se le solicite la posibilidad de exportar los datos del sistema a una hoja de calculo, con el fin de que los departamentos adecuados puedan realizar los cálculos y cuentas que les  sean necesarios.

Ya que la hoja de Calculo mas popular del mercado es Microsoft Excel, es una buena idea conocer como crear archivos que puedan ser abiertos y editados por este programa, a la vez que usar ese formato reduce riesgos de que ruido o problemas de importación hagan el archivo ilegible o los datos incorrectos.

Apache POI

Para la generación del los archivos Excel haremos uso de las librerías Apache POI, las cuales puede obtener en la pagina: http://poi.apache.org/ .

Para este punto ya sabra como agregar librerias a un proyecto de Eclipse, en caso de que no puedo recomendar la entrada: https://hashblogeando.wordpress.com/2014/04/27/crear-una-libreria-en-eclipse/ donde podra ver como llevar a cabo este procedimiento.

Figura 1 - Librerias POI

Figura 1 – Librerias POI

 

Codigo.

package mx.hashSoft.excel;

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

import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;

public class Excel {

static public void main(String[] args) {

HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet(“Reporte de productos”);

Row fila = sheet.createRow(0);
File archivo = new File(“ejemplo.xls”);
Cell celda;

String[] titulos = { “id”, “Cantidad”, “Consumo”, “Precio compra”, “Precio Venta” };
Double[] datos = { 1.0, 10.0, 45.0, 14.50, 30.50 };

int i;

// Creamos el encabezado

for (i = 0; i < titulos.length; i++) {
      celda = fila.createCell(i);
      celda.setCellValue(titulos[i]);
}

// Nueva fila

fila = sheet.createRow(1);

for (i = 0; i < datos.length; i++) {
      celda = fila.createCell(i);
      celda.setCellValue(datos[i]);
}

// Escribimos el archivo
try {
      FileOutputStream out = new FileOutputStream(archivo);
      workbook.write(out);
      out.close();

      System.out.println(“Archivo creado exitosamente!”);

} catch (IOException e) {
      System.out.println(“Error de escritura”);
e.printStackTrace();
}
}
}

Comentarios del código.

import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;

Estas son las librerías que necesitaremos, para crear el libro de Excel, la hoja de calculo, la fila y las celdas

HSSFWorkbook workbook = new HSSFWorkbook(); – Con esto creamos un nuevo libro de trabajo, el cual contendrá todas las hojas de calculo que necesitemos crear

HSSFSheet sheet = workbook.createSheet(“Reporte de productos”); – Vía el libro de trabajo que acabamos de crear generamos una nueva hoja de calculo, a la cual también el damos un nombre, este método lo podemos usar para crear cuantas hojas necesitemos

Row fila = sheet.createRow(0); – Creamos una nueva fila de celdas en la hoja de calculo, el numero de dicha fila sera el argumento de la función mas uno ya que Excel no maneja filas cero

File archivo = new File(“ejemplo.xls”); – El archivo en el que guardaremos la hoja de calculo, en este caso estamos creando una hoja de Excel formato 2003 asi que recuerde usar la extensión correcta.

Cell celda; – Esta variable hara referencia a una celda de la hoja de calculo, se usara posteriormente

celda = fila.createCell(i); – Con esto creamos una celda en la fila indicada, el numero que pasemos como argumento mas 1 sera la columna en la que dicha celda se ubicara

celda.setCellValue(titulos[i]); – Con este método especificamos el contenido de la celda, este método en particular tiene sobrecargas para manejar todos los tipos de datos que maneja excel

fila = sheet.createRow(1); – Con este método creamos una nueva fila ubicada en la posición siguiente

 FileOutputStream out = new FileOutputStream(archivo); – Creamos un flujo de datos de salida, el cual apuntara al archivo que creamos previamente y con el cual guardaremos el archivo.

workbook.write(out); – El método write almacena todo el contenido del libro de excel vía el flujo de datos que previamente creamos

out.close(); – Cerramos el flujo de datos, de modo que los datos se almacenen en disco duro.

Una vez que ejecute el programa obtendrá en la carpeta del proyecto algo similar al de la figura 2

Figura 2 - Archivo de salida

Figura 2 – Archivo de salida

Y cuando abra el archivo con Excel o con LibreOffice vera la salida mostrara en la figura 3

Figura 3 - Salida

Figura 3 – Salida

Algo que comentar es que este ejemplo crea un archivo Excel en formato Office 2003, las librerías POI también permiten generar archivos xlsx (Office 2007 y  superior) lo cual se describe en esta entrada: Creando archivos Excel en formato .xlsx

Espero que el ejemplo le de los datos necesarios para poder aplicar esto en alguna forma, que fuera útil y nos vemos en otra entrada.