Revista Tecnología

API POI de Apache. Hojas de cálculo I

Publicado el 14 abril 2015 por Instintobinario

En muchas ocasiones necesitamos que nuestros programas guarden los datos de forma persistente para poderlos recuperar cuando volvamos a arrancar el programa de nuevo. Existen varias opciones para dar solución a esto: utilizar una base de datos, guardar la configuración o información en archivos de texto plano… Sin embargo, en ocasiones, una base de datos es demasiado elaborada para los datos que debemos guardar, y un texto plano acaba siendo una auténtico desorden de información que no sabemos cómo encontrar. Para esto existe una solución a medio camino que permite mantener la información ordenada sin necesidad de construir una compleja base de datos: las hojas de cálculo o de Excel.

En este artículo voy a explicar cómo leer una hoja de cálculo de Excel desde un programa Java. Para ello vamos a utilizar una API de Apache para interactuar con todo tipo de documentos de Microsoft Office: Excel, Word, Power Point… Pero nosotros solamente vamos a centrarnos en los documentos xls y xlsx de Excel.

Introducción

En ésta API tenemos disponibles, básicamente, 3 paquetes:

  • Uno de alto nivel para las hojas de cálculo en general (package: org.apache.poi.ss.usermodel), que es la que la mayoría de la gente debe utilizar y la más simple.
  • El paquete para ficheros tipo xls (package: org.apache.poi.hssf.usermodel), que permite control de nivel más bajo.
  • Y el paquete para los nuevos formatos desde Excel 2007 OOXML, el xlsx (package: org.apache.poi.xssf.usermodel).

En éste caso vamos a utilizar solamente los elementos del paquete ss.usermodel, ya que se trata de un manual básico y simple de lectura y escritura de documentos Excel. Si se quiere profundizar, podéis acudir a la documentación oficial de apache para ésta API en éste enlace. Si lo que necesitáis es una guía de referencia de las clases y métodos es mejor que visitéis el Java doc del API.

Creación de un Libro de Excel

Para la creación de un nuevo libro de Excel (en adelante Workbook) vamos a utilizar la clase WorkbookFactory, la cual nos crea de forma automática el tipo de Workbook que más nos convenga (HSSFWorkbook o XSSFWorkbook). Vamos a utilizar como parámetro un InputStream. El código es el siguiente:

InputStream fIS = new FileInputStream("workbook.xlsx");
Workbook wb = WorkbookFactory.create(fIS);
fIS.close();

Una vez creado el Workbook, ya no necesitamos el InputStream, así que ya podemos cerrarlo. Además, hay que tener en cuenta que el InputStream lanza una excepción IOException, y la creación del Workbook lanza InvalidFormatException.

Lectura de Celdas de un Workbook

Para poder leer los contenidos del Workbook debemos extraer las hojas que contienen los datos. Para ello podemos referenciar la hoja por nombre o por índice:

Sheet s1 = wb.getSheet("Hoja 1");   //sheet by name
Sheet s2 = wb.getSheetAt(0);   //sheet by index

Una vez que tenemos la hoja que necesitamos (será necesario conocer la estructura interna del Workbook si no queremos recorrerlo todo), debemos contar con que los datos de la hoja se organizan por filas. Es decir, para acceder a una celda, debemos extraer primero la fila y luego la columna (la celda en sí). Para extraer una Fila, utilizamos el siguiente método (referenciando por índice):

Row r = s1.getRow(1);

Ahora que ya tenemos la fila en el objeto ‘r’, podemos acceder a las celdas de la misma de igual modo que hemos accedido a la fila:

Cell c = r.getCell(0);

Y ya tenemos la Celda que buscáramos. A partir de todo esto es fácil leer todos los datos de una hoja mediante dos bucles for del siguiente modo:

for(Row r : s) {
    for(Cell c : r) {
        [...]
    }
}

Extrayendo el contenido de la celda

Ahora que ya sabemos cómo llegar a una celda, necesitamos extraer la información que ésta contiene. La celda contiene un valor entero que representa el tipo de dato. Este tipo de dato está definido en la clase celda como un entero estático, correspondiendo de la siguiente forma:

CELL_TYPE_NUMERIC = 0
CELL_TYPE_STRING = 1
CELL_TYPE_FORMULA = 2
CELL_TYPE_BLANK = 3
CELL_TYPE_BOOLEAN = 4
CELL_TYPE_ERROR = 5

