Cómo generar Hojas de Excel en una aplicación JAVA usando Apache POI

El presente tutorial espero les sirva como referencia para el uso de la librería POI. Si tienen alguna observación y/o corrección deseo que me la hagan llegar.

Al principio, descargas los jars correspondientes a la última versión desde la web de Apache POI (http://poi.apache.org/)

Copias los jars en la carpeta de librerías (WEB-INF/lib).

Es importante tener en cuenta que cada archivo de Excel representa un LIBRO, dentro de cada libro tenemos HOJAS, dentro de cada HOJA tenemos FILAS, y, finalmente, en cada FILA tenemos CELDAS. Hago mención de esto porque nos ayudará a ver cómo se organiza la información en el archivo.

Primero, necesitamos crear un LIBRO haciendo uso de la blasé HSSFWorkbook:

// Proceso la información y genero el xls.

HSSFWorkbook objWB = new HSSFWorkbook();

… a continuación, creamos la hoja con la clase HSSFSheet

// Creo la hoja

HSSFSheet hoja1 = objWB.createSheet("hoja 1");

… luego, creamos la fila con HSSFRow

// creo la fila.
HSSFRow fila = hoja1.createRow((short)1);

Notemos que el valor que se envía al método encargado de crear las filas es de tipo short, el mismo que indica el número correspondiente a la fila que hemos de trabajar. El índice de las filas empieza en “0″, aunque ello no nos impide trabajar directamente con otras filas.

Una vez creada la fila, empezamos a trabajar con las celdas.

// Aunque no es necesario podemos establecer estilos a las celdas.
// Primero, establecemos el tipo de fuente
HSSFFont fuente = objLibro.createFont();
fuente.setFontHeightInPoints((short)11);
fuente.setFontName(fuente.FONT_ARIAL);
fuente.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);

// Luego creamos el objeto que se encargará de aplicar el estilo a la celda
HSSFCellStyle estiloCelda = objLibro.createCellStyle();
estiloCelda.setWrapText(true);
estiloCelda.setAlignment(HSSFCellStyle. ALIGN_JUSTIFY);
estiloCelda.setVerticalAlignment(HSSFCellStyle.VERTICAL_TOP);
estiloCelda.setFont(fuente);

// También, podemos establecer bordes...
estiloCelda.setBorderBottom(HSSFCellStyle.BORDER_MEDIUM);
estiloCelda.setBottomBorderColor((short)8);
estiloCelda.setBorderLeft(HSSFCellStyle.BORDER_MEDIUM);
estiloCelda.setLeftBorderColor((short)8);
estiloCelda.setBorderRight(HSSFCellStyle.BORDER_MEDIUM);
estiloCelda.setRightBorderColor((short)8);
estiloCelda.setBorderTop(HSSFCellStyle.BORDER_MEDIUM);
estiloCelda.setTopBorderColor((short)8);

// Establecemos el tipo de sombreado de nuestra celda
estiloCelda.setFillForegroundColor((short)22);
estiloCelda.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);

// Creamos la celda, aplicamos el estilo y definimos
// el tipo de dato que contendrá la celda
HSSFCell celda = objFila.createCell((short)0);
celda.setCellStyle(estiloCelda);
celda.setCellType(HSSFCell.CELL_TYPE_STRING);

// Finalmente, establecemos el valor
celda.setCellValue("Un valor");

Como podemos apreciar en el código tenemos la posibilidad de establecer estilos mediante las clases HSSFFont y HSSFCellStyle.

La primera, nos permite establecer el tipo de fuente que se empleará para la celda que hemos de utilizar. Para ello, contamos con los métodos setPointHeightInPoints que recibe un valor de tipo short que representa el tamaño de la fuente; el método setFontName el mismo que recibe una constante de la misma clase que nos permite establecer la fuente que se ha de emplear, y, otros métodos como: setBoldweight y setUnderline, entre otros, que nos permitirán aplicarle otros estilos y efectos al valor que ocupe nuestra celda.

