• EasyExcel的源码流程(导入Excel)


    1. 入口

    2.  EasyExcel类继承了EasyExcelFactory类,EasyExcel自动拥有EasyExcelFactory父类的所有方法,如read(),readSheet(),write(),writerSheet()等等。

    3. 进入.read()方法,需要传入三个参数(文件路径,表头映射类,read监听器)
       首先调用new ExcelReaderBuilder()方法,初始化ReadWorkbook对象
       设置完readWorkbook属性后调,返回excelReaderBuilder对象 

    4. 这里又个传入的参数是read监听器,进入其内部看一下,我们自定义了PersonListener实现了ReadListener。ReadListener接口源码 :

    自定义的PersonListener类:

    1. import com.alibaba.excel.context.AnalysisContext;
    2. import com.alibaba.excel.event.AnalysisEventListener;
    3. import com.aliyun.odps.jdbc.utils.LoggerFactory;
    4. import org.springframework.stereotype.Component;
    5. import java.util.ArrayList;
    6. import java.util.List;
    7. import java.util.Map;
    8. import java.util.logging.Logger;
    9. @Component
    10. public class PersonListener extends AnalysisEventListener {
    11. //一行一行读出excel内容 不读表头 EasyExcel之所以效率高,也是因它一行一行读取,解析。
    12. @Override
    13. public void invoke(PersonTest personTest, AnalysisContext analysisContext) {
    14. System.out.println("***"+personTest);
    15. }
    16. //读取表头
    17. @Override
    18. public void invokeHeadMap(Map headMap, AnalysisContext context) {
    19. System.out.println("表头"+headMap);
    20. }
    21. //读取完执行的方法
    22. @Override
    23. public void doAfterAllAnalysed(AnalysisContext analysisContext) {
    24. System.out.println("读取全部后执行");
    25. }
    26. }

    5. 接下来调用的是.sheet()方法,这里我们会传入sheetNo、sheetName参数,调用build()方法创建ExcelReader对象,传入ExcelReaderSheetBuilder构造方法中,最终创ExcelReaderSheetBuilder对象 

    6. 进入build()方法,build()方法生成了ExcelReader对象,初始化ExcelAnalyser,并实例化ExcelAnalyser。

    在实例化ExcelAnalyser时,choiceExcelExecutor()方法通过excel格式使用不同的执行器。
    我们看XLSX中,初始化了XlsxReadContext上下文对象,给到analysisContext,又初始化了XlsxSaxAnalyser解析器对象 

    1. public class ExcelAnalyserImpl implements ExcelAnalyser {
    2. private static final Logger LOGGER = LoggerFactory.getLogger(ExcelAnalyserImpl.class);
    3. private AnalysisContext analysisContext;
    4. private ExcelReadExecutor excelReadExecutor;
    5. /**
    6. * Prevent multiple shutdowns
    7. */
    8. private boolean finished = false;
    9. public ExcelAnalyserImpl(ReadWorkbook readWorkbook) {
    10. try {
    11. choiceExcelExecutor(readWorkbook);
    12. } catch (RuntimeException e) {
    13. finish();
    14. throw e;
    15. } catch (Throwable e) {
    16. finish();
    17. throw new ExcelAnalysisException(e);
    18. }
    19. }
    20. private void choiceExcelExecutor(ReadWorkbook readWorkbook) throws Exception {
    21. ExcelTypeEnum excelType = ExcelTypeEnum.valueOf(readWorkbook);
    22. switch (excelType) {
    23. case XLS:
    24. POIFSFileSystem poifsFileSystem;
    25. if (readWorkbook.getFile() != null) {
    26. poifsFileSystem = new POIFSFileSystem(readWorkbook.getFile());
    27. } else {
    28. poifsFileSystem = new POIFSFileSystem(readWorkbook.getInputStream());
    29. }
    30. // So in encrypted excel, it looks like XLS but it's actually XLSX
    31. if (poifsFileSystem.getRoot().hasEntry(Decryptor.DEFAULT_POIFS_ENTRY)) {
    32. InputStream decryptedStream = null;
    33. try {
    34. decryptedStream = DocumentFactoryHelper
    35. .getDecryptedStream(poifsFileSystem.getRoot().getFileSystem(), readWorkbook.getPassword());
    36. XlsxReadContext xlsxReadContext = new DefaultXlsxReadContext(readWorkbook, ExcelTypeEnum.XLSX);
    37. analysisContext = xlsxReadContext;
    38. excelReadExecutor = new XlsxSaxAnalyser(xlsxReadContext, decryptedStream);
    39. return;
    40. } finally {
    41. IOUtils.closeQuietly(decryptedStream);
    42. // as we processed the full stream already, we can close the filesystem here
    43. // otherwise file handles are leaked
    44. poifsFileSystem.close();
    45. }
    46. }
    47. if (readWorkbook.getPassword() != null) {
    48. Biff8EncryptionKey.setCurrentUserPassword(readWorkbook.getPassword());
    49. }
    50. XlsReadContext xlsReadContext = new DefaultXlsReadContext(readWorkbook, ExcelTypeEnum.XLS);
    51. xlsReadContext.xlsReadWorkbookHolder().setPoifsFileSystem(poifsFileSystem);
    52. analysisContext = xlsReadContext;
    53. excelReadExecutor = new XlsSaxAnalyser(xlsReadContext);
    54. break;
    55. case XLSX:
    56. XlsxReadContext xlsxReadContext = new DefaultXlsxReadContext(readWorkbook, ExcelTypeEnum.XLSX);
    57. analysisContext = xlsxReadContext;
    58. excelReadExecutor = new XlsxSaxAnalyser(xlsxReadContext, null);
    59. break;
    60. case CSV:
    61. CsvReadContext csvReadContext = new DefaultCsvReadContext(readWorkbook, ExcelTypeEnum.CSV);
    62. analysisContext = csvReadContext;
    63. excelReadExecutor = new CsvExcelReadExecutor(csvReadContext);
    64. break;
    65. default:
    66. break;
    67. }
    68. }
    69. /*
    70. ----------------------------------------略---------------------------------------------
    71. */
    72. }

    7. XlsxSaxAnalyser详解

        7.1 进入new XlsxSaxAnalyser(xlsxReadContext, null)方法看一下,这里使用到SAX模式模式解析excel

    1. public XlsxSaxAnalyser(XlsxReadContext xlsxReadContext, InputStream decryptedStream) throws Exception {
    2. this.xlsxReadContext = xlsxReadContext;
    3. // 初始化缓存(cache)
    4. XlsxReadWorkbookHolder xlsxReadWorkbookHolder = xlsxReadContext.xlsxReadWorkbookHolder();
    5. OPCPackage pkg = readOpcPackage(xlsxReadWorkbookHolder, decryptedStream);
    6. xlsxReadWorkbookHolder.setOpcPackage(pkg);
    7. // Read the Shared information Strings
    8. PackagePart sharedStringsTablePackagePart = pkg.getPart(SHARED_STRINGS_PART_NAME);
    9. if (sharedStringsTablePackagePart != null) {
    10. // 指定默认缓存
    11. defaultReadCache(xlsxReadWorkbookHolder, sharedStringsTablePackagePart);
    12. // 分析sharedStringsTable.xml,解析excel所有数据到readCache
    13. analysisSharedStringsTable(sharedStringsTablePackagePart.getInputStream(), xlsxReadWorkbookHolder);
    14. }
    15. XSSFReader xssfReader = new XSSFReader(pkg);
    16. analysisUse1904WindowDate(xssfReader, xlsxReadWorkbookHolder);
    17. // 设置样式表
    18. setStylesTable(xlsxReadWorkbookHolder, xssfReader);
    19. sheetList = new ArrayList<>();
    20. sheetMap = new HashMap<>();
    21. commentsTableMap = new HashMap<>();
    22. Map packageRelationshipCollectionMap = MapUtils.newHashMap();
    23. xlsxReadWorkbookHolder.setPackageRelationshipCollectionMap(packageRelationshipCollectionMap);
    24. // 获取所有sheet页
    25. XSSFReader.SheetIterator ite = (XSSFReader.SheetIterator)xssfReader.getSheetsData();
    26. int index = 0;
    27. if (!ite.hasNext()) {
    28. throw new ExcelAnalysisException("Can not find any sheet!");
    29. }
    30. // 遍历sheet页
    31. while (ite.hasNext()) {
    32. InputStream inputStream = ite.next();
    33. // 保存所有sheet页
    34. sheetList.add(new ReadSheet(index, ite.getSheetName()));
    35. // 保存所有sheet页的输入流
    36. sheetMap.put(index, inputStream);
    37. if (xlsxReadContext.readWorkbookHolder().getExtraReadSet().contains(CellExtraTypeEnum.COMMENT)) {
    38. CommentsTable commentsTable = ite.getSheetComments();
    39. if (null != commentsTable) {
    40. commentsTableMap.put(index, commentsTable);
    41. }
    42. }
    43. if (xlsxReadContext.readWorkbookHolder().getExtraReadSet().contains(CellExtraTypeEnum.HYPERLINK)) {
    44. PackageRelationshipCollection packageRelationshipCollection = Optional.ofNullable(ite.getSheetPart())
    45. .map(packagePart -> {
    46. try {
    47. return packagePart.getRelationships();
    48. } catch (InvalidFormatException e) {
    49. log.warn("Reading the Relationship failed", e);
    50. return null;
    51. }
    52. }).orElse(null);
    53. if (packageRelationshipCollection != null) {
    54. packageRelationshipCollectionMap.put(index, packageRelationshipCollection);
    55. }
    56. }
    57. index++;
    58. }
    59. }

        7.2 进入analysisSharedStringsTable方法,可以看到创建了一个SharedStringsTableHandler处理器

        7.3 再进入parseXmlSource看到xmlReader.setContentHandler(handler)这一行代码,设置了SharedStringsTableHandler处理器

    1. private void parseXmlSource(InputStream inputStream, ContentHandler handler) {
    2. InputSource inputSource = new InputSource(inputStream);
    3. try {
    4. SAXParserFactory saxFactory;
    5. String xlsxSAXParserFactoryName = xlsxReadContext.xlsxReadWorkbookHolder().getSaxParserFactoryName();
    6. if (StringUtils.isEmpty(xlsxSAXParserFactoryName)) {
    7. saxFactory = SAXParserFactory.newInstance();
    8. } else {
    9. saxFactory = SAXParserFactory.newInstance(xlsxSAXParserFactoryName, null);
    10. }
    11. try {
    12. saxFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
    13. } catch (Throwable ignore) {}
    14. try {
    15. saxFactory.setFeature("http://xml.org/sax/features/external-general-entities", false);
    16. } catch (Throwable ignore) {}
    17. try {
    18. saxFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
    19. } catch (Throwable ignore) {}
    20. SAXParser saxParser = saxFactory.newSAXParser();
    21. XMLReader xmlReader = saxParser.getXMLReader();
    22. xmlReader.setContentHandler(handler);
    23. xmlReader.parse(inputSource);
    24. inputStream.close();
    25. } catch (IOException | ParserConfigurationException | SAXException e) {
    26. throw new ExcelAnalysisException(e);
    27. } finally {
    28. if (inputStream != null) {
    29. try {
    30. inputStream.close();
    31. } catch (IOException e) {
    32. throw new ExcelAnalysisException("Can not close 'inputStream'!");
    33. }
    34. }
    35. }
    36. }

        7.4 我们将断点打在SharedStringsTableHandler里,发现下一步进入到这里面的startElement()    starteElement()后会调用endElement()

        7.5 反复调用,excel所有数据读取到readcache中

    8. 调用.doRead()方法,开始SAX解析

        8.1 进入build()方法

        8.2 build()执行完后,执行read()方法,read()里还会进入一次read() 

    9. 调用ExcelAnalyserImpl里的analysis()方法,设置sheetList,并调用执行器开始执行解析 

        9.1 调用的XlsxSaxAnalyser解析器execute()

     10. 进入parseXmlSource()方法,发现和之前的sax差不多,但只两次传入的handler类型不同,还是看一下传入的ContentHandler参数具体实现,进入XlsxRowHandler 内部

    1. public class XlsxRowHandler extends DefaultHandler {
    2. private final XlsxReadContext xlsxReadContext;
    3. private static final Map XLSX_CELL_HANDLER_MAP = new HashMap(32);
    4. static {
    5. CellFormulaTagHandler cellFormulaTagHandler = new CellFormulaTagHandler();
    6. XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.CELL_FORMULA_TAG, cellFormulaTagHandler);
    7. XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.X_CELL_FORMULA_TAG, cellFormulaTagHandler);
    8. CellInlineStringValueTagHandler cellInlineStringValueTagHandler = new CellInlineStringValueTagHandler();
    9. XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.CELL_INLINE_STRING_VALUE_TAG, cellInlineStringValueTagHandler);
    10. XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.X_CELL_INLINE_STRING_VALUE_TAG, cellInlineStringValueTagHandler);
    11. CellTagHandler cellTagHandler = new CellTagHandler();
    12. XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.CELL_TAG, cellTagHandler);
    13. XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.X_CELL_TAG, cellTagHandler);
    14. CellValueTagHandler cellValueTagHandler = new CellValueTagHandler();
    15. XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.CELL_VALUE_TAG, cellValueTagHandler);
    16. XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.X_CELL_VALUE_TAG, cellValueTagHandler);
    17. CountTagHandler countTagHandler = new CountTagHandler();
    18. XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.DIMENSION_TAG, countTagHandler);
    19. XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.X_DIMENSION_TAG, countTagHandler);
    20. HyperlinkTagHandler hyperlinkTagHandler = new HyperlinkTagHandler();
    21. XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.HYPERLINK_TAG, hyperlinkTagHandler);
    22. XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.X_HYPERLINK_TAG, hyperlinkTagHandler);
    23. MergeCellTagHandler mergeCellTagHandler = new MergeCellTagHandler();
    24. XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.MERGE_CELL_TAG, mergeCellTagHandler);
    25. XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.X_MERGE_CELL_TAG, mergeCellTagHandler);
    26. RowTagHandler rowTagHandler = new RowTagHandler();
    27. XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.ROW_TAG, rowTagHandler);
    28. XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.X_ROW_TAG, rowTagHandler);
    29. }
    30. public XlsxRowHandler(XlsxReadContext xlsxReadContext) {
    31. this.xlsxReadContext = xlsxReadContext;
    32. }
    33. @Override
    34. public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException {
    35. XlsxTagHandler handler = XLSX_CELL_HANDLER_MAP.get(name);
    36. if (handler == null || !handler.support(xlsxReadContext)) {
    37. return;
    38. }
    39. xlsxReadContext.xlsxReadSheetHolder().getTagDeque().push(name);
    40. handler.startElement(xlsxReadContext, name, attributes);
    41. }
    42. @Override
    43. public void characters(char[] ch, int start, int length) throws SAXException {
    44. String currentTag = xlsxReadContext.xlsxReadSheetHolder().getTagDeque().peek();
    45. if (currentTag == null) {
    46. return;
    47. }
    48. XlsxTagHandler handler = XLSX_CELL_HANDLER_MAP.get(currentTag);
    49. if (handler == null || !handler.support(xlsxReadContext)) {
    50. return;
    51. }
    52. handler.characters(xlsxReadContext, ch, start, length);
    53. }
    54. @Override
    55. public void endElement(String uri, String localName, String name) throws SAXException {
    56. XlsxTagHandler handler = XLSX_CELL_HANDLER_MAP.get(name);
    57. if (handler == null || !handler.support(xlsxReadContext)) {
    58. return;
    59. }
    60. handler.endElement(xlsxReadContext, name);
    61. xlsxReadContext.xlsxReadSheetHolder().getTagDeque().pop();
    62. }
    63. }

        10.1 startElement()和endElement()都有多种实现

    11. 进入用到的重要的几个类CellTagHandler、RowTagHandler

    CellTagHandler: 读取cell的值,并放入tempCellData

    1. public void startElement(XlsxReadContext xlsxReadContext, String name, Attributes attributes) {
    2. XlsxReadSheetHolder xlsxReadSheetHolder = xlsxReadContext.xlsxReadSheetHolder();
    3. xlsxReadSheetHolder.setColumnIndex(PositionUtils.getCol(attributes.getValue(ExcelXmlConstants.ATTRIBUTE_R),
    4. xlsxReadSheetHolder.getColumnIndex()));
    5. // t="s" ,it means String
    6. // t="str" ,it means String,but does not need to be read in the 'sharedStrings.xml'
    7. // t="inlineStr" ,it means String,but does not need to be read in the 'sharedStrings.xml'
    8. // t="b" ,it means Boolean
    9. // t="e" ,it means Error
    10. // t="n" ,it means Number
    11. // t is null ,it means Empty or Number
    12. CellDataTypeEnum type = CellDataTypeEnum.buildFromCellType(attributes.getValue(ExcelXmlConstants.ATTRIBUTE_T));
    13. xlsxReadSheetHolder.setTempCellData(new ReadCellData<>(type));
    14. xlsxReadSheetHolder.setTempData(new StringBuilder());
    15. // Put in data transformation information
    16. String dateFormatIndex = attributes.getValue(ExcelXmlConstants.ATTRIBUTE_S);
    17. int dateFormatIndexInteger;
    18. if (StringUtils.isEmpty(dateFormatIndex)) {
    19. dateFormatIndexInteger = DEFAULT_FORMAT_INDEX;
    20. } else {
    21. dateFormatIndexInteger = Integer.parseInt(dateFormatIndex);
    22. }
    23. xlsxReadSheetHolder.getTempCellData().setDataFormatData(
    24. xlsxReadContext.xlsxReadWorkbookHolder().dataFormatData(dateFormatIndexInteger));
    25. }
    26. @Override
    27. public void endElement(XlsxReadContext xlsxReadContext, String name) {
    28. XlsxReadSheetHolder xlsxReadSheetHolder = xlsxReadContext.xlsxReadSheetHolder();
    29. ReadCellData tempCellData = xlsxReadSheetHolder.getTempCellData();
    30. StringBuilder tempData = xlsxReadSheetHolder.getTempData();
    31. String tempDataString = tempData.toString();
    32. CellDataTypeEnum oldType = tempCellData.getType();
    33. switch (oldType) {
    34. case STRING:
    35. // In some cases, although cell type is a string, it may be an empty tag
    36. if (StringUtils.isEmpty(tempDataString)) {
    37. break;
    38. }
    39. String stringValue = xlsxReadContext.readWorkbookHolder().getReadCache().get(
    40. Integer.valueOf(tempDataString));
    41. tempCellData.setStringValue(stringValue);
    42. break;
    43. case DIRECT_STRING:
    44. case ERROR:
    45. tempCellData.setStringValue(tempDataString);
    46. tempCellData.setType(CellDataTypeEnum.STRING);
    47. break;
    48. case BOOLEAN:
    49. if (StringUtils.isEmpty(tempDataString)) {
    50. tempCellData.setType(CellDataTypeEnum.EMPTY);
    51. break;
    52. }
    53. tempCellData.setBooleanValue(BooleanUtils.valueOf(tempData.toString()));
    54. break;
    55. case NUMBER:
    56. case EMPTY:
    57. if (StringUtils.isEmpty(tempDataString)) {
    58. tempCellData.setType(CellDataTypeEnum.EMPTY);
    59. break;
    60. }
    61. tempCellData.setType(CellDataTypeEnum.NUMBER);
    62. tempCellData.setNumberValue(BigDecimal.valueOf(Double.parseDouble(tempDataString)));
    63. break;
    64. default:
    65. throw new IllegalStateException("Cannot set values now");
    66. }
    67. if (tempCellData.getStringValue() != null
    68. && xlsxReadContext.currentReadHolder().globalConfiguration().getAutoTrim()) {
    69. tempCellData.setStringValue(tempCellData.getStringValue().trim());
    70. }
    71. tempCellData.checkEmpty();
    72. tempCellData.setRowIndex(xlsxReadSheetHolder.getRowIndex());
    73. tempCellData.setColumnIndex(xlsxReadSheetHolder.getColumnIndex());
    74. xlsxReadSheetHolder.getCellMap().put(xlsxReadSheetHolder.getColumnIndex(), tempCellData);
    75. }

    RowTagHandler: 当一行读取完毕后,调用分析事件处理器,处理一行数据

                                xlsxReadContext.analysisEventProcessor().endRow(xlsxReadContext);

    1. public void startElement(XlsxReadContext xlsxReadContext, String name, Attributes attributes) {
    2. XlsxReadSheetHolder xlsxReadSheetHolder = xlsxReadContext.xlsxReadSheetHolder();
    3. int rowIndex = PositionUtils.getRowByRowTagt(attributes.getValue(ExcelXmlConstants.ATTRIBUTE_R),
    4. xlsxReadSheetHolder.getRowIndex());
    5. Integer lastRowIndex = xlsxReadContext.readSheetHolder().getRowIndex();
    6. while (lastRowIndex + 1 < rowIndex) {
    7. xlsxReadContext.readRowHolder(new ReadRowHolder(lastRowIndex + 1, RowTypeEnum.EMPTY,
    8. xlsxReadSheetHolder.getGlobalConfiguration(), new LinkedHashMap()));
    9. xlsxReadContext.analysisEventProcessor().endRow(xlsxReadContext);
    10. xlsxReadSheetHolder.setColumnIndex(null);
    11. xlsxReadSheetHolder.setCellMap(new LinkedHashMap());
    12. lastRowIndex++;
    13. }
    14. xlsxReadSheetHolder.setRowIndex(rowIndex);
    15. }
    16. @Override
    17. public void endElement(XlsxReadContext xlsxReadContext, String name) {
    18. XlsxReadSheetHolder xlsxReadSheetHolder = xlsxReadContext.xlsxReadSheetHolder();
    19. RowTypeEnum rowType = MapUtils.isEmpty(xlsxReadSheetHolder.getCellMap()) ? RowTypeEnum.EMPTY : RowTypeEnum.DATA;
    20. // It's possible that all of the cells in the row are empty
    21. if (rowType == RowTypeEnum.DATA) {
    22. boolean hasData = false;
    23. for (Cell cell : xlsxReadSheetHolder.getCellMap().values()) {
    24. if (!(cell instanceof ReadCellData)) {
    25. hasData = true;
    26. break;
    27. }
    28. ReadCellData readCellData = (ReadCellData)cell;
    29. if (readCellData.getType() != CellDataTypeEnum.EMPTY) {
    30. hasData = true;
    31. break;
    32. }
    33. }
    34. if (!hasData) {
    35. rowType = RowTypeEnum.EMPTY;
    36. }
    37. }
    38. xlsxReadContext.readRowHolder(new ReadRowHolder(xlsxReadSheetHolder.getRowIndex(), rowType,
    39. xlsxReadSheetHolder.getGlobalConfiguration(), xlsxReadSheetHolder.getCellMap()));
    40. xlsxReadContext.analysisEventProcessor().endRow(xlsxReadContext);
    41. xlsxReadSheetHolder.setColumnIndex(null);
    42. xlsxReadSheetHolder.setCellMap(new LinkedHashMap<>());
    43. }

    12. 进入endRow()方法

          endRow()里通过getIgnoreEmptyRow()来判断是否忽略空行(true为忽略,默认为true)

         想要设置IgnoreEmptyRow为false,可以在最初使用EasyExcel时设置:

    13. 进入dealData()方法

    1. private void dealData(AnalysisContext analysisContext) {
    2. ReadRowHolder readRowHolder = analysisContext.readRowHolder();
    3. Map> cellDataMap = (Map)readRowHolder.getCellMap();
    4. readRowHolder.setCurrentRowAnalysisResult(cellDataMap);
    5. int rowIndex = readRowHolder.getRowIndex();
    6. int currentHeadRowNumber = analysisContext.readSheetHolder().getHeadRowNumber();
    7. boolean isData = rowIndex >= currentHeadRowNumber;
    8. // Last head column
    9. if (!isData && currentHeadRowNumber == rowIndex + 1) {
    10. buildHead(analysisContext, cellDataMap);
    11. }
    12. // Now is data
    13. for (ReadListener readListener : analysisContext.currentReadHolder().readListenerList()) {
    14. try {
    15. if (isData) {
    16. readListener.invoke(readRowHolder.getCurrentRowAnalysisResult(), analysisContext);
    17. } else {
    18. readListener.invokeHead(cellDataMap, analysisContext);
    19. }
    20. } catch (Exception e) {
    21. onException(analysisContext, e);
    22. break;
    23. }
    24. if (!readListener.hasNext(analysisContext)) {
    25. throw new ExcelAnalysisStopException();
    26. }
    27. }
    28. }

    14. dealData()方法中的invoke方法会执行ModelBuildEventListener里的invoke()方法,在这里会进行单行数据到实体类的映射,buildStringList()真正执行映射

    15. 退回XlsxSaxAnalyser的解析器execute()方法

          进入readComments()方法,读取额外信息(批注、超链接、合并单元格信息读取)

    1. private void readComments(ReadSheet readSheet) {
    2. if (!xlsxReadContext.readWorkbookHolder().getExtraReadSet().contains(CellExtraTypeEnum.COMMENT)) {
    3. return;
    4. }
    5. CommentsTable commentsTable = commentsTableMap.get(readSheet.getSheetNo());
    6. if (commentsTable == null) {
    7. return;
    8. }
    9. Iterator cellAddresses = commentsTable.getCellAddresses();
    10. while (cellAddresses.hasNext()) {
    11. CellAddress cellAddress = cellAddresses.next();
    12. XSSFComment cellComment = commentsTable.findCellComment(cellAddress);
    13. CellExtra cellExtra = new CellExtra(CellExtraTypeEnum.COMMENT, cellComment.getString().toString(),
    14. cellAddress.getRow(), cellAddress.getColumn());
    15. xlsxReadContext.readSheetHolder().setCellExtra(cellExtra);
    16. xlsxReadContext.analysisEventProcessor().extra(xlsxReadContext);
    17. }
    18. }

    16. 最后进入.endSheet(xlsxReadContext)方法

    1. @Override
    2. public void endSheet(AnalysisContext analysisContext) {
    3. // 这里会调用所有监听器中的doAfterAllAnalysed方法,执行最后的操作
    4. for (ReadListener readListener : analysisContext.currentReadHolder().readListenerList()) {
    5. readListener.doAfterAllAnalysed(analysisContext);
    6. }
    7. }

    17. 在读取完毕之后,执行finish()方法,关闭所有流 

  • 相关阅读:
    浮点数通信
    vben-admin 学习记录
    TVS选型:瞬态抑制二极管选型!|深圳比创达EMC
    在Vue3项目中使用pinia代替Vuex进行数据存储
    SpringBoot:(六)YAML配置文件
    python爬虫基于管道持久化存储操作
    SpringBoot 整合Spring Security(简单版)
    服务器动态/静态/住宅/原生IP都是什么意思
    ASP WebShell 后门脚本与免杀
    力扣(LeetCode)75. 颜色分类(C语言)
  • 原文地址:https://blog.csdn.net/qq_44527508/article/details/133296044