这里的Java 8使用Apache POI 4.1将Excel(XLSX)文件加载到内存中,并将Java bean / POJO的列表写回到新的Excel文件中。
对我来说,一个Excel文件(至少是我正在使用的文件)实际上是POJO的列表,每一行都是POJO的不同实例,每一列都是该实例的不同字段值。观察:
在这里,我可能有一个名为POJO的POJO Car
,而上面的示例电子表格是List
:
@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
,处理该列表,然后将处理后的列表写回到输出文件,例如“ processed-cars.xlsx
”:
// 1. Load excel file into a ListInputStream inp = new FileInputStream("new-cars.xlsx"); Workbook workbook = WorkbookFactory.create(inp); Iterator iterator = workbook.getSheetAt(0).iterator(); List
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 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 | 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映射器(杰克逊,GSON等),多年来XML映射器(XStream的)和OR / M工具(休眠),它发生,我认为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 ListInputStream inp = new FileInputStream("new-cars.xlsx"); List carsInventory = WorkbookFactory.create(inp).buildList(Car.class); // 3. Process the list List processedInventory = processInventory(carsInventory); //4. Write to a new file WorkbookFactory.write(processInventory, "processed-cars.xlsx");
在POI领域是否存在类似的内容?还是我坚持我得到的东西?
到目前为止,Apache POI还没有这种功能。您可以检查一些外部库。我在下面提供一些库。
https://github.com/ozlerhakan/poiji
该库在mvnrepository中可用,链接在下面给出。该库仅提供一种从excel表格到Java pojo的绑定方式。
https://mvnrepository.com/artifact/com.github.ozlerhakan/poiji/2.2.0
如上所述,您可以执行以下操作。
public class Employee { @ExcelRow private int rowIndex; @ExcelCell(0) private long employeeId; @ExcelCell(1) private String name; @ExcelCell(2) private String surname; @ExcelCell(3) private int age; }
要将信息从excel工作表获取到java对象,您必须按照以下方式进行操作。
Listemployees = Poiji.fromExcel(new File("employees.xls"), Employee.class);
还有另一个库可以同时执行excel和java以及excel等功能。我在链接下方提供。
https://github.com/millij/poi-object-mapper
根据上述库,您可以执行以下操作。
@Sheet public class Employee { @SheetColumn("Age") private Integer age; @SheetColumn("Name") public String getName() { return name; } }
要从xlsx文件获取数据,您必须这样编写。
final File xlsxFile = new File(""); final XlsReader reader = new XlsReader(); List employees = reader.read(Employee.class, xlsxFile);
要将数据写入excel工作表,您必须这样做。
Listemployees = new ArrayList (); employees.add(new Employee("1", "foo", 12, "MALE", 1.68)); SpreadsheetWriter writer = new SpreadsheetWriter(" "); writer.addSheet(Employee.class, employees); writer.write();
您必须为您的用例评估两个库。