耶耶耶耶耶 发表于 2025-1-26 11:18:54

easyexcel-导入(读取)(read)-示例及核心部件

这块内容有点多,单独拉出来,要不看着太乱。
导入(读取)(read)-示例及核心部件

代码:
EasyExcel.read(file.getInputStream(), UserExcelVo.class, userListener).extraRead(CellExtraTypeEnum.MERGE)
      .sheet(0) // 指定读取哪个sheet
      .headRowNumber(1) // 指定标题行
      .doRead(); // 执行读取
导入(读取)(read)-核心部件

以上面代码为例。
EasyExcel(EasyExcelFactory) # 入口

read() # read()方法用于构建workbook(工作簿)对象,new ExcelReaderBuilder()

public class EasyExcelFactory {
   public static ExcelReaderBuilder read() {
      return new ExcelReaderBuilder();
    }
}
public class ExcelReaderBuilder extends AbstractExcelReaderParameterBuilder<ExcelReaderBuilder, ReadWorkbook> {
    /**
   * Workbook
   */
    private final ReadWorkbook readWorkbook;

    public ExcelReaderBuilder() {
      this.readWorkbook = new ReadWorkbook();
    }
}
doReadAll()

public class ExcelReaderBuilder extends AbstractExcelReaderParameterBuilder<ExcelReaderBuilder, ReadWorkbook> {
    public void doReadAll() {
      try (ExcelReader excelReader = build()) {
            excelReader.readAll();
      }
    }
}
public class ExcelReader implements Closeable {
   public void readAll() {
      excelAnalyser.analysis(null, Boolean.TRUE);
    }
}
public class ExcelAnalyserImpl implements ExcelAnalyser {
@Override
    public void analysis(List<ReadSheet> readSheetList, Boolean readAll) {
      try {
            if (!readAll && CollectionUtils.isEmpty(readSheetList)) {
                throw new IllegalArgumentException("Specify at least one read sheet.");
            }
            analysisContext.readWorkbookHolder().setParameterSheetDataList(readSheetList);
            analysisContext.readWorkbookHolder().setReadAll(readAll);
            try {
                excelReadExecutor.execute();
            } catch (ExcelAnalysisStopException e) {
                if (LOGGER.isDebugEnabled()) {
                  LOGGER.debug("Custom stop!");
                }
            }
      } catch (RuntimeException e) {
            finish();
            throw e;
      } catch (Throwable e) {
            finish();
            throw new ExcelAnalysisException(e);
      }
    }
}
这里选XlsxSaxAnalyser这个实现类吧

public class XlsxSaxAnalyser implements ExcelReadExecutor {
@Override
    public void execute() {
      for (ReadSheet readSheet : sheetList) {
            readSheet = SheetUtils.match(readSheet, xlsxReadContext);
            if (readSheet != null) {
                xlsxReadContext.currentSheet(readSheet);
                parseXmlSource(sheetMap.get(readSheet.getSheetNo()), new XlsxRowHandler(xlsxReadContext));
                // Read comments
                readComments(readSheet);
                // The last sheet is read
                xlsxReadContext.analysisEventProcessor().endSheet(xlsxReadContext);
            }
      }
    }
}
然后到这个类XlsxRowHandler,这里利用了策略模式,会根据xml差异的标签拿到对应的处置惩罚类来举行处置惩罚。

