Java 8在这里使用Apache POI 4.1将Excel(XLSX)文件加载到内存中,并将Java bean/POJO列表写回到新的Excel文件中。
对我来说,Excel文件(至少是我正在使用的文件)实际上是一个POJO列表,每行是POJO的一个不同示例,每列是该示例的一个不同字段值。
这里我可能有一个名为Car
的POJO,上面的电子表格示例是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();
虽然这可以工作,但在我看来,它看起来真的很难看/讨厌。(Jackson、GSON等)、XMLMap器(XStream)和OR/M工具(休眠)多年,我突然想到POI的API(或其他一些库)可能会提供一个“mapper-esque”解决方案,允许我以最少的代码和最大的优雅程度将Excel数据Map到POJO列表或从POJO列表绑定Excel数据。我在任何地方都找不到这样的功能。也许这是因为它不存在,或者也许我只是没有搜索正确的关键字。
理想情况下,应遵循以下原则:
// 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");
"在警察的地盘上有这样的东西吗?还是我被我得到的东西卡住了?"
5条答案
按热度按时间k4emjkb11#
到目前为止,Apache POI还没有这样的功能。有一些外部库可以查看。我提供了以下几个库。
https://github.com/ozlerhakan/poiji
该库在mvnrepository中可用,下面给出了链接。该库仅提供单向绑定,如从excel工作表到java pojo。
https://mvnrepository.com/artifact/com.github.ozlerhakan/poiji/2.2.0
按照上面的,你可以这样做。
要将excel表中的信息转换为java对象,必须按以下方式进行。
还有另一个库,它可以做两件事,如excel到java和java到excel。我提供下面的链接。
https://github.com/millij/poi-object-mapper
根据上面的库,您可以执行类似这样的操作。
要从xlsx文件中获取数据,必须这样写。
要将数据写入excel工作表,必须这样做。
您必须针对您的用例评估这两个库。
vc6uscn92#
我会考虑编写我自己的
apache poi
to/fromPOJO
mapper包,而不是简单地搜索任何可用的包。这样做可以更灵活地扩展功能,因为这样你就知道它是如何工作的,而不需要深入研究其他人写的代码,这些代码被分成很多类和方法。试图理解这样的代码真的很困难。更不用说知道在哪里放置自己想要的扩展了。首先,这里有一个包
PoiPOJO
,它到目前为止只包含两个类。PoiPOJOUtils
提供了两个静态方法。一个是sheetToPOJO
,一个是pojoToSheet
。ExcelColumn
是一个Annotation
接口,可以在POJO
类中使用。PoiPOJOUtils.java
:和
ExcelColumn.java
:这可以用来然后有...
Car.java
:和
TestPoiPOJO.java
:ExcelCars.xlsx
必须在第一个工作表中包含示例汽车表。列的顺序是灵活的。只有标题必须与类Car
中的ExcelColumn
注解的名称相对应。hgncfbus3#
我建议使用 oCell 库将ExcelMap到POJO以及将POJOMap到Excel。
https://github.com/rushuat/ocell
另外,这个库支持几种类型的注解(即oCell、Jackson、JAXB、JPA)和其他Map特性(例如数据转换、单元格格式化、字段忽略等)。
汽车POJO:
读取/写入Excel:
场转换器:
@字段格式来源:
Basic Excel currency format with Apache POI
3bygqnnd4#
与@Axel Ritcher的答案稍有不同,使用并行流,并针对具有Set Field(没有公式求值)的Java对象:
请注意,此示例假设pojo中有String、Double和Set,并且与Set对应的excel列具有逗号分隔的值。
例如:
和Excel工作表:
r9f1avp55#
我想找到一个简单的方法来解析一个xls/xlsx文件到一个pojo列表。经过一些搜索,我没有找到任何方便的东西,更喜欢快速开发它。现在我可以通过简单的调用来获得pojo:
如果有兴趣的话就看看吧:
https://github.com/ZPavel/excelToPojo