EasyExcel导入(仅供参考)
导包:
3.0.5 com.alibaba easyexcel ${easyexcel.version}
自定义监听器:
public class EasyExcelListener extends AnalysisEventListener { private static final Logger log = LoggerFactory.getLogger(EasyExcelListener.class); /** * 批量限制 */ private static final int BATCH_SIZE = 1000; /** * 接受一个参数,然后调用指定方法验证所有字段是否满足要求,不满足返回错误信息 * 也可以定义Consumer 该函数返回Boolean */ private final Function verify; /** * 接受一个list集合,然后执行数据保存入库等相关操作 */ private final Consumer<List> consumer; /** * 解析出来的数据零时存储的地方 */ private final List storage; /** * 统计解析条数 */ private int size = 0; /** * 通过 AnalysisContext 对象还可以获取当前 sheet,当前行等数据 */ @Override public void invoke(T data, AnalysisContext context) { log.info("解析到一条数据:{}", JSONUtil.toJsonStr(data)); //符合校验规则则添加 String message = verify.apply(data); if (StrUtil.isNotBlank(message)) { log.error("第{}行解析异常:{}", context.readRowHolder().getRowIndex() + 1, message); /*这里可以增加一些报错错误信息的操作*/ return; } storage.add(data); // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM if (storage.size() >= BATCH_SIZE) { accept(); } } /** * 所以的数据解析完了调用 */ @Override public void doAfterAllAnalysed(AnalysisContext context) { // 確保所有数据都完成入库 accept(); log.info("所有数据解析完成!"); } /** * 监听器实现这个方法就可以在读取数据的时候获取到异常信息 */ @Override public void onException(Exception exception, AnalysisContext context) { if (exception instanceof ExcelDataConvertException) { ExcelDataConvertException ex = (ExcelDataConvertException) exception; log.error("第{}行,第{}列解析异常", ex.getRowIndex() + 1, ex.getColumnIndex() + 1); /*这里可以增加一些报错错误信息的操作*/ } } /** * 入库、计数、清空等操作 */ private void accept() { consumer.accept(storage); size += storage.size(); storage.clear(); } public EasyExcelListener(Function verify, Consumer<List> consumer, List storage ) { this.verify = verify; this.consumer = consumer; this.storage = storage; }}
使用:
verify 自定义数据校验的方法
saveOrUpdate 数据保存或修改的相关操作
EasyExcelListener easyExcelListener = new EasyExcelListener(this::verify,this::saveOrUpdateBatch,new ArrayList()); EasyExcel.read(File.getInputStream(), Test.Class, excelListener).sheet().doRead();
Test类
public class Test { @ExcelProperty(value = "序号") private Integer number; @ExcelProperty(value = "编码") private String code; @ExcelProperty(value = "经度", converter = CustomDoubleConverter.class) private Double longitude; @ExcelProperty(value = "纬度", converter = CustomDoubleConverter.class) private Double latitude; //省略get set}
CustomDoubleConverter类
public class CustomDoubleConverter implements Converter { @Override public Class supportJavaTypeKey() { return Double.class; } @Override public CellDataTypeEnum supportExcelTypeKey() { return CellDataTypeEnum.NUMBER; } /** * 读的时候会调用 * * @param context * @return * @throws Exception */ @Override public Double convertToJavaData(ReadConverterContext context) throws Exception { BigDecimal numberValue = context.getReadCellData().getNumberValue(); if(numberValue == null){ String stringValue = context.getReadCellData().getStringValue(); if(StrUtil.isBlank(stringValue)){ return null; } Matcher matcher = SmartConstants.DOUBLE_PATTERN.matcher(stringValue); if(matcher.find()){ return Double.valueOf(stringValue); } return null; } return numberValue.doubleValue(); } /** * 写的时候会调用 * * @param context * @return * @throws Exception */ @Override public WriteCellData convertToExcelData(WriteConverterContext context) throws Exception { Double value = context.getValue(); return new WriteCellData(String.valueOf(value)); }}