Java 8 在这里使用 Apache POI 4.1 将 Excel (XLSX) 文件加载到内存中,并将 Java bean/POJO 列表写回新的 Excel 文件。
对我来说,一个 Excel 文件(至少是我正在使用的文件)实际上是一个 POJO 列表,每一行是 POJO 的不同实例,每一列是该实例的不同字段值。观察:
在这里,我可能有一个名为 的 POJO Car
,上面的示例电子表格是List<Car>
:
@Getter
@Setter
public class Car {
private String manufacturer;
private String model;
private String color;
private String year;
private BigDecimal price;
}
所以我有功能代码,它将一个 Excel 文件(“ new-cars.xlsx
”)读入一个List<Car>
,处理该列表,然后将处理后的列表写回一个输出文件,例如,“ processed-cars.xlsx
”:
// 1. Load excel file into a List<Car>
InputStream inp = new FileInputStream("new-cars.xlsx");
Workbook workbook = WorkbookFactory.create(inp);
Iterator<Row> iterator = workbook.getSheetAt(0).iterator();
List<Car> carsInventory = new ArrayList<>();
while (iterator.hasNext()) {
Car car = new Car();
Row currentRow = iterator.next();
// don't read the header
if (currentRow.getRowNum() == 0) {
continue;
}
Iterator<Cell> cellIterator = currentRow.iterator();
while (cellIterator.hasNext()) {
Cell currentCell = cellIterator.next();
CellAddress address = currentCell.getAddress();
if (0 == address.getColumn()) {
// 1st col is "Manufacturer"
car.setManufacturer(currentCell.getStringCellValue());
} else if (1 == address.getColumn()) {
// 2nd col is "Model"
car.setModel(currentCell.getStringCellValue());
} else if (2 == address.getColumn()) {
// 3rd col is "Color"
car.setColor(currentCell.getStringCellValue());
} else if (3 == address.getColumn()) {
// 4th col is "Year"
car.setYear(currentCell.getStringCellValue());
} else if (4 == address.getColumn()) {
// 5th col is "Price"
car.setPrice(BigDecimal.valueOf(currentCell.getNumericCellValue()));
}
}
carsInventory.add(car);
}
// 2. Process the list of Cars; doesn't matter what this does
List<Car> processedInventory = processInventory(carsInventory);
// 3. Output to "processed-cars.xlsx"
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet("Processed Inventory");
int rowNum = 0;
// create headers
Row headerRow = sheet.createRow(rowNum);
headerRow.createCell(0).setCellValue("Manufacturer");
headerRow.createCell(1).setCellValue("Model");
headerRow.createCell(2).setCellValue("Color");
headerRow.createCell(3).setCellValue("Year");
headerRow.createCell(4).setCellValue("Price");
rowNum++;
// rip through the cars list and convert each one into a subsequent row
for (Car processedCar : processedInventory) {
Row nextRow = sheet.createRow(rowNum);
nextRow.createCell(0).setCellValue(processedCar.getManufacturer());
nextRow.createCell(1).setCellValue(processedCar.getModel());
nextRow.createCell(2).setCellValue(processedCar.getColor());
nextRow.createCell(3).setCellValue(processedCar.getYear());
nextRow.createCell(4).setCellValue(processedCar.getPrice().doubleValue());
rowNum++;
}
FileOutputStream fos = new FileOutputStream("processed-cars.xlsx");
workbook.write(fos);
workbook.close();
虽然这可行,但对我来说它看起来真的很丑/讨厌。多年来我一直使用 JSON 映射器(Jackson、GSON 等)、XML 映射器(XStream)和 OR/M 工具(Hibernate),我突然想到 POI 的 API(或其他一些库)可能会提供“映射器” -esque ”解决方案,它允许我以最少的代码和最大的优雅将 Excel 数据映射/绑定到 POJO 列表。但是,我在任何地方都找不到任何此类功能。也许这是因为它不存在,或者我只是没有搜索正确的关键字。
理想情况下,大致如下:
// Annotate the fields with something that POI (or whatever tool) can pick up
@Getter
@Setter
public class Car {
@ExcelColumn(name = "Manufacturer", col = 0)
private String manufacturer;
@ExcelColumn(name = "Model", col = 1)
private String model;
@ExcelColumn(name = "Color", col = 2)
private String color;
@ExcelColumn(name = "Year", col = 3)
private String year;
@ExcelColumn(name = "Price", col = 4)
private BigDecimal price;
}
// 2. Now load the Excel into a List<Car>
InputStream inp = new FileInputStream("new-cars.xlsx");
List<Car> carsInventory = WorkbookFactory.create(inp).buildList(Car.class);
// 3. Process the list
List<Car> processedInventory = processInventory(carsInventory);
//4. Write to a new file
WorkbookFactory.write(processInventory, "processed-cars.xlsx");
POI-land中是否存在类似的东西?还是我坚持我所得到的?