1. 简介
数据映射是软件开发中的核心技能。Excel作为广泛使用的数据管理工具,掌握Java对象与Excel数据的转换对开发者至关重要。
本教程将探讨如何将Excel数据转换为Java对象列表。
Maven仓库中提供了多个处理Excel文件的Java库,其中Apache POI最为常用。但**我们将使用四个库实现转换:Apache POI、Poiji、FastExcel和JExcelApi (Jxl)**。
2. 模型准备
首先需要创建对象蓝图——FoodInfo
类:
public class FoodInfo {
private String category;
private String name;
private String measure;
private double calories;
// 标准构造方法、toString、getter和setter
}
3. Apache POI
Apache POI (Poor Obfuscation Implementation) 是处理Microsoft文档的Java API。它是一套纯Java库,用于读写Microsoft Office文件(如Word、Outlook、Excel等)。
3.1. Maven依赖
将Maven依赖添加到pom.xml
:
<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>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>4.1.2</version>
</dependency>
3.2. 转换Excel数据为对象列表
通过Workbook
接口可以访问Excel文件的sheet和单元格。该接口有两个实现类:HSSFWorkbook
处理.xls
文件,XSSFWorkbook
处理.xlsx
文件。
以下代码使用Apache POI将.xlsx
文件转换为FoodInfo
对象列表:
public static List<FoodInfo> excelDataToListOfObjets_withApachePOI(String fileLocation)
throws IOException {
FileInputStream file = new FileInputStream(new File(fileLocation));
Workbook workbook = new XSSFWorkbook(file);
Sheet sheet = workbook.getSheetAt(0);
List<FoodInfo> foodData = new ArrayList<FoodInfo>();
DataFormatter dataFormatter = new DataFormatter();
for (int n = 1; n < sheet.getPhysicalNumberOfRows(); n++) {
Row row = sheet.getRow(n);
FoodInfo foodInfo = new FoodInfo();
int i = row.getFirstCellNum();
foodInfo.setCategory(dataFormatter.formatCellValue(row.getCell(i)));
foodInfo.setName(dataFormatter.formatCellValue(row.getCell(++i)));
foodInfo.setMeasure(dataFormatter.formatCellValue(row.getCell(++i)));
foodInfo.setCalories(row.getCell(++i).getNumericCellValue());
foodData.add(foodInfo);
}
return foodData;
}
使用getPhysicalNumberOfRows()
方法获取非空行数。循环时跳过标题行(i = 1
)。
根据字段类型,使用dataFormatter
或getNumericValue()
方法转换单元格值。
通过单元测试验证代码(使用food_info.xlsx
文件):
Apache POI支持新旧Excel格式(.xls
和.xlsx
)。
4. Poiji
Poiji是线程安全的Java库,提供Excel到Java类的单向映射API。它基于Apache POI构建,但使用更简单,可直接将Excel行转换为Java对象。
4.1. 设置Maven依赖
添加Poiji依赖到pom.xml
:
<dependency>
<groupId>com.github.ozlerhakan</groupId>
<artifactId>poiji</artifactId>
<version>4.1.1</version>
</dependency>
4.2. 使用注解配置类
Poiji通过@ExcelCellName(String cellName)
或@ExcelCell(int cellIndex)
注解简化数据映射。
为FoodInfo
类添加注解:
public class FoodInfo {
@ExcelCellName("Category")
private String category;
@ExcelCellName("Name")
private String name;
@ExcelCellName("Measure")
private String measure;
@ExcelCellName("Calories")
private double calories;
// 标准构造方法、getter和setter
}
API支持多sheet工作簿。使用@ExcelSheet(String sheetName)
注解指定目标sheet,其他sheet将被忽略。
未使用注解时,仅处理第一个sheet。
若需跳过特定行,添加@ExcelRow
注解的private int rowIndex
属性。
4.3. 转换Excel数据为对象列表
Poiji默认忽略Excel标题行。
以下代码将Excel文件转换为FoodInfo
列表:
public class ExcelDataToListOfObjectsPOIJI {
public static List<FoodInfo> excelDataToListOfObjets_withPOIJI(String fileLocation){
return Poiji.fromExcel(new File(fileLocation), FoodInfo.class);
}
}
程序将首个sheet转换为FoodInfo
对象列表,每行对应一个对象,单元格值映射为属性。列表大小等于非标题行数。
处理加密Excel时,通过PoijiOptionsBuilder
设置密码:
PoijiOptions options = PoijiOptionsBuilder.settings()
.password("excel123").build();
List<FoodInfo> foodData = Poiji.fromExcel(new File(fileLocation), FoodInfo.class, options);
单元测试验证:
@Test
public void whenParsingExcelFileWithPOIJI_thenConvertsToList() throws IOException {
List<FoodInfo> foodInfoList =
ExcelDataToListOfObjectsPOIJI
.excelDataToListOfObjets_withPOIJI("src\\main\\resources/food_info.xlsx");
assertEquals("Beverages", foodInfoList.get(0).getCategory());
assertEquals("Dairy", foodInfoList.get(3).getCategory());
}
5. FastExcel
FastExcel是高效低内存的库,专为Java中创建和读取基础Excel工作簿设计。仅支持.xlsx
格式,功能少于Apache POI。
仅读取单元格内容,不支持图表、样式等格式。
5.1. 设置Maven依赖
添加FastExcel和FastExcel Reader依赖:
5.2. 转换Excel数据为对象列表
处理大文件时,FastExcel是理想选择(尽管功能有限)。通过ReadableWorkbook
类访问整个工作簿。
可按名称或索引获取sheet。
以下代码将Excel数据转换为FoodInfo
列表:
public static List<FoodInfo> excelDataToListOfObjets_withFastExcel(String fileLocation)
throws IOException, NumberFormatException {
List<FoodInfo> foodData = new ArrayList<FoodInfo>();
try (FileInputStream file = new FileInputStream(fileLocation);
ReadableWorkbook wb = new ReadableWorkbook(file)) {
Sheet sheet = wb.getFirstSheet();
for (Row row: sheet.read()) {
if (row.getRowNum() == 1) {
continue;
}
FoodInfo food = new FoodInfo();
food.setCategory(row.getCellText(0));
food.setName(row.getCellText(1));
food.setMeasure(row.getCellText(2));
food.setCalories(Double.parseDouble(row.getCellText(3)));
foodData.add(food);
}
}
return foodData;
}
API读取所有行(包括标题行),需跳过第一行(非零基索引)。
访问单元格有两种方式:
- 创建
Cell
对象:Cell cell = row.getCell(int cellIndex)
或row.getCell(String cellAddress)
- 直接获取数据:
row.getCellText()
提取内容后需转换为food
对象的字段类型。
单元测试验证:
@Test
public void whenParsingExcelFileWithFastExcel_thenConvertsToList() throws IOException {
List<FoodInfo> foodInfoList = ExcelDataToListOfObjectsFastExcel
.excelDataToListOfObjets_withFastExcel("src\\main\\resources/food_info.xlsx");
assertEquals("Beverages", foodInfoList.get(0).getCategory());
assertEquals("Dairy", foodInfoList.get(3).getCategory());
}
6. JExcelApi (Jxl)
JExcelApi (Jxl) 是轻量级Java库,用于读写修改Excel电子表格。
6.1. 设置Maven依赖
添加JExcelApi依赖到pom.xml
:
<dependency>
<groupId>net.sourceforge.jexcelapi</groupId>
<artifactId>jxl</artifactId>
<version>2.6.12</version>
</dependency>
6.2. 转换Excel数据为对象列表
仅支持旧版Excel格式(.xls
)。Workbook
类用于访问sheet列表。
以下代码将.xls
文件转换为FoodInfo
列表:
public static List<FoodInfo> excelDataToListOfObjets_withJxl(String fileLocation)
throws IOException, BiffException {
List<FoodInfo> foodData = new ArrayList<FoodInfo>();
Workbook workbook = Workbook.getWorkbook(new File(fileLocation));
Sheet sheet = workbook.getSheet(0);
int rows = sheet.getRows();
for (int i = 1; i < rows; i++) {
FoodInfo foodInfo = new FoodInfo();
foodInfo.setCategory(sheet.getCell(0, i).getContents());
foodInfo.setName(sheet.getCell(1, i).getContents());
foodInfo.setMeasure(sheet.getCell(2, i).getContents());
foodInfo.setCalories(Double.parseDouble(sheet.getCell(3, i).getContents()));
foodData.add(foodInfo);
}
return foodData;
}
库不忽略标题行,需从i = 1
开始循环。sheet对象是零基索引的行列表。
JExcel的单元格访问与FastExcel类似,都使用getCell()
方法。但JExcel直接从Sheet
对象调用,且方法接受colNum
和rowNum
两个整数参数:sheet.getCell(colNum, rowNum)
。
单元测试验证:
@Test
public void whenParsingExcelFileWithJxl_thenConvertsToList()
throws IOException, BiffException {
List<FoodInfo> foodInfoList = ExcelDataToListOfObjectsJxl
.excelDataToListOfObjets_withJxl("src\\main\\resources/food_info.xls");
assertEquals("Beverages", foodInfoList.get(0).getCategory());
assertEquals("Dairy", foodInfoList.get(3).getCategory());
}
7. 总结
本文探讨了使用Apache POI、Poiji、FastExcel和JExcelApi将Excel数据转换为Java对象的方法。选择库需根据具体需求权衡利弊:
✅ Poiji:最简单直接的转换方案
⚠️ FastExcel/Jxl:高性能双向映射,但功能有限
❌ Apache POI:功能最全(支持样式/图表),但较复杂
完整源代码见GitHub仓库。