Introducción a Apache POI
Apache POI es una API Java para manipular documentos en formatos de Microsoft. Sus componentes principales incluyen HSSF para archivos Excel (.xls) y HWPF para Word. HSSF es el módulo más maduro y estable.
Configuración de dependencias Maven
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.0</version>
</dependency>
Componentes principales de HSSF
- HSSFWorkbook: Representa un archivo Excel completo
- HSSFSheet: Hoja de cálculo dentro del libro
- HSSFRow: Fila en una hoja
- HSSFCell: Celda individual
- HSSFCellStyle: Configuración de estilos para celdas
Flujo básico de exportación
- Crear instancia de HSSFWorkbook
- Generar objeto HSSFSheet
- Crear filas mediante HSSFRow
- Definir celdas usando HSSFCell
- Escribir el workbook en HttpServletResponse
Clase de utilidad para exportación
public class ExportadorExcel {
public static Workbook generarLibro(String hoja, String[] titulos,
String[][] datos, Workbook libro) {
if (libro == null) libro = new HSSFWorkbook();
Sheet sheet = libro.createSheet(hoja);
// Crear estilo de celda centrado
CellStyle estilo = libro.createCellStyle();
estilo.setAlignment(HorizontalAlignment.CENTER);
// Generar encabezados
Row filaEncabezado = sheet.createRow(0);
for (int i = 0; i < titulos.length; i++) {
Cell celda = filaEncabezado.createCell(i);
celda.setCellValue(titulos[i]);
celda.setCellStyle(estilo);
}
// Llenar datos
for (int i = 0; i < datos.length; i++) {
Row filaDatos = sheet.createRow(i + 1);
for (int j = 0; j < datos[i].length; j++) {
filaDatos.createCell(j).setCellValue(datos[i][j]);
}
}
return libro;
}
}
Manejo de versiones y estilos
Para alineación de celdas en POI 3.17+:
CellStyle estilo = libro.createCellStyle();
estilo.setAlignment(HorizontalAlignment.CENTER);
estilo.setVerticalAlignment(VerticalAlignment.CENTER);
Lectura de archivos Excel
public List<Map<String, Object>> leerExcel(String ruta) throws IOException {
InputStream is = new FileInputStream(ruta);
Workbook libro = WorkbookFactory.create(is);
List<Map<String, Object>> datos = new ArrayList<>();
Sheet hoja = libro.getSheetAt(0);
// Procesar filas
for (Row fila : hoja) {
Map<String, Object> filaDatos = new HashMap<>();
for (Cell celda : fila) {
filaDatos.put("Col_" + celda.getColumnIndex(), obtenerValorCelda(celda));
}
datos.add(filaDatos);
}
return datos;
}
private String obtenerValorCelda(Cell celda) {
switch (celda.getCellType()) {
case STRING: return celda.getStringCellValue();
case NUMERIC: return String.valueOf(celda.getNumericCellValue());
case BOOLEAN: return String.valueOf(celda.getBooleanCellValue());
default: return "";
}
}
Contrloador de ejemplo para exportación
@RestController
@RequestMapping("/excel")
public class ControladorExcel {
@GetMapping("/exportar")
public void exportar(HttpServletResponse response) throws IOException {
String[] titulos = {"Nombre", "Edad"};
String[][] datos = {{"Ana", "25"}, {"Carlos", "30"}};
Workbook libro = ExportadorExcel.generarLibro("Datos", titulos, datos, null);
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment; filename=reporte.xls");
libro.write(response.getOutputStream());
}
}