项目中excel 导入导出框架是用的poi(新项目推荐使用easyexcel),excel导出比较简单,比较麻烦的是excel导入,因为几乎每个字段都必须校验是否合法,所有字段的校验都写在一起的话,代码会很乱,特别是字段很多,业务校验规则有比较复杂的时候,很容易出bug,后续也很难维护。excel导入,项目中还有一个需求是,把excel中所有校验不通过的错误信息一起提示出来,而不是检查到一个错误就终止读取,这样可以提高用户的效率。所以封装了一个校验和业务分开的excel导入工具。
大致思路是,利用反射将读取到值赋给对应的字段,其中每个字段都可以单独设置一个校验接口,校验通过则赋值,不通过则添加错误信息。
读取excel值,通过反射赋给对应的字段
/** * @param sheet excel表格页 * @param columnConfigList 实体类字段配置列表 * @param tClass 实体类类型 * @param <T> * @return */ public <T> ExcelImportData<T> read(Sheet sheet, List<ColumnConfig> columnConfigList, Class<T> tClass) { ExcelImportData<T> excelImportData = new ExcelImportData<T>(); int count = getRealRowCount(sheet); // 真实的行数 if (count < 2) { excelImportData.addErrorData("excel表格中没有数据"); return excelImportData; } for (int i = 1; i < count; i++) { Row row = sheet.getRow(i); // excel中一行数据 try { T data = tClass.newInstance(); // 对应excel中一行数据 // 根据每个字段的配置,读取excel,然后通过反射赋给对应的字段,若不通过则添加错误信息 for (ColumnConfig columnConfig : columnConfigList) { Field field = tClass.getDeclaredField(columnConfig.getPropertyName()); // 其中一个字段 field.setAccessible(true); int columnIndex = columnConfig.getExcelColumnIndex(); CellInfo cellInfo = new CellInfo(i, columnIndex, field.getType(), sheet.getRow(0).getCell(columnIndex).getStringCellValue()); ExcelUnitData excelUnitData = getExcelUnitData(row.getCell(columnIndex), cellInfo, columnConfig); if (excelUnitData.getUnitFlag() == ExcelUnitData.SUCCESS) { if (excelUnitData.getData() != null) { field.set(data, excelUnitData.getData()); // 给这个字段赋值 } }else { excelImportData.addErrorData(excelUnitData.getErrorInfo()); } } if (excelImportData.getFlag() == ExcelImportData.SUCCESS) { excelImportData.addData(data); } } catch (IllegalAccessException e) { logger.error("read: " + e.getMessage()); } catch (NoSuchFieldException e) { logger.error("read: " + e.getMessage()); } catch (InstantiationException e) { logger.error("read: " + e.getMessage()); } } return excelImportData; }校验接口,每个字段单独设置
// 校验接口 public interface IExcelValidator<E> { // 校验是否通过 ExcelUnitData<E> isPass(E cellValue, Cell cell, CellInfo cellInfo); }具体代码分析,后续有时间再补。
引入依赖
<dependency> <groupId>com.github.chocolatecw</groupId> <artifactId>excelvalidate</artifactId> <version>1.0.0</version> </dependency>使用示例
CommonExcelReader commonExcelReader = new CommonExcelReader(); File excelFile = new File("excel文件路径"); // 实体类字段配置,与excel表格的列一一对应,可使用ConfigBuilder类生成,数组的顺序即表格列的顺序 List<ColumnConfig> columnConfigList = new ColumnConfig.ConfigBuilder(new String[]{"testPropertyOne", "testPropertyTwo", "testPropertyThird", "testPropertyFourth"}) .setValidator("testPropertyOne", CommonValidator.mobileValidator) // 设置字段的校验器,key为字段名 .build(); ExcelImportData<TestExcelEntity> excelImportData = commonExcelReader.read(excelFile, columnConfigList, TestExcelEntity.class); if (excelImportData.getFlag() == ExcelImportData.SUCCESS) { // 导入成功,数据获取list List<TestExcelEntity> dataList = excelImportData.getExcelDataList(); System.out.println("导入成功!"); }else { // 导入失败,getErrorConnectStr 获取全部错误信息 System.out.println("导入失败:" + excelImportData.getErrorConnectStr(",")); }https://github.com/chocolatecw/excelvalidate
好用记得给star!