|
@@ -0,0 +1,116 @@
|
|
|
+package com.ruoyi.common.utils.poi;
|
|
|
+
|
|
|
+import cn.hutool.core.collection.CollUtil;
|
|
|
+import cn.hutool.core.util.StrUtil;
|
|
|
+import com.alibaba.excel.context.AnalysisContext;
|
|
|
+import com.alibaba.excel.event.AnalysisEventListener;
|
|
|
+import com.alibaba.excel.exception.ExcelAnalysisException;
|
|
|
+import com.alibaba.excel.exception.ExcelDataConvertException;
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
+import com.ruoyi.common.utils.ValidatorUtils;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+import javax.validation.*;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.Set;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 公共excel监听类
|
|
|
+ * @param <T>
|
|
|
+ */
|
|
|
+public class ExcelListener<T> extends AnalysisEventListener<T> {
|
|
|
+
|
|
|
+ private static final Logger LOGGER = LoggerFactory.getLogger(ExcelListener.class);
|
|
|
+ /** 数据对象list */
|
|
|
+ private final List<T> list = new ArrayList<>();
|
|
|
+ /** 错误信息列表 */
|
|
|
+ private final List<String> errorList = new ArrayList<>();
|
|
|
+ /** 遇到异常是否跳出导入,默认为是 */
|
|
|
+ private Boolean skipException = Boolean.TRUE;
|
|
|
+ /** 是否Validator检验,默认为是 */
|
|
|
+ private Boolean isValidate = Boolean.TRUE;
|
|
|
+ /**
|
|
|
+ * 导入回执
|
|
|
+ */
|
|
|
+ private final ExcelResult<T> excelResult = new ExcelResult<>();
|
|
|
+
|
|
|
+ public ExcelListener() {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ public ExcelListener(boolean isValidate, boolean skipException) {
|
|
|
+ this.isValidate = isValidate;
|
|
|
+ this.skipException = skipException;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理异常
|
|
|
+ *
|
|
|
+ * @param exception ExcelDataConvertException
|
|
|
+ * @param context excel上下文
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public void onException(Exception exception, AnalysisContext context) throws Exception {
|
|
|
+ // 如果是某一个单元格的转换异常 能获取到具体行号
|
|
|
+ // 如果要获取头的信息 配合doAfterAllAnalysedHeadMap使用
|
|
|
+ String errMsg = null;
|
|
|
+ if (exception instanceof ExcelDataConvertException) {
|
|
|
+ ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException)exception;
|
|
|
+ errMsg = StrUtil.format("第{}行-第{}列解析异常<br/>", excelDataConvertException.getRowIndex() + 1,
|
|
|
+ excelDataConvertException.getColumnIndex() + 1);
|
|
|
+ LOGGER.error(errMsg);
|
|
|
+ }
|
|
|
+ if (exception instanceof ConstraintViolationException) {
|
|
|
+ ConstraintViolationException constraintViolationException = (ConstraintViolationException)exception;
|
|
|
+ Set<ConstraintViolation<?>> constraintViolations = constraintViolationException.getConstraintViolations();
|
|
|
+ String constraintViolationsMsg= CollUtil.join(constraintViolations
|
|
|
+ .stream()
|
|
|
+ .map(ConstraintViolation::getMessage)
|
|
|
+ .collect(Collectors.toList()),
|
|
|
+ ",");
|
|
|
+ errMsg = StrUtil.format("第{}行数据校验异常:{}", context.readRowHolder().getRowIndex() + 1,
|
|
|
+ constraintViolationsMsg);
|
|
|
+ LOGGER.error(errMsg);
|
|
|
+ }
|
|
|
+ errorList.add(errMsg);
|
|
|
+ if (!skipException){
|
|
|
+ throw new ExcelAnalysisException(errMsg);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
|
|
|
+ LOGGER.debug("解析到一条头数据:{}", JSON.toJSONString(headMap));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void invoke(T data, AnalysisContext context) {
|
|
|
+ if (isValidate) {
|
|
|
+ ValidatorUtils.validate(data);
|
|
|
+ }
|
|
|
+ list.add(data);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void doAfterAllAnalysed(AnalysisContext context) {
|
|
|
+ excelResult.setList(list);
|
|
|
+ excelResult.setErrorList(errorList);
|
|
|
+ LOGGER.debug("所有数据解析完成!");
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取导入数据
|
|
|
+ * @return 导入数据
|
|
|
+ */
|
|
|
+ public List<T> getList() {
|
|
|
+ return list;
|
|
|
+ }
|
|
|
+
|
|
|
+ public ExcelResult<T> getExcelResult() {
|
|
|
+ return excelResult;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|