Para saber de qué tipo es una celda tenemos el siguiente método que nos devuelve un entero de acuerdo con los valores anteriores:

getCellType();

Para la obtención del valor de la celda, según el tipo de dato, tenemos los siguientes métodos:

getCellFormula();   //devuelve String
getBooleanCellValue();   //devuelve boolean
getDateCellValue();  //devuelve Date
getErrorCellValue();   //devuelve byte
getNumericCellValue();   //devuelve double
getRichStringCellValue();   //devuelve RichTextString
getStringCellValue();   //devuelve String

El RichTextString es un tipo de dato propio de ésta API al que se le puede aplicar una fuente a determinadas partes arbitrarias. Cada método se utiliza para extraer de las celdas que tienen el tipo de dato que se indica en el nombre del método. La excepción es el método getCellFormula(), que devuelve un String con la fórmula que contiene esa celda y getErrorCellValue(), que codifica el código de error como un valor byte.

Cuando una Celda tiene el valor de fórmula debemos saber cuál es el tipo de resultado que da para poder extraer dicho valor. Para extraer correctamente este valor debemos conocer el tipo de dato que da como resultado dicha fórmula, y para ello utilizamos el siguiente método que nos devolverá el tipo en forma de entero como sea visto antes:

getCachedFormulaResultType();

Métodos de ayuda

Existen algunos métodos auxiliares que nos pueden ayudar en la lectura. Vamos a ver cuáles hay en el Workbook, cuáles en la hoja y cuáles en la celda.

En el Workbook hay los siguientes métodos:

  • getActiveSheetIndex() -> Devuelve el índice (int) de la hoja activa del Workbook.
  • getNumberOfSheets() -> Devuelve el número de hojas del Workbook.
  • getSheetIndex(Sheet sheet) -> Devuelve el índice de la hoja indicada en el Workbook.
  • getSheetIndex(String name) -> Devuelve el índice de la hoja indicada por nombre en el Workbook.
  • getSheetName(int i) -> Devuelve el nombre de la hoja en el índice indicado.

En la hoja tenemos éstos:

  • getCellComment(int row, int column) -> Devuelve el comentario en un objeto Comment asignado a la celda dada por la fila y columna.
  • getFirstRowNum() -> Devuelve un entero con el índice de la primera fila de la hoja de Excel.
  • getLastRowNum() -> Devuelve un entero con el índice de la última fila de la hoja.
  • getPhysicalNumberOfRows() -> Devuelve un entero con el número de filas físicamente definidas en la hoja.
  • getSheetName() -> Devuelve el nombre de la hoja.
  • rowIterator() -> Devuelve un Iterador de las filas físicas. Esto nos permitiría recorrer las filas mediante dicho Iterador.
  • getWorkbook() -> Devuelve el Workbook que corresponde a la hoja en cuestión.

En la Fila tenemos éstos:

  • cellIterator() -> Devuelve un Iterador de las celdas. Esto nos permitiría recorrer las celdas mediante dicho Iterador.
  • getFirstCellNum() -> Devuelve el número de la primera celda de la fila.
  • getLastCellNum() -> Devuelve el número de la última celda de la fila.
  • getPhysicalNumberOfCells() -> Devuelve un entero con el número de celdas físicamente definidas en la fila.
  • getRowNum() -> Devuelve el número de la fila actual.
  • getSheet() -> Devuelve la hoja a la cual corresponde la fila.

En la Celda tenemos:

  • getCellComment() -> devuelve un objeto Comment con el comentario asignado a la celda.
  • getColumnIndex() -> devuelve un entero con el índice de la columna en la que está la celda.
  • getRow() -> Devuelve la fila a la que a la cual corresponde esta celda.
  • getRowIndex() -> Devuelve el índice de la fila en que se encuentra la celda.
  • getSheet() -> Devuelve la hoja a la cual corresponde la celda.

Esto no es todo lo que se puede hacer con ésta API, pero, evidentemente, no se puede detallar todas las funciones de la misma. Para ampliar información Puedes consultas el Java doc de a API o la web oficial.

En la segunda parte de esta guía explicaré la creación y escritura de datos en hojas de Excel.

El artículo API POI de Apache. Hojas de cálculo I apareció por primera vez en Instinto Binario.


Volver a la Portada de Logo Paperblog

Dossier Paperblog

Revista