|
@@ -0,0 +1,227 @@
|
|
|
|
+package com.qmth.distributed.print.business.util.excel;
|
|
|
|
+
|
|
|
|
+import com.alibaba.excel.annotation.ExcelProperty;
|
|
|
|
+import com.alibaba.excel.context.AnalysisContext;
|
|
|
|
+import com.alibaba.excel.event.AnalysisEventListener;
|
|
|
|
+import com.alibaba.excel.metadata.CellExtra;
|
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
|
+import org.hibernate.validator.constraints.Length;
|
|
|
|
+import org.hibernate.validator.constraints.Range;
|
|
|
|
+import org.slf4j.Logger;
|
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
|
+import org.springframework.util.LinkedMultiValueMap;
|
|
|
|
+
|
|
|
|
+import javax.validation.constraints.*;
|
|
|
|
+import java.lang.annotation.Annotation;
|
|
|
|
+import java.lang.reflect.Field;
|
|
|
|
+import java.math.BigDecimal;
|
|
|
|
+import java.util.*;
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * @Description: easyexcel监听
|
|
|
|
+ * @Param:
|
|
|
|
+ * @return:
|
|
|
|
+ * @Author: wangliang
|
|
|
|
+ * @Date: 2022/5/14
|
|
|
|
+ */
|
|
|
|
+public abstract class BasicExcelListener<T> extends AnalysisEventListener<T> {
|
|
|
|
+ private final static Logger log = LoggerFactory.getLogger(BasicExcelListener.class);
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 批处理阈值2000
|
|
|
|
+ */
|
|
|
|
+ private static int BATCH_COUNT = 2000;
|
|
|
|
+ public static final String SUCCESS = "success";
|
|
|
|
+ public static final String ERROR = "error";
|
|
|
|
+ private LinkedMultiValueMap<String, T> list;
|
|
|
|
+ private StringJoiner errorDataSj = new StringJoiner("\n");
|
|
|
|
+ private Exception exception = null;
|
|
|
|
+
|
|
|
|
+ public BasicExcelListener() {
|
|
|
|
+ this.list = new LinkedMultiValueMap<>(BATCH_COUNT);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public BasicExcelListener(int batchCount) {
|
|
|
|
+ BATCH_COUNT = batchCount;
|
|
|
|
+ this.list = new LinkedMultiValueMap<>(BATCH_COUNT);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public abstract void handle(LinkedMultiValueMap<String, T> dataList, StringJoiner errorData, Exception exception);
|
|
|
|
+
|
|
|
|
+// public abstract void errorData(List<String> errorDataList);
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void invoke(T o, AnalysisContext analysisContext) {
|
|
|
|
+// if (validData(o, analysisContext) || (analysisContext.readRowHolder().getRowIndex() == 2001 || analysisContext.readRowHolder().getRowIndex() == 7001)) {
|
|
|
|
+ if (validData(o, analysisContext)) {
|
|
|
|
+ list.add(ERROR, o);
|
|
|
|
+ BasicExcelRow basicExcelRow = (BasicExcelRow) o;
|
|
|
|
+ errorDataSj.add("第" + basicExcelRow.getSheet() + "个sheet第" + (basicExcelRow.getRow() - 1) + "行" + basicExcelRow.getErrorMessage().toString());
|
|
|
|
+ } else {
|
|
|
|
+ list.add(SUCCESS, o);
|
|
|
|
+ }
|
|
|
|
+ if (list.size() >= BATCH_COUNT) {
|
|
|
|
+ handle(list, errorDataSj, this.exception);
|
|
|
|
+ list.clear();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+// @Override
|
|
|
|
+// public void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context) {
|
|
|
|
+// log.info("表头:{}", JSONObject.toJSONString(headMap));
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
|
|
|
|
+ log.info("表头:{}", JSONObject.toJSONString(headMap));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void doAfterAllAnalysed(AnalysisContext analysisContext) {
|
|
|
|
+ log.info("所有数据解析完成!");
|
|
|
|
+ handle(list, errorDataSj, this.exception);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void onException(Exception exception, AnalysisContext context) {
|
|
|
|
+ log.info("onException is come in!");
|
|
|
|
+// XlsxReadSheetHolder xlsxReadSheetHolder = (XlsxReadSheetHolder) context.currentReadHolder();
|
|
|
|
+// errorDataSj.add("第" + (xlsxReadSheetHolder.getSheetNo() + 1) + "个sheet第" + (xlsxReadSheetHolder.getRowIndex() - 1) + "行" + exception.getMessage().toString());
|
|
|
|
+ this.exception = exception;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void extra(CellExtra extra, AnalysisContext context) {
|
|
|
|
+ log.info("extra is come in!");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void extendBasicExcelField(T o, AnalysisContext analysisContext, List<String> errorMessage) {
|
|
|
|
+ try {
|
|
|
|
+ Field rowField = o.getClass().getField("row");
|
|
|
|
+ rowField.setAccessible(true);
|
|
|
|
+ rowField.set(o, analysisContext.readRowHolder().getRowIndex());
|
|
|
|
+
|
|
|
|
+ Field sheetField = o.getClass().getField("sheet");
|
|
|
|
+ sheetField.setAccessible(true);
|
|
|
|
+ sheetField.set(o, analysisContext.readSheetHolder().getSheetNo() + 1);
|
|
|
|
+
|
|
|
|
+ Field errorMessageMapField = o.getClass().getField("errorMessage");
|
|
|
|
+ errorMessageMapField.setAccessible(true);
|
|
|
|
+ errorMessageMapField.set(o, errorMessage);
|
|
|
|
+ } catch (NoSuchFieldException | IllegalAccessException e) {
|
|
|
|
+ log.error("请求出错:", e);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private boolean validData(T o, AnalysisContext analysisContext) {
|
|
|
|
+ List<String> errorMessage = new ArrayList<>();
|
|
|
|
+ Field[] fields = o.getClass().getDeclaredFields();
|
|
|
|
+ Object object = null;
|
|
|
|
+ for (int i = 0; i < fields.length; i++) {
|
|
|
|
+ fields[i].setAccessible(true);
|
|
|
|
+ try {
|
|
|
|
+ object = fields[i].get(o);
|
|
|
|
+ } catch (IllegalAccessException e) {
|
|
|
|
+ e.printStackTrace();
|
|
|
|
+ }
|
|
|
|
+ ExcelProperty excelProperty = fields[i].getDeclaredAnnotation(ExcelProperty.class);
|
|
|
|
+ if (Objects.isNull(excelProperty)) {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ Annotation[] annotations = fields[i].getDeclaredAnnotations();
|
|
|
|
+ NotBlank notBlank = null;
|
|
|
|
+ Length length = null;
|
|
|
|
+ Min min = null;
|
|
|
|
+ Max max = null;
|
|
|
|
+ DecimalMin decimalMin = null;
|
|
|
|
+ DecimalMax decimalMax = null;
|
|
|
|
+ NotNull notNull = null;
|
|
|
|
+ Null isnull = null;
|
|
|
|
+ NotEmpty notEmpty = null;
|
|
|
|
+ Size size = null;
|
|
|
|
+ Range range = null;
|
|
|
|
+ AssertTrue assertTrue = null;
|
|
|
|
+ AssertFalse assertFalse = null;
|
|
|
|
+ for (Annotation annotation : annotations) {
|
|
|
|
+ if (annotation instanceof NotBlank) {
|
|
|
|
+ notBlank = (NotBlank) annotation;
|
|
|
|
+ if (Objects.isNull(object) || Objects.equals(object, " ")) {
|
|
|
|
+ errorMessage.add("列名[" + excelProperty.value()[0] + "]:" + notBlank.message());
|
|
|
|
+ }
|
|
|
|
+ } else if (annotation instanceof Length) {
|
|
|
|
+ length = (Length) annotation;
|
|
|
|
+ if (Objects.nonNull(object) && (object.toString().length() < length.min() || object.toString().length() > length.max())) {
|
|
|
|
+ errorMessage.add("列名[" + excelProperty.value()[0] + "]:" + length.message());
|
|
|
|
+ }
|
|
|
|
+ } else if (annotation instanceof Min) {
|
|
|
|
+ min = (Min) annotation;
|
|
|
|
+ if (Objects.nonNull(object) && Long.parseLong(object.toString()) < min.value()) {
|
|
|
|
+ errorMessage.add("列名[" + excelProperty.value()[0] + "]:" + min.message());
|
|
|
|
+ }
|
|
|
|
+ } else if (annotation instanceof Max) {
|
|
|
|
+ max = (Max) annotation;
|
|
|
|
+ if (Objects.nonNull(object) && Long.parseLong(object.toString()) > max.value()) {
|
|
|
|
+ errorMessage.add("列名[" + excelProperty.value()[0] + "]:" + max.message());
|
|
|
|
+ }
|
|
|
|
+ } else if (annotation instanceof DecimalMin) {
|
|
|
|
+ decimalMin = (DecimalMin) annotation;
|
|
|
|
+ if (Objects.nonNull(object) && new BigDecimal(object.toString()).compareTo(new BigDecimal(decimalMin.value())) == -1) {
|
|
|
|
+ errorMessage.add("列名[" + excelProperty.value()[0] + "]:" + decimalMin.message());
|
|
|
|
+ }
|
|
|
|
+ } else if (annotation instanceof DecimalMax) {
|
|
|
|
+ decimalMax = (DecimalMax) annotation;
|
|
|
|
+ if (Objects.nonNull(object) && new BigDecimal(object.toString()).compareTo(new BigDecimal(decimalMax.value())) == 1) {
|
|
|
|
+ errorMessage.add("列名[" + excelProperty.value()[0] + "]:" + decimalMax.message());
|
|
|
|
+ }
|
|
|
|
+ } else if (annotation instanceof NotNull) {
|
|
|
|
+ notNull = (NotNull) annotation;
|
|
|
|
+ if (Objects.isNull(object)) {
|
|
|
|
+ errorMessage.add("列名[" + excelProperty.value()[0] + "]:" + notNull.message());
|
|
|
|
+ }
|
|
|
|
+ } else if (annotation instanceof Null) {
|
|
|
|
+ isnull = (Null) annotation;
|
|
|
|
+ if (Objects.nonNull(object)) {
|
|
|
|
+ errorMessage.add("列名[" + excelProperty.value()[0] + "]:" + isnull.message());
|
|
|
|
+ }
|
|
|
|
+ } else if (annotation instanceof NotEmpty) {
|
|
|
|
+ notEmpty = (NotEmpty) annotation;
|
|
|
|
+ if (Objects.isNull(object)) {
|
|
|
|
+ errorMessage.add("列名[" + excelProperty.value()[0] + "]:" + notEmpty.message());
|
|
|
|
+ }
|
|
|
|
+ } else if (annotation instanceof Size) {
|
|
|
|
+ size = (Size) annotation;
|
|
|
|
+ if (Objects.nonNull(object) && (object.toString().length() < size.min() || object.toString().length() > size.max())) {
|
|
|
|
+ errorMessage.add("列名[" + excelProperty.value()[0] + "]:" + size.message());
|
|
|
|
+ }
|
|
|
|
+ } else if (annotation instanceof Range) {
|
|
|
|
+ range = (Range) annotation;
|
|
|
|
+ if (Objects.nonNull(object) && (Long.parseLong(object.toString()) < range.min() || Long.parseLong(object.toString()) > range.max())) {
|
|
|
|
+ errorMessage.add("列名[" + excelProperty.value()[0] + "]:" + range.message());
|
|
|
|
+ }
|
|
|
|
+ } else if (annotation instanceof AssertTrue) {
|
|
|
|
+ assertTrue = (AssertTrue) annotation;
|
|
|
|
+ if (Objects.nonNull(object) && Boolean.valueOf(object.toString())) {
|
|
|
|
+ errorMessage.add("列名[" + excelProperty.value()[0] + "]:" + assertTrue.message());
|
|
|
|
+ }
|
|
|
|
+ } else if (annotation instanceof AssertFalse) {
|
|
|
|
+ assertFalse = (AssertFalse) annotation;
|
|
|
|
+ if (Objects.nonNull(object) && !Boolean.valueOf(object.toString())) {
|
|
|
|
+ errorMessage.add("列名[" + excelProperty.value()[0] + "]:" + assertFalse.message());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (errorMessage.size() > 0) {
|
|
|
|
+ extendBasicExcelField(o, analysisContext, errorMessage);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return errorMessage.size() > 0 ? true : false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ //可重写的方法:
|
|
|
|
+// void invoke(T data, AnalysisContext context); //处理一行数据
|
|
|
|
+// void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) //处理表头的一行数据
|
|
|
|
+// void extra(CellExtra extra, AnalysisContext context); //获取单元格的额外信息
|
|
|
|
+// void doAfterAllAnalysed(AnalysisContext context) //全部读取结束后的操作
|
|
|
|
+// boolean hasNext(AnalysisContext context); //是否读取下一行
|
|
|
|
+// void onException(Exception exception, AnalysisContext context) //发生异常时调用
|
|
|
|
+}
|