La segunda, es la clase que, finalmente, nos ayudará a aplicar el estilo a la celda. Podemos acomodar y alinear el texto mediante los métodos setWrapText, setAlignment y setVerticalAlignment; aplicar la fuente trabajada, con el método setFont; configurar los bordes mediante los métodos: setBorderBottom, setBorderLeft, setBorderRight, setBorderTop, para el tipo; y, setBottomBorderColor, setLeftBorderColor, setRightBorderColor, setTopBorderColor para establecer el color de los bordes; y, establecer el sombreado de las celdas mediante los métodos setFillForegroundColor, setFillBackgroundColor y setFillPattern .

Aunque, es un poco ‘engorroso’ andar trabajando estos estilos, celda por celda, de esta forma, lo mejor es encapsular todo este proceso en métodos que nos permitan ahorrar líneas de código, preestableciendo, los estilos que se emplearán.

Según la versión de la librería que se esté empleando, podremos contar o no, con algunas constantes para la configuración del color y el establecimiento de los sombreados. Por ello adjunto información respecto a los colores en el anexo A y respecto a los sombreados en el Anexo B, al final del documento.

Finalmente, volcamos nuestro libro a un archivo de la siguiente forma:

// Volcamos la información a un archivo.
String strNombreArchivo = "C:/libro1.xls";
File objFile = new File(strNombreArchivo);
FileOutputStream archivoSalida = new FileOutputStream(objFile);
objWB.write(archivoSalida);
archivoSalida.close();

A continuación les presento el código completo..

// Proceso la información y genero el xls
HSSFWorkbook objWB = new HSSFWorkbook();

// Creo la hoja
HSSFSheet hoja1 = objWB.createSheet("hoja 1");

// Proceso la información y genero el xls.
HSSFRow fila = hoja1.createRow((short)1);

// Aunque no es necesario podemos establecer estilos a las celdas.
// Primero, establecemos el tipo de fuente
HSSFFont fuente = objLibro.createFont();
fuente.setFontHeightInPoints((short)11);
fuente.setFontName(fuente.FONT_ARIAL);
fuente.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);

// Luego creamos el objeto que se encargará de aplicar el estilo a la celda
HSSFCellStyle estiloCelda = objLibro.createCellStyle();
estiloCelda.setWrapText(true);
estiloCelda.setAlignment(HSSFCellStyle. ALIGN_JUSTIFY);
estiloCelda.setVerticalAlignment(HSSFCellStyle.VERTICAL_TOP);
estiloCelda.setFont(fuente);

// También, podemos establecer bordes...
estiloCelda.setBorderBottom(HSSFCellStyle.BORDER_MEDIUM);
estiloCelda.setBottomBorderColor((short)8);
estiloCelda.setBorderLeft(HSSFCellStyle.BORDER_MEDIUM);
estiloCelda.setLeftBorderColor((short)8);
estiloCelda.setBorderRight(HSSFCellStyle.BORDER_MEDIUM);
estiloCelda.setRightBorderColor((short)8);
estiloCelda.setBorderTop(HSSFCellStyle.BORDER_MEDIUM);
estiloCelda.setTopBorderColor((short)8);

// Establecemos el tipo de sombreado de nuestra celda
estiloCelda.setFillForegroundColor((short)22);
estiloCelda.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);

// Creamos la celda, aplicamos el estilo y definimos
// el tipo de dato que contendrá la celda
HSSFCell celda = objFila.createCell((short)0);
celda.setCellStyle(estiloCelda);
celda.setCellType(HSSFCell.CELL_TYPE_STRING);

// Finalmente, establecemos el valor
celda.setCellValue("Un valor");

// Volcamos la información a un archivo.
String strNombreArchivo = "C:/libro1.xls";
File objFile = new File(strNombreArchivo);
FileOutputStream archivoSalida = new FileOutputStream(objFile);
objWB.write(archivoSalida);
archivoSalida.close();

Aunque el ejemplo es un tanto simplón, todo lo presentado aquí generalmente se combina con arreglos de beans y bucles, los cuales, nos ayudarán a presentar más datos en nuestras hojas de Excel.

El objetivo de este tutorial no es mostrar todas las opciones disponibles, sino solo presentar un pequeño caso práctico sobre el uso de HSSF (POI) para la generación de archivos en formato Excel.

