Introdución a Apache POI
Apache POI es una biblioteca de código abierto de la Fundación de Software Apache, que proporciona API en Java para leer y escribir archivos en formatos de Microsoft Office.
Componentes Princpiales
- HSSF: Permite la lectura y escritura de archivos en formato Excel (.xls).
- XSSF: Soporta el formato Excel OOXML (.xlsx).
- HWPF: Manipula documentos de Word.
- HSLF: Trabaja con presentaciones de PowerPoint.
- HDGF: Gestiona archivos de Visio.
Para usar POI, se debe incluir la siguiente dependencia en el proyecto:
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
</dependency>
Nota: La versión 3.17 es la última compatible con JDK 6.
Conceptos de HSSF
HSSF, acrónimo de Horrible SpreadSheet Format, ofrece dos tipos de API para operaciones de lectura: el modelo de usuario (usermodel) y el modelo de eventos (eventusermodel).
Clases para la Estructura de Documentos Excel
- HSSFWorkbook: Representa el libro de Excel.
- HSSFSheet: Corresponde a una hoja de cálculo.
- HSSFRow: Define una fila.
- HSSFCell: Indica una celda.
- HSSFFont: Maneja estilos de fuente.
- HSSFCellStyle: Controla el formato de celdas.
- HSSFDataFormat: Formatea datos como fechas.
- HSSFHeader/HSSFFooter: Gestionan encabezados y pies de página.
- HSSFPrintSetup: Configura opciones de impresión.
Ejemplos de Lectura y Escritura
Lectura de Datos desde un Archivo Excel
El siguiente método lee datos de un archivo Excel y los almacena en una lista. Se asume un archivo con columnas: código de área, provincia, ciudad, distrito y código postal.
public List<Region> cargarDatosDesdeExcel() {
List<Region> registros = new ArrayList<>();
try (InputStream flujo = new FileInputStream("ruta/archivo.xls")) {
HSSFWorkbook libroExcel = new HSSFWorkbook(flujo);
HSSFSheet hojaDatos = libroExcel.getSheetAt(0);
for (int indice = 1; indice <= hojaDatos.getLastRowNum(); indice++) {
HSSFRow filaActual = hojaDatos.getRow(indice);
if (filaActual == null) continue;
String codigoArea = obtenerTextoCelda(filaActual.getCell(0));
String nombreProvincia = obtenerTextoCelda(filaActual.getCell(1));
String nombreCiudad = obtenerTextoCelda(filaActual.getCell(2));
String nombreDistrito = obtenerTextoCelda(filaActual.getCell(3));
String codigoPostal = obtenerTextoCelda(filaActual.getCell(4));
Region region = new Region();
region.setCodigoArea(codigoArea);
region.setProvincia(nombreProvincia);
region.setCiudad(nombreCiudad);
region.setDistrito(nombreDistrito);
region.setCodigoPostal(codigoPostal);
registros.add(region);
}
libroExcel.close();
} catch (IOException e) {
e.printStackTrace();
}
return registros;
}
private String obtenerTextoCelda(HSSFCell celda) {
if (celda == null) return "";
return celda.getStringCellValue();
}
Exportación de Datos a un Archivo Excel
Este método genera un archivo Excel a partir de una lista de objetos, con encabezados personalizados. Incluye manejo de respuestas HTTP para descargas.
public void generarArchivoExcel(HttpServletResponse respuesta, List<Region> datos) throws IOException {
HSSFWorkbook libro = new HSSFWorkbook();
HSSFSheet hoja = libro.createSheet("Regiones");
// Crear fila de encabezados
HSSFRow filaEncabezado = hoja.createRow(0);
String[] titulos = {"Provincia", "Ciudad", "Distrito", "Código Postal", "Código Corto"};
for (int i = 0; i < titulos.length; i++) {
filaEncabezado.createCell(i).setCellValue(titulos[i]);
}
// Llenar datos
for (int idx = 0; idx < datos.size(); idx++) {
Region reg = datos.get(idx);
HSSFRow filaDatos = hoja.createRow(idx + 1);
filaDatos.createCell(0).setCellValue(reg.getProvincia());
filaDatos.createCell(1).setCellValue(reg.getCiudad());
filaDatos.createCell(2).setCellValue(reg.getDistrito());
filaDatos.createCell(3).setCellValue(reg.getCodigoPostal());
filaDatos.createCell(4).setCellValue(reg.getCodigoCorto());
}
// Configurar respuesta para descarga
String nombreArchivo = "exportacion_datos.xlsx";
respuesta.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
respuesta.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(nombreArchivo, "UTF-8"));
try (ServletOutputStream flujoSalida = respuesta.getOutputStream()) {
libro.write(flujoSalida);
}
libro.close();
}
Métodos Comunes para Operaciones con Excel
Creación y Lectura de Objetos
// Abrir un archivo existente
POIFSFileSystem sistemaArchivos = new POIFSFileSystem(new FileInputStream("documento.xlsx"));
HSSFWorkbook libroTrabajo = new HSSFWorkbook(sistemaArchivos);
HSSFSheet hojaCalculo = libroTrabajo.getSheetAt(0);
HSSFRow fila = hojaCalculo.getRow(indiceFila);
HSSFCell celda = fila.getCell(indiceColumna);
HSSFCellStyle estilo = celda.getCellStyle();
// Crear un nuevo libro
HSSFWorkbook nuevoLibro = new HSSFWorkbook();
HSSFSheet nuevaHoja = nuevoLibro.createSheet("Hoja1");
HSSFRow nuevaFila = nuevaHoja.createRow(0);
HSSFCellStyle nuevoEstilo = nuevoLibro.createCellStyle();
nuevaFila.createCell(0).setCellValue("Ejemplo");
Manipulación de Contenido
- Configurar nombre de hoja:
libro.setSheetName(indice, "Título", HSSFCell.ENCODING_UTF_16); - Obtener número de hojas:
int totalHojas = libro.getNumberOfSheets(); - Ajustar dimensiones:
hoja.setColumnWidth(columna, ancho); fila.setHeight(alto); - Combinar celdas: Ussar
Regionyhoja.addMergedRegion(region);
Estilos y Formato
HSSFCellStyle estiloCelda = libro.createCellStyle();
estiloCelda.setBorderBottom(HSSFCellStyle.BORDER_DOTTED);
estiloCelda.setBorderLeft(HSSFCellStyle.BORDER_DOTTED);
HSSFFont fuente = libro.createFont();
fuente.setFontHeightInPoints((short) 12);
fuente.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
estiloCelda.setFont(fuente);
estiloCelda.setAlignment(HSSFCellStyle.ALIGN_CENTER);
Manejo de Imágenes
ByteArrayOutputStream flujoBytes = new ByteArrayOutputStream();
BufferedImage imagen = ImageIO.read(new File("imagen.jpg"));
ImageIO.write(imagen, "jpg", flujoBytes);
HSSFPatriarch dibujante = hoja.createDrawingPatriarch();
HSSFClientAnchor ancla = new HSSFClientAnchor(0, 0, 1023, 255, (short) 0, 0, (short) 1, 1);
dibujante.createPicture(ancla, libro.addPicture(flujoBytes.toByteArray(), HSSFWorkbook.PICTURE_TYPE_JPEG));
Lectura Versátil de Valores
public String extraerValorCelda(HSSFCell celda) {
if (celda == null) return "";
switch (celda.getCellType()) {
case HSSFCell.CELL_TYPE_STRING:
return celda.getStringCellValue().trim();
case HSSFCell.CELL_TYPE_NUMERIC:
return String.valueOf(celda.getNumericCellValue());
case HSSFCell.CELL_TYPE_FORMULA:
celda.setCellType(HSSFCell.CELL_TYPE_NUMERIC);
return String.valueOf(celda.getNumericCellValue());
case HSSFCell.CELL_TYPE_BOOLEAN:
return String.valueOf(celda.getBooleanCellValue());
default:
return "";
}
}