public class XlsxRowHandler extends DefaultHandler {
static {
      CellFormulaTagHandler cellFormulaTagHandler = new CellFormulaTagHandler();
      XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.CELL_FORMULA_TAG, cellFormulaTagHandler);
      XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.X_CELL_FORMULA_TAG, cellFormulaTagHandler);
      XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.NS2_CELL_FORMULA_TAG, cellFormulaTagHandler);
      CellInlineStringValueTagHandler cellInlineStringValueTagHandler = new CellInlineStringValueTagHandler();
      XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.CELL_INLINE_STRING_VALUE_TAG, cellInlineStringValueTagHandler);
      XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.X_CELL_INLINE_STRING_VALUE_TAG, cellInlineStringValueTagHandler);
      XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.NS2_CELL_INLINE_STRING_VALUE_TAG, cellInlineStringValueTagHandler);
      CellTagHandler cellTagHandler = new CellTagHandler();
      XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.CELL_TAG, cellTagHandler);
      XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.X_CELL_TAG, cellTagHandler);
      XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.NS2_CELL_TAG, cellTagHandler);
      CellValueTagHandler cellValueTagHandler = new CellValueTagHandler();
      XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.CELL_VALUE_TAG, cellValueTagHandler);
      XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.X_CELL_VALUE_TAG, cellValueTagHandler);
      XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.NS2_CELL_VALUE_TAG, cellValueTagHandler);
      CountTagHandler countTagHandler = new CountTagHandler();
      XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.DIMENSION_TAG, countTagHandler);
      XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.X_DIMENSION_TAG, countTagHandler);
      XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.NS2_DIMENSION_TAG, countTagHandler);
      HyperlinkTagHandler hyperlinkTagHandler = new HyperlinkTagHandler();
      XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.HYPERLINK_TAG, hyperlinkTagHandler);
      XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.X_HYPERLINK_TAG, hyperlinkTagHandler);
      XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.NS2_HYPERLINK_TAG, hyperlinkTagHandler);
      MergeCellTagHandler mergeCellTagHandler = new MergeCellTagHandler();
      XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.MERGE_CELL_TAG, mergeCellTagHandler);
      XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.X_MERGE_CELL_TAG, mergeCellTagHandler);
      XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.NS2_MERGE_CELL_TAG, mergeCellTagHandler);
      RowTagHandler rowTagHandler = new RowTagHandler();
      XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.ROW_TAG, rowTagHandler);
      XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.X_ROW_TAG, rowTagHandler);
      XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.NS2_ROW_TAG, rowTagHandler);
    }
}
从上面代码找到RowTagHandler这个类,每剖析了一行数据后都会举行处置惩罚

public class RowTagHandler extends AbstractXlsxTagHandler {
@Override
    public void endElement(XlsxReadContext xlsxReadContext, String name) {
      XlsxReadSheetHolder xlsxReadSheetHolder = xlsxReadContext.xlsxReadSheetHolder();
      RowTypeEnum rowType = MapUtils.isEmpty(xlsxReadSheetHolder.getCellMap()) ? RowTypeEnum.EMPTY : RowTypeEnum.DATA;
      // It's possible that all of the cells in the row are empty
      if (rowType == RowTypeEnum.DATA) {
            boolean hasData = false;
            for (Cell cell : xlsxReadSheetHolder.getCellMap().values()) {
                if (!(cell instanceof ReadCellData)) {
                  hasData = true;
                  break;
                }
                ReadCellData<?> readCellData = (ReadCellData<?>)cell;
                if (readCellData.getType() != CellDataTypeEnum.EMPTY) {
                  hasData = true;
                  break;
                }
            }
            if (!hasData) {
                rowType = RowTypeEnum.EMPTY;
            }
      }
      xlsxReadContext.readRowHolder(new ReadRowHolder(xlsxReadSheetHolder.getRowIndex(), rowType,
            xlsxReadSheetHolder.getGlobalConfiguration(), xlsxReadSheetHolder.getCellMap()));
      xlsxReadContext.analysisEventProcessor().endRow(xlsxReadContext);
      xlsxReadSheetHolder.setColumnIndex(null);
      xlsxReadSheetHolder.setCellMap(new LinkedHashMap<>());
    }
}
然后看endRow()方法

public class DefaultAnalysisEventProcessor implements AnalysisEventProcessor {
    @Override
    public void endRow(AnalysisContext analysisContext) {
      if (RowTypeEnum.EMPTY.equals(analysisContext.readRowHolder().getRowType())) {
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("Empty row!");
            }
            if (analysisContext.readWorkbookHolder().getIgnoreEmptyRow()) {
                return;
            }
      }
      dealData(analysisContext);
    }
}
进入到dealData方法中