Deseo mencionar que para la creación del presente tutorial me basé en la documentación de la página de Apache POI así como también al contenido de la página JAVA DRIVE (en japonés).

~ por apiconz en Octubre 22, 2007.

33 comentarios to “Cómo generar Hojas de Excel en una aplicación JAVA usando Apache POI”

  1. Excelente tutorial, muchas gracias

  2. Muy bueno el tutorial, es excelente si quieres te envio informacion sobre otras cosas de utilidad de java.
    a mi correo
    sbravo@fach.cl

  3. [...] Cómo generar Hojas de Excel en una aplicación JAVA usando Apache POI http://apiconz.wordpress.com/2007/10/22/como-generar-hojas-de-excel-en-una-aplicacion-java-usando-ap... [...]

  4. Parce la verdad quiero aprender a utilizar esa jonda de POI nada que puedo hp no se que hacer ud donde vive necesito la ayuda de alguie.

    tengo un archivo de excely quiero generar un reporte basado en ese mismo archivo es para generar unos boletins para un colegio por favor mi correo es camilornest_2@hotmail.com gracias le agradecere la colaboracion..

    y esta excelente el sitio es el unico en el que muestran ejemplos de como usar la POI

  5. Parce la verdad quiero aprender a utilizar esa jonda de POI nada que puedo hp no se que hacer ud donde vive necesito la ayuda de alguie.

    tengo un archivo de excel y quiero generar un reporte basado en ese mismo archivo es para generar unos boletines para un colegio por favor mi correo es camilornesto_2@hotmail.com gracias le agradecere la colaboracion..

    y esta excelente el sitio es el unico en el que muestran ejemplos de como usar la POI

  6. exelente tu tutorial lo has probado

  7. Hola
    Excelente tutorial, tengo una unica pregunta, ¡sabes como hacer para adaptar el tamaño de las columnas de acuerdo al texto mas grande?
    Salu2 y Gracias

  8. muy buen tutorial, pero eres un PERO ERES UN PINCHE PRESUMIDO!!!

    oni he itte!!!

  9. Excelente tutorial solo que deberias poner codigo o explicar como leer de un archivo de excel para meter los datos en una base de datos.

  10. Otra cosa cual de todas las librerias que aparecen el pagina APACHE POI se baja para que funciona esto.

  11. Hola; soy nueva en esto de utilizar poi; pero gracias a este tutorial he aprendido mucho; pero me falta saber una cosa; resulta que estoy trabajando en un sistema en donde genero un archivo excel con datos; en eso no tengo problemas; sino que debe tener una imagen de la empresa (logo.jpg); y no se como agregarlo a mi documento excel. Agradeceria que me ayudaran en esto. Gracias

  12. Buenas,

    Necesito generar un nuevo excel a partir de otro, pero que respete el formato de las celdas (si tiene color, si está en otra letra, incluso el MERGE and CENTER), como lo puedo hacer???

  13. ya baje las clases POI para poder manipular la información de exel pero al momento de pegar los objetos en exel me borra el contenido que esta en otras celdas como por ejemplo los encabezados anexo codigo donde se pega la informacion

    HSSFRow row = sheet.createRow((short)1);//aqui es donde se defin en que celda empezara a pegar los datos

    HSSFWorkbook workbook = new HSSFWorkbook();
    FileOutputStream fOut = new FileOutputStream(salaryBookPath);
    HSSFSheet sheet = workbook.createSheet(“Carga”);

    HSSFRow row = sheet.createRow((short)1);/*aqui es donde se defin en que celda empezara a pegar los datos*/
    HSSFCell cell = row.createCell((short) 0);
    HSSFCell cell1 = row.createCell((short) 1);
    HSSFCell cell2 = row.createCell((short) 2);

    y este es el codigo completo para que lo vean:

    package com.sforce.soap.lectura;

    import java.io.BufferedReader;
    import com.sforce.soap.enterprise.*;
    import com.sforce.soap.enterprise.sobject.Account;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.InputStream;
    import org.apache.poi.hssf.usermodel.HSSFCell;
    import org.apache.poi.hssf.usermodel.HSSFRow;
    import org.apache.poi.hssf.usermodel.HSSFSheet;
    import org.apache.poi.hssf.usermodel.HSSFWorkbook;
    import org.apache.poi.poifs.filesystem.POIFSFileSystem;

    public class CargaExcel {

    private SoapBindingStub sfdc;
    private LoginResult LoginResult = null;
    private boolean loggedIn = false;
    private HSSFSheet dtCuentas = null;
    private String salaryBookPath = “D://eclipse//projects//carga.xls”;
    private HSSFWorkbook libro = null;
    private POIFSFileSystem fs = null;

    //static BufferedReader rdr =
    // new BufferedReader(new java.io.InputStreamReader(System.in));

    public static void main(String[] args){

    CargaExcel leer = new CargaExcel();
    leer.consulta();
    }

    private boolean inicio() {

    try {
    // Create sfdc object
    sfdc = (SoapBindingStub) new SforceServiceLocator().getSoap();
    // login
    LoginResult = sfdc.login(“xxxxxxxxxxxxx”, “xxxxxxxxxxxxxxxxxxxxxx”);
    } catch (Exception ex) {
    System.out.println(“An unexpected error has occurred.” + ex.getMessage());
    return false;
    }

    // Reset the SOAP endpoint to the returned server URL
    sfdc._setProperty(SoapBindingStub.ENDPOINT_ADDRESS_PROPERTY, LoginResult.getServerUrl());
    // Create a new session header object
    // add the session ID returned from the
    SessionHeader sh = new SessionHeader();
    sh.setSessionId(LoginResult.getSessionId());
    sfdc.setHeader(“SforceService”, “SessionHeader”, sh);
    loggedIn = true;

    // get user info
    try {
    GetUserInfoResult userInfo = sfdc.getUserInfo();
    } catch (Exception ex) {
    System.out.println(“An unexpected error has occurred.” + ex.getMessage());
    return false;
    }

    return true;
    }

    private void consulta() {

    if (!loggedIn) {
    if (!inicio()) {
    return;
    }
    }
    QueryResult queryResult = null;

    try{

    queryResult = sfdc.query(“Select p.Id,p.Name,p.Website,p.Type from Account p where p.Name = ‘Acme’”);
    boolean done = false;
    while (!done){
    for (int i=0; i<queryResult.getRecords().length; i++) {
    Account pos = (Account)queryResult.getRecords(i);
    String id = pos.getId();
    String Name = pos.getName();
    String Type = pos.getType();
    String Website = pos.getWebsite();
    System.out.println(id);
    System.out.println(Name);
    System.out.println(Type);
    System.out.println(Website);
    //aqui se realiza el mapeo pero borra la primer celda
    HSSFWorkbook workbook = new HSSFWorkbook();
    FileOutputStream fOut = new FileOutputStream(salaryBookPath);
    HSSFSheet sheet = workbook.createSheet(“Carga”);
    HSSFRow row = sheet.createRow((short)1);//aqui es donde se defin en que celda empezara a pegar los datos
    HSSFCell cell = row.createCell((short) 0);
    HSSFCell cell1 = row.createCell((short) 1);
    HSSFCell cell2 = row.createCell((short) 2);
    cell.setCellValue(pos.getId());
    cell1.setCellValue(pos.getName());
    cell2.setCellValue(pos.getWebsite());
    workbook.write(fOut);
    fOut.close();

    if (queryResult.isDone()) {
    done= true;
    }
    else {
    queryResult = sfdc.queryMore(queryResult.getQueryLocator());
    }
    }
    System.out.println(“Carga ejecutada con exito”);
    }
    }
    catch (Exception ex)
    {
    System.out.println(“\nFailed to cargar información, error message was: \n” +
    ex.getMessage());
    }

    }
    }

    GRacias

  14. a mi no m sale nada, m da el siguiente error
    Activation.main: advertencia: no se han especificado las propiedades del sistema sun.rmi.activation.execPolicy

  15. Hola, tengo una pregunta estoy intentando exportar el valor de un resulset a excel, pero al hacerlo me manda un erro, te dejo el código con el que lo hago y al final el error que me manda, espero puedas ayudarme.

    public static void main(String[] args) {
    try{
    DriverManager.registerDriver(new com.microsoft.sqlserver.jdbc.SQLServerDriver());
    Connection con = DriverManager.getConnection(“conexion”);
    Statement stmt = con.createStatement();
    String query = “select IdCliente, NumContrato,IDDivision, Nombre, Colonia from tblClientes where iddivision=51 and idcliente=67″;

    ResultSet resultSet = stmt.executeQuery(query);
    RowSetDynaClass rowSet = new RowSetDynaClass(resultSet, false);
    Map beans = new HashMap();
    beans.put(“tblClientes”, rowSet.getRows()); //employee
    XLSTransformer transformer = new XLSTransformer();
    transformer.toString();
    transformer.transformXLS( “C://sistemas//java//webExcel//sql.xls”, beans, “C://sistemas//java//webExcel//Template22.xls”);
    }
    catch(Exception e){
    System.out.println(e.getMessage());
    }
    }

    Exception in thread “main” java.lang.NoSuchMethodError: org.apache.poi.hssf.usermodel.HSSFCell.setEncoding(S)V
    at org.jxls.transformer.CellTransformer.transform(CellTransformer.java:92)
    at org.jxls.transformer.SimpleRowTransformer.transform(SimpleRowTransformer.java:54)
    at org.jxls.transformer.CollectionRowTransformer.transform(CollectionRowTransformer.java:72)
    at org.jxls.transformer.SheetTransformer.transformSheet(SheetTransformer.java:88)
    at org.jxls.transformer.XLSTransformer.transformXLS(XLSTransformer.java:226)
    at org.jxls.transformer.XLSTransformer.transformXLS(XLSTransformer.java:194)
    at src.clsConectaExcel.main(clsConectaExcel.java:54)

    y esto es lo que tendo en el archivo sql.xls

    ${employee.name} ${employee.age} ${employee.birthdate} ${employee.payment} ${employee.bonus}

  16. estoy desarrollando una aplicacion mediante web en apache haciendo consultas a bases de datos en oracle, pero tambien manipulo los archivos con POI solo que al generar el reporte tengo un error de java heap space, lo he corrido con -Xmx1024m pero aun asi no se soluciona y en la traza de error marca una linea de codigo donde se añade contenido a una celda….

    me gustaria saber si es el POI o necesito alguna clase de optimizacion o de otro framework que me ayude, gracias

  17. hola muy bueno el tutorial, gracias.

    Hubiese sido ideal que explicaras sobre un método que permita cambiar el ancho de la celda de acuerdo al texto que se le incorpora.

  18. Hola, a ver si me pueden ayudar.

    estoy utilizando la version 3.2

    hago lo siguiente:

    cell.setCellValue(Double.parseDouble(sharePercent)/100);

    pero luego no consigo ponerle un formato que me pinte el valor en como un porcentaje con dos dígitos en la parte decimal.

    si al estylo le pongo esto style.setDataFormat((short)0xa); me corre la coma a la izda. He probado tb a poner style.setDataFormat(format.getFormat(“00,00%”)); y otras formas.

    Saludos y gracias.

    ¿Sabeis como hacerlo?

  19. Hola, gracias por poblicar el tutorial esta muy bueno, pero tengo un problema y una pregunta. El problema es que cuando corro la aplicación en debian me da un error de ejecución: java.lang.NoSuchMethodError: org.apache.poi.hssf.usermodel.HSSFSheet.createRow(I)Lorg/apache/poi/hssf/usermodel/HSSFRow;

    y la pregunta es si hay forma de establecer el ancho de cada columna de acuerdo al texto?

    Gracias

  20. Bueno el tutorial, yo lo único que quisiera saber, si es posible, es cómo inserto un combo box en una celda… eso no lo encuentro, ni lo logro ver en la documentación, porque algunas partes están muy faltas de explicación ni ningún tutorial dice cómo hacerlo… o algún libro, página que me puedan recomendar??

    • Hola quizas sea un poco tarde para esto, pero recien estoy usando el POI el cual me parece interesante, este link quizas pueda ayudarte con lo que necesitas

      http://poi.apache.org/spreadsheet/quick-guide.html#Validation

      Drop Down Lists:

      This code will do the same but offer the user a drop down list to select a value from.

      HSSFWorkbook workbook = new HSSFWorkbook();
      HSSFSheet sheet = workbook.createSheet(“Data Validation”);
      CellRangeAddressList addressList = new CellRangeAddressList(
      0, 0, 0, 0);
      DVConstraint dvConstraint = DVConstraint.createExplicitListConstraint(
      new String[]{“10″, “20″, “30″});
      HSSFDataValidation dataValidation = new HSSFDataValidation
      (addressList, dvConstraint);
      datavalidation.setSuppressDropDownArrow(false);
      sheet.addValidationData(dataValidation);

  21. Aunque aquí nadie responde a nada, voy a probar suerte.
    ¿¿Cómo podría, desde una aplicación, hacer que no creara un archivo en disco sino que se descargara directamente??

    Salu2

  22. Hace mucho que no respondo un comentario, pero lo que te puedo sugerir es que busques la forma de escribir con un servlet el resultado a través de un BufferString o algo asi y seteas el document type al tipo que corresponde.

    Es lo que se me viene a la mente :)

  23. Hola quisiera citar la pregunta hecha por Alejandro ya que tambien necesito la respuesta: “hola muy bueno el tutorial, gracias.

    Hubiese sido ideal que explicaras sobre un método que permita cambiar el ancho de la celda de acuerdo al texto que se le incorpora.

    alejandro dijo esto en Enero 21, 2009″.
    De antemano muchas gracias

  24. Bueno, ya encontre una solucion, la pongo aca por si a alguien mas le sirve (extraida de la pagina http://poi.apache.org):
    Sheet hoja1 = workbook.getSheetAt(0);
    hoja1.autoSizeColumn((short)0); //ajusta el ancho de la primera columna
    hoja1.autoSizeColumn((short)1); //ajusta el ancho de la segunda columna

    Y para mezclar celdas existe este metodo:
    hoja1.addMergedRegion(new CellRangeAddress(fi,ff,ci,cf));
    Donde los parametros estan dados por
    int fi: Fila inicial
    int ff: Fila final
    int ci: columna inicial
    int cf: columna final

  25. Hola!! que pasa cuando queremos utilizar XSSF?? esto es paa leer los nuevos archivos de word y excel!!! gracias

  26. hola …..muy buen tutorial …..

    pero tengo una pregunta estoy haciendo una aplicacion con ICEFACES y utilizo como servidor a GLASSFISH V2 y necesito generar hojas de excel…. NO HAY PROBLEMA SI UTILIZO LAS LIBRERIAS DE APACHE POI ya que el servidor que utilizo es glassfish ?????????….necesito saber de urgencia ….

    GRACIAS..!!!!

  27. Muy buen tutorial, gracias!!

    pero tengo el mismo problema que arturo (pregunta del 12 de junio 2009). De hecho, yo he añadido: “import org.apache.poi.xssf.usermodel.XSSFWorkbook;” pero al hacer esto:
    Workbook wb = new XSSFWorkbook();
    me da el error siguiente:
    “El tipo java.lang.Iterable no se puede resolver. Se le hace referencia indirectamente desde los archivos .class necesarios”.
    Qué significa esto??? gracias ….

  28. Muy Buen Tutorial

  29. Hola, como estan muchachos acabo conocer POI mediante ustedes. Mi pregunta es ¿Cómo puedo leer un archivo Excel?.

    Ya que necesito esa información para llenar de unarchivo exce un una tabla de base de datos. Muchas Gracias de antemano.

  30. hola espero alguien pueda leer esto… necesito sabercomo poner informacion en una celda especifica… es que este tutorial hace que nadamas ponga info en la celda en la columna y celda que creo peropara poner informacion en distintas celdas como le hago… gracias

  31. una vez creada la fila, ¿se puede modificar algun registro en pàrticular?, pues quise hacer varias tablas en una misma fila, pero solo veia que se podia trabajar solo en una de de ellas un lado de una de la otra, Gracias

Deja un comentario