在 Java 中处理 Microsoft Excel 文件,需要用到第三方库,因为Java标准库并不直接支持Excel格式。常用到的第三方库包括 Apache POI, JExcel, Fastexcel, EasyExcel等,它们可以帮助开发者动态读取、写入或者修改 Excel 中的内容。
Apache POI
Apache POI 库支持.xls和.xlsx文件,并且是一个比处理 Excel 文件的其他 Java 库更复杂的库。
依赖引入
POI 需要引入两个依赖库:
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.5</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.5</version>
</dependency>
它提供了用于对Excel文件进行建模的Workbook接口,以及对 Excel 文件的元素进行建模的Sheet、Row 和Cell接口,并且支持两种Excel文件格式。
使用较新的.xlsx文件格式时,将使用到XSSFWorkbook、XSSFSheet、XSSFRow和XSSFCell类。
处理旧的.xls格式,将使用到HSSFWorkbook、HSSFSheet、HSSFRow和HSSFCell类。
读取Excel文件
先创建一个方法来打开.xlsx文件,然后从该文件的第一页读取内容。
读取单元格内容的方法根据单元格中数据的类型而变化。可以使用Cell接口的getCellType()方法确定单元格内容的类型。
首先,创建文件对象:
FileInputStream file = new FileInputStream(new File(fileLocation));
Workbook workbook = new XSSFWorkbook(file);
然后,检索文件的第一页并循环迭代每一行:
Sheet sheet = workbook.getSheetAt(0);
Map<Integer, List<String>> data = new HashMap<>();
int i = 0;
for (Row row : sheet) {
data.put(i, new ArrayList<String>());
for (Cell cell : row) {
switch (cell.getCellType()) {
case STRING: ... break;
case NUMERIC: ... break;
case BOOLEAN: ... break;
case FORMULA: ... break;
default: data.get(new Integer(i)).add(" ");
}
}
i++;
}
Apache POI 有不同的方法来读取每种类型的数据。
JExcel
JExcel 库是一个轻量级库,优点是比 Apache POI 更容易使用,但缺点是它只提供对处理.xls (1997-2003) 格式的 Excel 文件的支持,不支持.xlsx文件。
依赖引入
<dependency>
<groupId>org.jxls</groupId>
<artifactId>jxls-jexcel</artifactId>
<version>1.0.9</version>
</dependency>
JExcel 只需要引入一个依赖库,但是该依赖最新版停留在 2019 年,已经多年未更新。
读取Excel文件
为了处理 Excel 文件,该库提供了一系列代表 Excel 文件不同部分的类。Workbook类代表整个工作表集合。 Sheet类表示单个工作表,Cell类表示电子表格的单个单元格。
public Map<Integer, List<String>> readJExcel(String fileLocation)
throws IOException, BiffException {
Map<Integer, List<String>> 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<String>());
for (int j = 0; j < columns; j++) {
data.get(i)
.add(sheet.getCell(j, i)
.getContents());
}
}
return data;
}
Fastexcel
Fastexcel 是一个易于使用的库,与 Apache POI 相比,功能有限且内存占用较低。
它使用CompletableFuture的多线程支持使其成为处理功能不广泛的大型文件时的绝佳选择。目前,该库仅支持基本样式,不支持图形。
依赖引入
<dependency>
<groupId>org.dhatim</groupId>
<artifactId>fastexcel-reader</artifactId>
<version>0.17.0</version>
</dependency>
<dependency>
<groupId>org.dhatim</groupId>
<artifactId>fastexcel</artifactId>
<version>0.17.0</version>
</dependency>
Fastexcel 需要引入两个依赖。
读取Excel文件
下面简单演示Fastexcel读取 excel 文件:
public Map<Integer, List<String>> readExcel(String fileLocation) throws IOException {
Map<Integer, List<String>> data = new HashMap<>();
FileInputStream file = new FileInputStream(fileLocation);
ReadableWorkbook wb = new ReadableWorkbook(file)) {
Sheet sheet = wb.getFirstSheet();
try (Stream<Row> rows = sheet.openStream()) {
rows.forEach(r -> {
data.put(r.getRowNum(), new ArrayList<>());
for (Cell cell : r) {
data.get(r.getRowNum()).add(cell.getRawValue());
}
});
}
return data;
}
在这里,使用的是 cell.getRawValue() 它将该单元格的值作为字符串返回。或者,基于CellType ,也可以使用 Row 类中的 getCellAsBoolean(int cellIndex)、getCellAsDate(int cellIndex)、getCellAsString(int cellIndex) 或getCellAsNumber(int cellIndex)方法来读取单元格的内容。
EasyExcel
EasyExcel 是阿里巴巴开源的基于Java的Excel操作工具,它可以处理大量数据,具有高性能和低内存占用。开源地址:https://github.com/alibaba/easyexcel
依赖引入
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.3.4</version>
</dependency>
Fastexcel 需要引入一个依赖,其内部引用了 easyexcel-core 依赖。
读取Excel文件
EasyExcel 处理 Excel 数据是基于实体对象的,因此先要创建一个 Java Bean:
@Data //生成getter、setter、toString等方法
public class ReadDemoData {
private String string;
private Date date;
private Double doubleData;
}
EasyExcel 默认一行行的读取excel,所以需要创建excel一行一行的回调监听器:
public class ReadDemoDataListener implements ReadListener<ReadDemoData> {
//在读取 Excel 文件表头时调用的方法。可用于对表头进行校验或者记录日志等操作
@Override
public void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context) {
}
//在读取到一行数据时调用的方法。泛型<T>表示读取到的数据类型。可以在该方法中对读取到的数据进行处理
@Override
public void invoke(ReadDemoData readDemoData, AnalysisContext analysisContext) {
log.info("解析到一行数据:{}", readDemoData.toString());
}
}
读取文件时,传入文件路径与解析监听器:
public void simpleRead() {
String fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx";
// 这里 需要指定读用哪个class去读,然后读取第一个sheet 同步读取会自动finish
EasyExcel.read(fileName, ReadDemoData.class, new ReadDemoDataListener()).sheet().doRead();
}
当然,如果业务场景简单,也可以不创建回调监听器:
EasyExcel.read(fileName, ReadDemoData.class, new PageReadListener<DemoData>(dataList -> {
for (ReadDemoData demoData : dataList) {
log.info("读取到一条数据{}", JSON.toJSONString(demoData));
}
})).sheet().doRead();
总结
Apache POI
- 支持.xls和.xlsx格式的文件。
- 提供了丰富的API来操作Excel文件,包括读取、写入和修改。
- 包含Workbook、Sheet、Row和Cell接口以及相应的实现类。
JExcel
- 轻量级库,易于使用。
- 仅支持.xls格式(1997-2003)的Excel文件。
- 提供了Workbook、Sheet和Cell类来操作Excel文件。
Fastexcel
- 易于使用的库,内存占用较低。
- 支持多线程读取大型Excel文件。
- 目前仅支持基本样式,不支持图形。
EasyExcel
- 阿里巴巴开源的高性能Excel操作工具。
- 适合处理大量数据,具有低内存占用。
- 基于实体对象操作Excel数据,支持自定义读取监听器。
处理Excel文件是Java开发中的常见任务,尤其是在数据分析和报表生成方面。Apache POI、JExcel、Fastexcel和EasyExcel是几个流行的库,它们提供了不同程度的功能和易用性。开发者可以根据项目需求、Excel文件的格式以及对性能和内存的要求来选择合适的库。Apache POI以其全面的功能和广泛的社区支持而闻名,而JExcel则因其简单性而受到欢迎。Fastexcel和EasyExcel则提供了更现代的API和优化的性能。在选择库时,还应考虑库的维护状态和社区支持,以确保能够获得必要的帮助和更新。