private void dealData(AnalysisContext analysisContext) {
      ReadRowHolder readRowHolder = analysisContext.readRowHolder();
      Map<Integer, ReadCellData<?>> cellDataMap = (Map)readRowHolder.getCellMap();
      readRowHolder.setCurrentRowAnalysisResult(cellDataMap);
      int rowIndex = readRowHolder.getRowIndex();
      int currentHeadRowNumber = analysisContext.readSheetHolder().getHeadRowNumber();

      boolean isData = rowIndex >= currentHeadRowNumber;

      // Last head column
      if (!isData && currentHeadRowNumber == rowIndex + 1) {
            buildHead(analysisContext, cellDataMap);
      }
      // Now is data
      for (ReadListener readListener : analysisContext.currentReadHolder().readListenerList()) {
            try {
                if (isData) {
                  readListener.invoke(readRowHolder.getCurrentRowAnalysisResult(), analysisContext);
                } else {
                  readListener.invokeHead(cellDataMap, analysisContext);
                }
            } catch (Exception e) {
                onException(analysisContext, e);
                break;
            }
            if (!readListener.hasNext(analysisContext)) {
                throw new ExcelAnalysisStopException();
            }
      }
    }
这里可以看到,每剖析了一行数据后都会逐个调用监听器的invoke方法(包括easyexcel默认的监听器和我们自定义的监听器)
跟踪invoke()方法,选用ModelBuildEventListener这个实现类吧

进入到ModelBuildEventListener实现类,这个实现类是easyexcel自带的默认的监听器,这个监听器的主要作用是将excel的每行数据封装
public class ModelBuildEventListener implements IgnoreExceptionReadListener<Map<Integer, ReadCellData<?>>> {

    @Override
    public void invoke(Map<Integer, ReadCellData<?>> cellDataMap, AnalysisContext context) {
      ReadSheetHolder readSheetHolder = context.readSheetHolder();
      if (HeadKindEnum.CLASS.equals(readSheetHolder.excelReadHeadProperty().getHeadKind())) {
            context.readRowHolder()
                .setCurrentRowAnalysisResult(buildUserModel(cellDataMap, readSheetHolder, context));
            return;
      }
      context.readRowHolder().setCurrentRowAnalysisResult(buildNoModel(cellDataMap, readSheetHolder, context));
    }
}
进入到buildUserModel方法中

private Object buildUserModel(Map<Integer, ReadCellData<?>> cellDataMap, ReadSheetHolder readSheetHolder,
      AnalysisContext context) {
      ExcelReadHeadProperty excelReadHeadProperty = readSheetHolder.excelReadHeadProperty();
      Object resultModel;
      try {
            resultModel = excelReadHeadProperty.getHeadClazz().newInstance();
      } catch (Exception e) {
            throw new ExcelDataConvertException(context.readRowHolder().getRowIndex(), 0,
                new ReadCellData<>(CellDataTypeEnum.EMPTY), null,
                "Can not instance class: " + excelReadHeadProperty.getHeadClazz().getName(), e);
      }
      Map<Integer, Head> headMap = excelReadHeadProperty.getHeadMap();
      BeanMap dataMap = BeanMapUtils.create(resultModel);
      for (Map.Entry<Integer, Head> entry : headMap.entrySet()) {
            Integer index = entry.getKey();
            Head head = entry.getValue();
            String fieldName = head.getFieldName();
            if (!cellDataMap.containsKey(index)) {
                continue;
            }
            ReadCellData<?> cellData = cellDataMap.get(index);
            Object value = ConverterUtils.convertToJavaObject(cellData, head.getField(),
                ClassUtils.declaredExcelContentProperty(dataMap, readSheetHolder.excelReadHeadProperty().getHeadClazz(),
                  fieldName, readSheetHolder), readSheetHolder.converterMap(), context,
                context.readRowHolder().getRowIndex(), index);
            if (value != null) {
                dataMap.put(fieldName, value);
            }
      }
      return resultModel;
    }
可以看到,先是通过反射创建对象,然后根据反射对各个对象赋值。
至此,excel的一行数据就被easyexcel默认的监听器剖析成了对应的java对象,然后我们在自定义的监听器中就能拿到这个对象并举行处置惩罚了。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: easyexcel-导入(读取)(read)-示例及核心部件