1. Introducción
En este tutorial, demostraremos el uso de las API de Apache POI y JExcel para trabajar con hojas de cálculo de Excel .
Ambas bibliotecas se pueden utilizar para leer, escribir y modificar dinámicamente el contenido de una hoja de cálculo de Excel y proporcionar una forma eficaz de integrar Microsoft Excel en una aplicación Java.
2. Dependencias de Maven
Para comenzar, necesitaremos agregar las siguientes dependencias a nuestro archivo pom.xml :
org.apache.poi poi 3.15 org.apache.poi poi-ooxml 3.15
Las últimas versiones de poi-ooxml y jxls-jexcel se pueden descargar desde Maven Central.
3. Apache POI
La biblioteca Apache POI admite archivos .xls y .xlsx y es una biblioteca más compleja que otras bibliotecas de Java para trabajar con archivos de Excel.
Proporciona el libro de trabajo interfaz para modelar un Excel archivo, y la hoja , la fila y celulares interfaces que modelo de los elementos de un archivo de Excel, así como implementaciones de cada interfaz para ambos formatos de archivo.
Cuando se trabaja con la nueva .xlsx formato de archivo, debe utilizar los XSSFWorkbook, XSSFSheet, XSSFRow y XSSFCell clases .
Para trabajar con la mayor .xls formato, utilice los HSSFWorkbook, HSSFSheet, HSSFRow, y HSSFCell clases .
3.1. Leyendo desde Excel
Creemos un método que abra un archivo .xlsx y luego lea el contenido de la primera hoja del archivo.
El método para leer el contenido de la celda varía según el tipo de datos de la celda. El tipo de contenido de la celda se puede determinar mediante el método getCellTypeEnum () de la interfaz de la celda .
Primero, abramos el archivo desde una ubicación determinada:
FileInputStream file = new FileInputStream(new File(fileLocation)); Workbook workbook = new XSSFWorkbook(file);
A continuación, recuperemos la primera hoja del archivo e iteremos por cada fila:
Sheet sheet = workbook.getSheetAt(0); Map
data = new HashMap(); int i = 0; for (Row row : sheet) { data.put(i, new ArrayList()); for (Cell cell : row) { switch (cell.getCellTypeEnum()) { case STRING: ... break; case NUMERIC: ... break; case BOOLEAN: ... break; case FORMULA: ... break; default: data.get(new Integer(i)).add(" "); } } i++; }
Apache POI tiene diferentes métodos para leer cada tipo de datos. Ampliemos el contenido de cada caso de interruptor anterior.
Cuando el valor de enumeración del tipo de celda es STRING , el contenido se leerá utilizando el método getRichStringCellValue () de la interfaz de celda :
data.get(new Integer(i)).add(cell.getRichStringCellValue().getString());
Las celdas que tienen el tipo de contenido NUMÉRICO pueden contener una fecha o un número y se leen de la siguiente manera:
if (DateUtil.isCellDateFormatted(cell)) { data.get(i).add(cell.getDateCellValue() + ""); } else { data.get(i).add(cell.getNumericCellValue() + ""); }
Para los valores BOOLEAN , tenemos el método getBooleanCellValue () :
data.get(i).add(cell.getBooleanCellValue() + "");
Y cuando el tipo de celda es FORMULA , podemos usar el método getCellFormula () :
data.get(i).add(cell.getCellFormula() + "");
3.2. Escribir en Excel
Apache POI usa las mismas interfaces presentadas en la sección anterior para escribir en un archivo de Excel y tiene un mejor soporte para el estilo que JExcel.
Creemos un método que escriba una lista de personas en una hoja titulada "Personas" . Primero, crearemos y aplicaremos estilo a una fila de encabezado que contiene las celdas "Nombre" y "Edad" :
Workbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet("Persons"); sheet.setColumnWidth(0, 6000); sheet.setColumnWidth(1, 4000); Row header = sheet.createRow(0); CellStyle headerStyle = workbook.createCellStyle(); headerStyle.setFillForegroundColor(IndexedColors.LIGHT_BLUE.getIndex()); headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); XSSFFont font = ((XSSFWorkbook) workbook).createFont(); font.setFontName("Arial"); font.setFontHeightInPoints((short) 16); font.setBold(true); headerStyle.setFont(font); Cell headerCell = header.createCell(0); headerCell.setCellValue("Name"); headerCell.setCellStyle(headerStyle); headerCell = header.createCell(1); headerCell.setCellValue("Age"); headerCell.setCellStyle(headerStyle);
A continuación, escribamos el contenido de la tabla con un estilo diferente:
CellStyle style = workbook.createCellStyle(); style.setWrapText(true); Row row = sheet.createRow(2); Cell cell = row.createCell(0); cell.setCellValue("John Smith"); cell.setCellStyle(style); cell = row.createCell(1); cell.setCellValue(20); cell.setCellStyle(style);
Finalmente, escribamos el contenido en un archivo 'temp.xlsx' en el directorio actual y cierre el libro de trabajo:
File currDir = new File("."); String path = currDir.getAbsolutePath(); String fileLocation = path.substring(0, path.length() - 1) + "temp.xlsx"; FileOutputStream outputStream = new FileOutputStream(fileLocation); workbook.write(outputStream); workbook.close();
Probemos los métodos anteriores en una prueba JUnit que escribe contenido en el archivo temp.xlsx y luego lee el mismo archivo para verificar que contiene el texto que hemos escrito:
public class ExcelTest { private ExcelPOIHelper excelPOIHelper; private static String FILE_NAME = "temp.xlsx"; private String fileLocation; @Before public void generateExcelFile() throws IOException { File currDir = new File("."); String path = currDir.getAbsolutePath(); fileLocation = path.substring(0, path.length() - 1) + FILE_NAME; excelPOIHelper = new ExcelPOIHelper(); excelPOIHelper.writeExcel(); } @Test public void whenParsingPOIExcelFile_thenCorrect() throws IOException { Map
data = excelPOIHelper.readExcel(fileLocation); assertEquals("Name", data.get(0).get(0)); assertEquals("Age", data.get(0).get(1)); assertEquals("John Smith", data.get(1).get(0)); assertEquals("20", data.get(1).get(1)); } }
4. JExcel
La biblioteca JExcel es una biblioteca liviana que tiene la ventaja de que es más fácil de usar que Apache POI, pero con la desventaja de que solo brinda soporte para procesar archivos de Excel en formato .xls (1997-2003).
Por el momento, los archivos .xlsx no son compatibles.
4.1. Leyendo desde Excel
Para trabajar con archivos de Excel, esta biblioteca proporciona una serie de clases que representan las diferentes partes de un archivo de Excel. La clase Workbook representa la colección completa de hojas. La clase Hoja representa una sola hoja y la clase Celda representa una sola celda de una hoja de cálculo.
Let's write a method that creates a workbook from a specified Excel file, gets the first sheet of the file, then traverses its content and adds each row in a HashMap:
public class JExcelHelper { public Map
readJExcel(String fileLocation) throws IOException, BiffException { Map
data = new HashMap(); Workbook workbook = Workbook.getWorkbook(new File(fileLocation)); Sheet sheet = workbook.getSheet(0); int rows = sheet.getRows(); int columns = sheet.getColumns(); for (int i = 0; i < rows; i++) { data.put(i, new ArrayList()); for (int j = 0; j < columns; j++) { data.get(i) .add(sheet.getCell(j, i) .getContents()); } } return data; } }
4.2. Writing to Excel
For writing to an Excel file, the JExcel library offers classes similar to the ones used above, that model a spreadsheet file: WritableWorkbook, WritableSheet, and WritableCell.
The WritableCell class has subclasses corresponding to the different types of content that can be written: Label, DateTime, Number, Boolean, Blank, and Formula.
This library also provides support for basic formattings, such as controlling font, color and cell width.
Let's write a method that creates a workbook called ‘temp.xls' in the current directory, then writes the same content we wrote in the Apache POI section.
First, let's create the workbook:
File currDir = new File("."); String path = currDir.getAbsolutePath(); String fileLocation = path.substring(0, path.length() - 1) + "temp.xls"; WritableWorkbook workbook = Workbook.createWorkbook(new File(fileLocation));
Next, let's create the first sheet and write the header of the excel file, containing “Name” and “Age” cells:
WritableSheet sheet = workbook.createSheet("Sheet 1", 0); WritableCellFormat headerFormat = new WritableCellFormat(); WritableFont font = new WritableFont(WritableFont.ARIAL, 16, WritableFont.BOLD); headerFormat.setFont(font); headerFormat.setBackground(Colour.LIGHT_BLUE); headerFormat.setWrap(true); Label headerLabel = new Label(0, 0, "Name", headerFormat); sheet.setColumnView(0, 60); sheet.addCell(headerLabel); headerLabel = new Label(1, 0, "Age", headerFormat); sheet.setColumnView(0, 40); sheet.addCell(headerLabel);
With a new style, let's write the content of the table we've created:
WritableCellFormat cellFormat = new WritableCellFormat(); cellFormat.setWrap(true); Label cellLabel = new Label(0, 2, "John Smith", cellFormat); sheet.addCell(cellLabel); Number cellNumber = new Number(1, 2, 20, cellFormat); sheet.addCell(cellNumber);
It's very important to remember to write to the file and close it at the end so it can be used by other processes, using the write() and close() methods of Workbook class:
workbook.write(); workbook.close();
5. Conclusión
Este tutorial ha ilustrado cómo usar la API de Apache POI y la API de JExcel para leer y escribir un archivo de Excel desde un programa Java.
El código fuente completo de este artículo se puede encontrar en el proyecto GitHub.