From e63190976af92983c9e3e1de6c065628bc26b3b7 Mon Sep 17 00:00:00 2001 From: Jiaju Zhuang Date: Sun, 15 Mar 2020 04:06:04 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E6=96=B0=E5=A2=9E=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E8=AF=BB=E5=8F=96=E6=89=B9=E6=B3=A8=E3=80=81=E8=B6=85?= =?UTF-8?q?=E9=93=BE=E6=8E=A5=E3=80=81=E5=90=88=E5=B9=B6=E5=8D=95=E5=85=83?= =?UTF-8?q?=E6=A0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../excel/analysis/ExcelAnalyserImpl.java | 10 +- .../analysis/v03/XlsListSheetListener.java | 1 + .../excel/analysis/v03/XlsRecordHandler.java | 8 + .../excel/analysis/v03/XlsSaxAnalyser.java | 15 +- .../handlers/AbstractXlsRecordHandler.java | 19 ++ .../v03/handlers/BlankRecordHandler.java | 2 +- .../v03/handlers/BofRecordHandler.java | 9 +- .../v03/handlers/BoolErrRecordHandler.java | 2 +- .../v03/handlers/BoundSheetRecordHandler.java | 2 +- .../v03/handlers/DummyRecordHandler.java | 4 +- .../v03/handlers/EofRecordHandler.java | 2 +- .../v03/handlers/FormulaRecordHandler.java | 4 +- .../v03/handlers/HyperlinkRecordHandler.java | 30 ++++ .../v03/handlers/IndexRecordHandler.java | 2 +- .../v03/handlers/LabelRecordHandler.java | 2 +- .../v03/handlers/LabelSstRecordHandler.java | 2 +- .../v03/handlers/MergeCellsRecordHandler.java | 35 ++++ .../v03/handlers/NoteRecordHandler.java | 20 ++- .../v03/handlers/NumberRecordHandler.java | 2 +- .../v03/handlers/ObjRecordHandler.java | 2 +- .../v03/handlers/RkRecordHandler.java | 2 +- .../v03/handlers/SstRecordHandler.java | 2 +- .../v03/handlers/StringRecordHandler.java | 2 +- .../v03/handlers/TextObjectRecordHandler.java | 8 +- .../analysis/v07/XlsxHandlerFactory.java | 28 --- .../analysis/v07/XlsxRowResultHolder.java | 33 ---- .../excel/analysis/v07/XlsxSaxAnalyser.java | 42 ++++- .../handlers/AbstractCellValueTagHandler.java | 64 +++++++ .../v07/handlers/AbstractXlsxTagHandler.java | 32 ++++ .../v07/handlers/CellFormulaTagHandler.java | 32 ++++ .../CellInlineStringValueTagHandler.java | 23 +++ .../analysis/v07/handlers/CellTagHandler.java | 53 ++++++ .../v07/handlers/CellValueTagHandler.java | 34 ++++ ...wCellHandler.java => CountTagHandler.java} | 9 +- .../v07/handlers/DefaultCellHandler.java | 169 ------------------ .../v07/handlers/HyperlinkTagHandler.java | 35 ++++ .../v07/handlers/MergeCellTagHandler.java | 34 ++++ .../handlers/ProcessResultCellHandler.java | 30 ---- .../analysis/v07/handlers/RowTagHandler.java | 35 ++++ .../v07/handlers/XlsxCellHandler.java | 29 --- .../analysis/v07/handlers/XlsxTagHandler.java | 53 ++++++ .../v07/handlers/sax/XlsxRowHandler.java | 46 +++-- .../excel/constant/ExcelXmlConstants.java | 15 ++ .../excel/context/AnalysisContext.java | 14 -- .../excel/context/AnalysisContextImpl.java | 10 -- .../excel/enums/CellExtraTypeEnum.java | 21 +++ .../alibaba/excel/enums/ExtraReadEnum.java | 13 -- .../com/alibaba/excel/enums/RowTypeEnum.java | 4 - .../AbstractIgnoreExceptionReadListener.java | 12 ++ .../excel/event/AnalysisEventListener.java | 12 ++ .../com/alibaba/excel/metadata/CellExtra.java | 113 +++++++++++- .../read/builder/ExcelReaderBuilder.java | 37 +++- .../excel/read/listener/ReadListener.java | 11 ++ .../excel/read/metadata/ReadWorkbook.java | 10 +- .../read/metadata/holder/ReadRowHolder.java | 4 +- .../read/metadata/holder/ReadSheetHolder.java | 56 +++++- .../metadata/holder/ReadWorkbookHolder.java | 32 ++-- .../holder/xls/XlsReadSheetHolder.java | 40 ----- .../holder/xls/XlsReadWorkbookHolder.java | 18 +- .../holder/xlsx/XlsxReadSheetHolder.java | 54 +++++- .../holder/xlsx/XlsxReadWorkbookHolder.java | 2 + .../processor/AnalysisEventProcessor.java | 7 + .../DefaultAnalysisEventProcessor.java | 70 ++++---- .../com/alibaba/excel/util/SheetUtils.java | 14 +- .../easyexcel/test/core/extra/ExtraData.java | 14 ++ .../test/core/extra/ExtraDataListener.java | 55 ++++++ .../test/core/extra/ExtraDataTest.java | 44 +++++ .../easyexcel/test/temp/Lock2Test.java | 6 + .../easyexcel/test/temp/read/CommentTest.java | 2 +- src/test/resources/demo/demo.xlsx | Bin 12291 -> 10173 bytes src/test/resources/extra/extra.xls | Bin 0 -> 19968 bytes src/test/resources/extra/extra.xlsx | Bin 0 -> 12045 bytes update.md | 4 +- 73 files changed, 1147 insertions(+), 515 deletions(-) create mode 100644 src/main/java/com/alibaba/excel/analysis/v03/handlers/AbstractXlsRecordHandler.java create mode 100644 src/main/java/com/alibaba/excel/analysis/v03/handlers/HyperlinkRecordHandler.java create mode 100644 src/main/java/com/alibaba/excel/analysis/v03/handlers/MergeCellsRecordHandler.java delete mode 100644 src/main/java/com/alibaba/excel/analysis/v07/XlsxHandlerFactory.java delete mode 100644 src/main/java/com/alibaba/excel/analysis/v07/XlsxRowResultHolder.java create mode 100644 src/main/java/com/alibaba/excel/analysis/v07/handlers/AbstractCellValueTagHandler.java create mode 100644 src/main/java/com/alibaba/excel/analysis/v07/handlers/AbstractXlsxTagHandler.java create mode 100644 src/main/java/com/alibaba/excel/analysis/v07/handlers/CellFormulaTagHandler.java create mode 100644 src/main/java/com/alibaba/excel/analysis/v07/handlers/CellInlineStringValueTagHandler.java create mode 100644 src/main/java/com/alibaba/excel/analysis/v07/handlers/CellTagHandler.java create mode 100644 src/main/java/com/alibaba/excel/analysis/v07/handlers/CellValueTagHandler.java rename src/main/java/com/alibaba/excel/analysis/v07/handlers/{CountRowCellHandler.java => CountTagHandler.java} (68%) delete mode 100644 src/main/java/com/alibaba/excel/analysis/v07/handlers/DefaultCellHandler.java create mode 100644 src/main/java/com/alibaba/excel/analysis/v07/handlers/HyperlinkTagHandler.java create mode 100644 src/main/java/com/alibaba/excel/analysis/v07/handlers/MergeCellTagHandler.java delete mode 100644 src/main/java/com/alibaba/excel/analysis/v07/handlers/ProcessResultCellHandler.java create mode 100644 src/main/java/com/alibaba/excel/analysis/v07/handlers/RowTagHandler.java delete mode 100644 src/main/java/com/alibaba/excel/analysis/v07/handlers/XlsxCellHandler.java create mode 100644 src/main/java/com/alibaba/excel/analysis/v07/handlers/XlsxTagHandler.java create mode 100644 src/main/java/com/alibaba/excel/enums/CellExtraTypeEnum.java delete mode 100644 src/main/java/com/alibaba/excel/enums/ExtraReadEnum.java create mode 100644 src/test/java/com/alibaba/easyexcel/test/core/extra/ExtraData.java create mode 100644 src/test/java/com/alibaba/easyexcel/test/core/extra/ExtraDataListener.java create mode 100644 src/test/java/com/alibaba/easyexcel/test/core/extra/ExtraDataTest.java create mode 100644 src/test/resources/extra/extra.xls create mode 100644 src/test/resources/extra/extra.xlsx diff --git a/src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java b/src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java index f8d81fa6..4546c4bb 100644 --- a/src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java +++ b/src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java @@ -110,7 +110,7 @@ public class ExcelAnalyserImpl implements ExcelAnalyser { if (!readAll && CollectionUtils.isEmpty(readSheetList)) { throw new IllegalArgumentException("Specify at least one read sheet."); } - analysisContext.readWorkbookHolder().setParametersheetDataList(readSheetList); + analysisContext.readWorkbookHolder().setParameterSheetDataList(readSheetList); analysisContext.readWorkbookHolder().setReadAll(readAll); try { excelReadExecutor.execute(); @@ -150,16 +150,16 @@ public class ExcelAnalyserImpl implements ExcelAnalyser { } try { if ((readWorkbookHolder instanceof XlsxReadWorkbookHolder) - && ((XlsxReadWorkbookHolder) readWorkbookHolder).getOpcPackage() != null) { - ((XlsxReadWorkbookHolder) readWorkbookHolder).getOpcPackage().revert(); + && ((XlsxReadWorkbookHolder)readWorkbookHolder).getOpcPackage() != null) { + ((XlsxReadWorkbookHolder)readWorkbookHolder).getOpcPackage().revert(); } } catch (Throwable t) { throwable = t; } try { if ((readWorkbookHolder instanceof XlsReadWorkbookHolder) - && ((XlsReadWorkbookHolder) readWorkbookHolder).getPoifsFileSystem() != null) { - ((XlsReadWorkbookHolder) readWorkbookHolder).getPoifsFileSystem().close(); + && ((XlsReadWorkbookHolder)readWorkbookHolder).getPoifsFileSystem() != null) { + ((XlsReadWorkbookHolder)readWorkbookHolder).getPoifsFileSystem().close(); } } catch (Throwable t) { throwable = t; diff --git a/src/main/java/com/alibaba/excel/analysis/v03/XlsListSheetListener.java b/src/main/java/com/alibaba/excel/analysis/v03/XlsListSheetListener.java index 31d2db8c..cfdc6bee 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/XlsListSheetListener.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/XlsListSheetListener.java @@ -35,6 +35,7 @@ public class XlsListSheetListener implements HSSFListener { public XlsListSheetListener(XlsReadContext xlsReadContext) { this.xlsReadContext = xlsReadContext; + xlsReadContext.xlsReadWorkbookHolder().setNeedReadSheet(Boolean.FALSE); } @Override diff --git a/src/main/java/com/alibaba/excel/analysis/v03/XlsRecordHandler.java b/src/main/java/com/alibaba/excel/analysis/v03/XlsRecordHandler.java index dea327f5..3b4fa7c2 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/XlsRecordHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/XlsRecordHandler.java @@ -10,6 +10,14 @@ import com.alibaba.excel.context.xls.XlsReadContext; * @author Dan Zheng */ public interface XlsRecordHandler { + /** + * Whether to support + * + * @param xlsReadContext + * @param record + */ + boolean support(XlsReadContext xlsReadContext, Record record); + /** * Processing record * diff --git a/src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java b/src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java index c90f6559..a94a7d31 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java @@ -18,9 +18,11 @@ import org.apache.poi.hssf.record.BoolErrRecord; import org.apache.poi.hssf.record.BoundSheetRecord; import org.apache.poi.hssf.record.EOFRecord; import org.apache.poi.hssf.record.FormulaRecord; +import org.apache.poi.hssf.record.HyperlinkRecord; import org.apache.poi.hssf.record.IndexRecord; import org.apache.poi.hssf.record.LabelRecord; import org.apache.poi.hssf.record.LabelSSTRecord; +import org.apache.poi.hssf.record.MergeCellsRecord; import org.apache.poi.hssf.record.NoteRecord; import org.apache.poi.hssf.record.NumberRecord; import org.apache.poi.hssf.record.ObjRecord; @@ -40,9 +42,11 @@ import com.alibaba.excel.analysis.v03.handlers.BoundSheetRecordHandler; import com.alibaba.excel.analysis.v03.handlers.DummyRecordHandler; import com.alibaba.excel.analysis.v03.handlers.EofRecordHandler; import com.alibaba.excel.analysis.v03.handlers.FormulaRecordHandler; +import com.alibaba.excel.analysis.v03.handlers.HyperlinkRecordHandler; import com.alibaba.excel.analysis.v03.handlers.IndexRecordHandler; import com.alibaba.excel.analysis.v03.handlers.LabelRecordHandler; import com.alibaba.excel.analysis.v03.handlers.LabelSstRecordHandler; +import com.alibaba.excel.analysis.v03.handlers.MergeCellsRecordHandler; import com.alibaba.excel.analysis.v03.handlers.NoteRecordHandler; import com.alibaba.excel.analysis.v03.handlers.NumberRecordHandler; import com.alibaba.excel.analysis.v03.handlers.ObjRecordHandler; @@ -84,9 +88,11 @@ public class XlsSaxAnalyser implements HSSFListener, ExcelReadExecutor { XLS_RECORD_HANDLER_MAP.put(DUMMY_RECORD_SID, new DummyRecordHandler()); XLS_RECORD_HANDLER_MAP.put(EOFRecord.sid, new EofRecordHandler()); XLS_RECORD_HANDLER_MAP.put(FormulaRecord.sid, new FormulaRecordHandler()); + XLS_RECORD_HANDLER_MAP.put(HyperlinkRecord.sid, new HyperlinkRecordHandler()); XLS_RECORD_HANDLER_MAP.put(IndexRecord.sid, new IndexRecordHandler()); XLS_RECORD_HANDLER_MAP.put(LabelRecord.sid, new LabelRecordHandler()); XLS_RECORD_HANDLER_MAP.put(LabelSSTRecord.sid, new LabelSstRecordHandler()); + XLS_RECORD_HANDLER_MAP.put(MergeCellsRecord.sid, new MergeCellsRecordHandler()); XLS_RECORD_HANDLER_MAP.put(NoteRecord.sid, new NoteRecordHandler()); XLS_RECORD_HANDLER_MAP.put(NumberRecord.sid, new NumberRecordHandler()); XLS_RECORD_HANDLER_MAP.put(ObjRecord.sid, new ObjRecordHandler()); @@ -117,7 +123,7 @@ public class XlsSaxAnalyser implements HSSFListener, ExcelReadExecutor { EventWorkbookBuilder.SheetRecordCollectingListener workbookBuildingListener = new EventWorkbookBuilder.SheetRecordCollectingListener( xlsReadWorkbookHolder.getFormatTrackingHSSFListener()); - xlsReadWorkbookHolder.setHsffWorkbook(workbookBuildingListener.getStubHSSFWorkbook()); + xlsReadWorkbookHolder.setHssfWorkbook(workbookBuildingListener.getStubHSSFWorkbook()); HSSFEventFactory factory = new HSSFEventFactory(); HSSFRequest request = new HSSFRequest(); request.addListenerForAllRecords(xlsReadWorkbookHolder.getFormatTrackingHSSFListener()); @@ -139,10 +145,15 @@ public class XlsSaxAnalyser implements HSSFListener, ExcelReadExecutor { if (handler == null) { return; } - if ((handler instanceof IgnorableXlsRecordHandler) && xlsReadContext.xlsReadSheetHolder().getIgnoreRecord()) { + boolean ignoreRecord = (handler instanceof IgnorableXlsRecordHandler) + && xlsReadContext.xlsReadSheetHolder() != null && xlsReadContext.xlsReadSheetHolder().getIgnoreRecord(); + if (ignoreRecord) { // No need to read the current sheet return; } + if (!handler.support(xlsReadContext, record)) { + return; + } handler.processRecord(xlsReadContext, record); } diff --git a/src/main/java/com/alibaba/excel/analysis/v03/handlers/AbstractXlsRecordHandler.java b/src/main/java/com/alibaba/excel/analysis/v03/handlers/AbstractXlsRecordHandler.java new file mode 100644 index 00000000..93b3d1a3 --- /dev/null +++ b/src/main/java/com/alibaba/excel/analysis/v03/handlers/AbstractXlsRecordHandler.java @@ -0,0 +1,19 @@ +package com.alibaba.excel.analysis.v03.handlers; + +import org.apache.poi.hssf.record.Record; + +import com.alibaba.excel.analysis.v03.XlsRecordHandler; +import com.alibaba.excel.context.xls.XlsReadContext; + +/** + * Abstract xls record handler + * + * @author Jiaju Zhuang + **/ +public abstract class AbstractXlsRecordHandler implements XlsRecordHandler { + + @Override + public boolean support(XlsReadContext xlsReadContext, Record record) { + return true; + } +} diff --git a/src/main/java/com/alibaba/excel/analysis/v03/handlers/BlankRecordHandler.java b/src/main/java/com/alibaba/excel/analysis/v03/handlers/BlankRecordHandler.java index 372a44ca..e6290eb5 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/handlers/BlankRecordHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/handlers/BlankRecordHandler.java @@ -12,7 +12,7 @@ import com.alibaba.excel.metadata.CellData; * * @author Dan Zheng */ -public class BlankRecordHandler implements IgnorableXlsRecordHandler { +public class BlankRecordHandler extends AbstractXlsRecordHandler implements IgnorableXlsRecordHandler { @Override public void processRecord(XlsReadContext xlsReadContext, Record record) { diff --git a/src/main/java/com/alibaba/excel/analysis/v03/handlers/BofRecordHandler.java b/src/main/java/com/alibaba/excel/analysis/v03/handlers/BofRecordHandler.java index 59870bad..973d83eb 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/handlers/BofRecordHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/handlers/BofRecordHandler.java @@ -7,11 +7,9 @@ import org.apache.poi.hssf.record.BOFRecord; import org.apache.poi.hssf.record.BoundSheetRecord; import org.apache.poi.hssf.record.Record; -import com.alibaba.excel.analysis.v03.XlsRecordHandler; import com.alibaba.excel.context.xls.XlsReadContext; import com.alibaba.excel.exception.ExcelAnalysisStopException; import com.alibaba.excel.read.metadata.ReadSheet; -import com.alibaba.excel.read.metadata.holder.xls.XlsReadSheetHolder; import com.alibaba.excel.read.metadata.holder.xls.XlsReadWorkbookHolder; import com.alibaba.excel.util.SheetUtils; @@ -20,7 +18,7 @@ import com.alibaba.excel.util.SheetUtils; * * @author Dan Zheng */ -public class BofRecordHandler implements XlsRecordHandler { +public class BofRecordHandler extends AbstractXlsRecordHandler { @Override public void processRecord(XlsReadContext xlsReadContext, Record record) { @@ -29,7 +27,6 @@ public class BofRecordHandler implements XlsRecordHandler { return; } XlsReadWorkbookHolder xlsReadWorkbookHolder = xlsReadContext.xlsReadWorkbookHolder(); - XlsReadSheetHolder XlsReadSheetHolder = xlsReadContext.xlsReadSheetHolder(); // Init read sheet Data initReadSheetDataList(xlsReadWorkbookHolder); Integer readSheetIndex = xlsReadWorkbookHolder.getReadSheetIndex(); @@ -43,9 +40,9 @@ public class BofRecordHandler implements XlsRecordHandler { readSheet = SheetUtils.match(readSheet, xlsReadContext); if (readSheet != null) { xlsReadContext.currentSheet(readSheet); - XlsReadSheetHolder.setIgnoreRecord(Boolean.FALSE); + xlsReadContext.xlsReadSheetHolder().setIgnoreRecord(Boolean.FALSE); } else { - XlsReadSheetHolder.setIgnoreRecord(Boolean.TRUE); + xlsReadContext.xlsReadSheetHolder().setIgnoreRecord(Boolean.TRUE); } // Go read the next one xlsReadWorkbookHolder.setReadSheetIndex(xlsReadWorkbookHolder.getReadSheetIndex() + 1); diff --git a/src/main/java/com/alibaba/excel/analysis/v03/handlers/BoolErrRecordHandler.java b/src/main/java/com/alibaba/excel/analysis/v03/handlers/BoolErrRecordHandler.java index 60e72338..8d435213 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/handlers/BoolErrRecordHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/handlers/BoolErrRecordHandler.java @@ -13,7 +13,7 @@ import com.alibaba.excel.metadata.CellData; * * @author Dan Zheng */ -public class BoolErrRecordHandler implements IgnorableXlsRecordHandler { +public class BoolErrRecordHandler extends AbstractXlsRecordHandler implements IgnorableXlsRecordHandler { @Override public void processRecord(XlsReadContext xlsReadContext, Record record) { diff --git a/src/main/java/com/alibaba/excel/analysis/v03/handlers/BoundSheetRecordHandler.java b/src/main/java/com/alibaba/excel/analysis/v03/handlers/BoundSheetRecordHandler.java index 96e7b33c..685dcc65 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/handlers/BoundSheetRecordHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/handlers/BoundSheetRecordHandler.java @@ -11,7 +11,7 @@ import com.alibaba.excel.context.xls.XlsReadContext; * * @author Dan Zheng */ -public class BoundSheetRecordHandler implements IgnorableXlsRecordHandler { +public class BoundSheetRecordHandler extends AbstractXlsRecordHandler implements IgnorableXlsRecordHandler { @Override public void processRecord(XlsReadContext xlsReadContext, Record record) { diff --git a/src/main/java/com/alibaba/excel/analysis/v03/handlers/DummyRecordHandler.java b/src/main/java/com/alibaba/excel/analysis/v03/handlers/DummyRecordHandler.java index 15a68dc9..ab41d298 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/handlers/DummyRecordHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/handlers/DummyRecordHandler.java @@ -18,7 +18,7 @@ import com.alibaba.excel.read.metadata.holder.xls.XlsReadSheetHolder; * * @author Dan Zheng */ -public class DummyRecordHandler implements IgnorableXlsRecordHandler { +public class DummyRecordHandler extends AbstractXlsRecordHandler implements IgnorableXlsRecordHandler { @Override public void processRecord(XlsReadContext xlsReadContext, Record record) { XlsReadSheetHolder xlsReadSheetHolder = xlsReadContext.xlsReadSheetHolder(); @@ -27,7 +27,7 @@ public class DummyRecordHandler implements IgnorableXlsRecordHandler { LastCellOfRowDummyRecord lcrdr = (LastCellOfRowDummyRecord)record; xlsReadSheetHolder.setRowIndex(lcrdr.getRow()); xlsReadContext.readRowHolder(new ReadRowHolder(lcrdr.getRow(), xlsReadSheetHolder.getTempRowType(), - xlsReadContext.readSheetHolder().getGlobalConfiguration())); + xlsReadContext.readSheetHolder().getGlobalConfiguration(), xlsReadSheetHolder.getCellMap())); xlsReadContext.analysisEventProcessor().endRow(xlsReadContext); xlsReadSheetHolder.setCellMap(new LinkedHashMap()); } else if (record instanceof MissingCellDummyRecord) { diff --git a/src/main/java/com/alibaba/excel/analysis/v03/handlers/EofRecordHandler.java b/src/main/java/com/alibaba/excel/analysis/v03/handlers/EofRecordHandler.java index 4b1517b3..0ca7313e 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/handlers/EofRecordHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/handlers/EofRecordHandler.java @@ -10,7 +10,7 @@ import com.alibaba.excel.context.xls.XlsReadContext; * * @author Dan Zheng */ -public class EofRecordHandler implements IgnorableXlsRecordHandler { +public class EofRecordHandler extends AbstractXlsRecordHandler implements IgnorableXlsRecordHandler { @Override public void processRecord(XlsReadContext xlsReadContext, Record record) { diff --git a/src/main/java/com/alibaba/excel/analysis/v03/handlers/FormulaRecordHandler.java b/src/main/java/com/alibaba/excel/analysis/v03/handlers/FormulaRecordHandler.java index f04cdb77..004d9c67 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/handlers/FormulaRecordHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/handlers/FormulaRecordHandler.java @@ -21,7 +21,7 @@ import com.alibaba.excel.metadata.CellData; * * @author Dan Zheng */ -public class FormulaRecordHandler implements IgnorableXlsRecordHandler { +public class FormulaRecordHandler extends AbstractXlsRecordHandler implements IgnorableXlsRecordHandler { private static final Logger LOGGER = LoggerFactory.getLogger(FormulaRecordHandler.class); private static final String ERROR = "#VALUE!"; @@ -35,7 +35,7 @@ public class FormulaRecordHandler implements IgnorableXlsRecordHandler { CellType cellType = CellType.forInt(frec.getCachedResultType()); String formulaValue = null; try { - formulaValue = HSSFFormulaParser.toFormulaString(xlsReadContext.xlsReadWorkbookHolder().getHsffWorkbook(), + formulaValue = HSSFFormulaParser.toFormulaString(xlsReadContext.xlsReadWorkbookHolder().getHssfWorkbook(), frec.getParsedExpression()); } catch (Exception e) { LOGGER.debug("Get formula value error.", e); diff --git a/src/main/java/com/alibaba/excel/analysis/v03/handlers/HyperlinkRecordHandler.java b/src/main/java/com/alibaba/excel/analysis/v03/handlers/HyperlinkRecordHandler.java new file mode 100644 index 00000000..915abf61 --- /dev/null +++ b/src/main/java/com/alibaba/excel/analysis/v03/handlers/HyperlinkRecordHandler.java @@ -0,0 +1,30 @@ +package com.alibaba.excel.analysis.v03.handlers; + +import org.apache.poi.hssf.record.HyperlinkRecord; +import org.apache.poi.hssf.record.Record; + +import com.alibaba.excel.analysis.v03.IgnorableXlsRecordHandler; +import com.alibaba.excel.context.xls.XlsReadContext; +import com.alibaba.excel.enums.CellExtraTypeEnum; +import com.alibaba.excel.metadata.CellExtra; + +/** + * Record handler + * + * @author Dan Zheng + */ +public class HyperlinkRecordHandler extends AbstractXlsRecordHandler implements IgnorableXlsRecordHandler { + @Override + public boolean support(XlsReadContext xlsReadContext, Record record) { + return xlsReadContext.readWorkbookHolder().getExtraReadSet().contains(CellExtraTypeEnum.HYPERLINK); + } + + @Override + public void processRecord(XlsReadContext xlsReadContext, Record record) { + HyperlinkRecord hr = (HyperlinkRecord)record; + CellExtra cellExtra = new CellExtra(CellExtraTypeEnum.HYPERLINK, hr.getAddress(), hr.getFirstRow(), + hr.getFirstColumn(), hr.getLastRow(), hr.getLastColumn()); + xlsReadContext.xlsReadSheetHolder().setCellExtra(cellExtra); + xlsReadContext.analysisEventProcessor().extra(xlsReadContext); + } +} diff --git a/src/main/java/com/alibaba/excel/analysis/v03/handlers/IndexRecordHandler.java b/src/main/java/com/alibaba/excel/analysis/v03/handlers/IndexRecordHandler.java index de21da89..b95812eb 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/handlers/IndexRecordHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/handlers/IndexRecordHandler.java @@ -11,7 +11,7 @@ import com.alibaba.excel.context.xls.XlsReadContext; * * @author Jiaju Zhuang */ -public class IndexRecordHandler implements IgnorableXlsRecordHandler { +public class IndexRecordHandler extends AbstractXlsRecordHandler implements IgnorableXlsRecordHandler { @Override public void processRecord(XlsReadContext xlsReadContext, Record record) { if (xlsReadContext.readSheetHolder() == null) { diff --git a/src/main/java/com/alibaba/excel/analysis/v03/handlers/LabelRecordHandler.java b/src/main/java/com/alibaba/excel/analysis/v03/handlers/LabelRecordHandler.java index 1335ada3..4f63ab0c 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/handlers/LabelRecordHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/handlers/LabelRecordHandler.java @@ -13,7 +13,7 @@ import com.alibaba.excel.metadata.CellData; * * @author Dan Zheng */ -public class LabelRecordHandler implements IgnorableXlsRecordHandler { +public class LabelRecordHandler extends AbstractXlsRecordHandler implements IgnorableXlsRecordHandler { @Override public void processRecord(XlsReadContext xlsReadContext, Record record) { LabelRecord lrec = (LabelRecord)record; diff --git a/src/main/java/com/alibaba/excel/analysis/v03/handlers/LabelSstRecordHandler.java b/src/main/java/com/alibaba/excel/analysis/v03/handlers/LabelSstRecordHandler.java index 7979241e..7fb5cd0d 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/handlers/LabelSstRecordHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/handlers/LabelSstRecordHandler.java @@ -17,7 +17,7 @@ import com.alibaba.excel.metadata.CellData; * * @author Dan Zheng */ -public class LabelSstRecordHandler implements IgnorableXlsRecordHandler { +public class LabelSstRecordHandler extends AbstractXlsRecordHandler implements IgnorableXlsRecordHandler { @Override public void processRecord(XlsReadContext xlsReadContext, Record record) { diff --git a/src/main/java/com/alibaba/excel/analysis/v03/handlers/MergeCellsRecordHandler.java b/src/main/java/com/alibaba/excel/analysis/v03/handlers/MergeCellsRecordHandler.java new file mode 100644 index 00000000..4689f2b6 --- /dev/null +++ b/src/main/java/com/alibaba/excel/analysis/v03/handlers/MergeCellsRecordHandler.java @@ -0,0 +1,35 @@ +package com.alibaba.excel.analysis.v03.handlers; + +import org.apache.poi.hssf.record.MergeCellsRecord; +import org.apache.poi.hssf.record.Record; +import org.apache.poi.ss.util.CellRangeAddress; + +import com.alibaba.excel.analysis.v03.IgnorableXlsRecordHandler; +import com.alibaba.excel.context.xls.XlsReadContext; +import com.alibaba.excel.enums.CellExtraTypeEnum; +import com.alibaba.excel.metadata.CellExtra; + +/** + * Record handler + * + * @author Dan Zheng + */ +public class MergeCellsRecordHandler extends AbstractXlsRecordHandler implements IgnorableXlsRecordHandler { + + @Override + public boolean support(XlsReadContext xlsReadContext, Record record) { + return xlsReadContext.readWorkbookHolder().getExtraReadSet().contains(CellExtraTypeEnum.MERGE); + } + + @Override + public void processRecord(XlsReadContext xlsReadContext, Record record) { + MergeCellsRecord mcr = (MergeCellsRecord)record; + for (int i = 0; i < mcr.getNumAreas(); i++) { + CellRangeAddress cellRangeAddress = mcr.getAreaAt(i); + CellExtra cellExtra = new CellExtra(CellExtraTypeEnum.MERGE, null, cellRangeAddress.getFirstRow(), + cellRangeAddress.getFirstColumn(), cellRangeAddress.getLastRow(), cellRangeAddress.getLastColumn()); + xlsReadContext.xlsReadSheetHolder().setCellExtra(cellExtra); + xlsReadContext.analysisEventProcessor().extra(xlsReadContext); + } + } +} diff --git a/src/main/java/com/alibaba/excel/analysis/v03/handlers/NoteRecordHandler.java b/src/main/java/com/alibaba/excel/analysis/v03/handlers/NoteRecordHandler.java index 8c2993dc..6b6d803e 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/handlers/NoteRecordHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/handlers/NoteRecordHandler.java @@ -5,7 +5,7 @@ import org.apache.poi.hssf.record.Record; import com.alibaba.excel.analysis.v03.IgnorableXlsRecordHandler; import com.alibaba.excel.context.xls.XlsReadContext; -import com.alibaba.excel.enums.RowTypeEnum; +import com.alibaba.excel.enums.CellExtraTypeEnum; import com.alibaba.excel.metadata.CellExtra; /** @@ -13,17 +13,19 @@ import com.alibaba.excel.metadata.CellExtra; * * @author Dan Zheng */ -public class NoteRecordHandler implements IgnorableXlsRecordHandler { +public class NoteRecordHandler extends AbstractXlsRecordHandler implements IgnorableXlsRecordHandler { + + @Override + public boolean support(XlsReadContext xlsReadContext, Record record) { + return xlsReadContext.readWorkbookHolder().getExtraReadSet().contains(CellExtraTypeEnum.COMMENT); + } @Override public void processRecord(XlsReadContext xlsReadContext, Record record) { NoteRecord nr = (NoteRecord)record; - String note = xlsReadContext.xlsReadSheetHolder().getObjectCacheMap().get(nr.getShapeId()); - CellExtra cellExtra = new CellExtra(); - cellExtra.setRowIndex(nr.getRow()); - cellExtra.setRowIndex(nr.getColumn()); - cellExtra.setNote(note); - xlsReadContext.xlsReadSheetHolder().getCellMap().put(nr.getColumn(), cellExtra); - xlsReadContext.xlsReadSheetHolder().setTempRowType(RowTypeEnum.EXTRA); + String text = xlsReadContext.xlsReadSheetHolder().getObjectCacheMap().get(nr.getShapeId()); + CellExtra cellExtra = new CellExtra(CellExtraTypeEnum.COMMENT, text, nr.getRow(), nr.getColumn()); + xlsReadContext.xlsReadSheetHolder().setCellExtra(cellExtra); + xlsReadContext.analysisEventProcessor().extra(xlsReadContext); } } diff --git a/src/main/java/com/alibaba/excel/analysis/v03/handlers/NumberRecordHandler.java b/src/main/java/com/alibaba/excel/analysis/v03/handlers/NumberRecordHandler.java index 5e2fbca4..50608095 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/handlers/NumberRecordHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/handlers/NumberRecordHandler.java @@ -16,7 +16,7 @@ import com.alibaba.excel.metadata.CellData; * * @author Dan Zheng */ -public class NumberRecordHandler implements IgnorableXlsRecordHandler { +public class NumberRecordHandler extends AbstractXlsRecordHandler implements IgnorableXlsRecordHandler { @Override public void processRecord(XlsReadContext xlsReadContext, Record record) { diff --git a/src/main/java/com/alibaba/excel/analysis/v03/handlers/ObjRecordHandler.java b/src/main/java/com/alibaba/excel/analysis/v03/handlers/ObjRecordHandler.java index e8a0cc1b..97bcd20f 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/handlers/ObjRecordHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/handlers/ObjRecordHandler.java @@ -13,7 +13,7 @@ import com.alibaba.excel.context.xls.XlsReadContext; * * @author Jiaju Zhuang */ -public class ObjRecordHandler implements IgnorableXlsRecordHandler { +public class ObjRecordHandler extends AbstractXlsRecordHandler implements IgnorableXlsRecordHandler { @Override public void processRecord(XlsReadContext xlsReadContext, Record record) { ObjRecord or = (ObjRecord)record; diff --git a/src/main/java/com/alibaba/excel/analysis/v03/handlers/RkRecordHandler.java b/src/main/java/com/alibaba/excel/analysis/v03/handlers/RkRecordHandler.java index 22ba166b..d8317b37 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/handlers/RkRecordHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/handlers/RkRecordHandler.java @@ -12,7 +12,7 @@ import com.alibaba.excel.metadata.CellData; * * @author Dan Zheng */ -public class RkRecordHandler implements IgnorableXlsRecordHandler { +public class RkRecordHandler extends AbstractXlsRecordHandler implements IgnorableXlsRecordHandler { @Override public void processRecord(XlsReadContext xlsReadContext, Record record) { diff --git a/src/main/java/com/alibaba/excel/analysis/v03/handlers/SstRecordHandler.java b/src/main/java/com/alibaba/excel/analysis/v03/handlers/SstRecordHandler.java index c11ff4c0..35727b66 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/handlers/SstRecordHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/handlers/SstRecordHandler.java @@ -12,7 +12,7 @@ import com.alibaba.excel.context.xls.XlsReadContext; * * @author Dan Zheng */ -public class SstRecordHandler implements IgnorableXlsRecordHandler { +public class SstRecordHandler extends AbstractXlsRecordHandler implements IgnorableXlsRecordHandler { @Override public void processRecord(XlsReadContext xlsReadContext, Record record) { xlsReadContext.readWorkbookHolder().setReadCache(new XlsCache((SSTRecord)record)); diff --git a/src/main/java/com/alibaba/excel/analysis/v03/handlers/StringRecordHandler.java b/src/main/java/com/alibaba/excel/analysis/v03/handlers/StringRecordHandler.java index e4c40ecf..3b95cfdb 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/handlers/StringRecordHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/handlers/StringRecordHandler.java @@ -15,7 +15,7 @@ import com.alibaba.excel.read.metadata.holder.xls.XlsReadSheetHolder; * * @author Dan Zheng */ -public class StringRecordHandler implements IgnorableXlsRecordHandler { +public class StringRecordHandler extends AbstractXlsRecordHandler implements IgnorableXlsRecordHandler { private static final Logger LOGGER = LoggerFactory.getLogger(StringRecordHandler.class); @Override diff --git a/src/main/java/com/alibaba/excel/analysis/v03/handlers/TextObjectRecordHandler.java b/src/main/java/com/alibaba/excel/analysis/v03/handlers/TextObjectRecordHandler.java index 1ee3543b..949498f0 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/handlers/TextObjectRecordHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/handlers/TextObjectRecordHandler.java @@ -7,6 +7,7 @@ import org.slf4j.LoggerFactory; import com.alibaba.excel.analysis.v03.IgnorableXlsRecordHandler; import com.alibaba.excel.context.xls.XlsReadContext; +import com.alibaba.excel.enums.CellExtraTypeEnum; import com.alibaba.excel.read.metadata.holder.xls.XlsReadSheetHolder; /** @@ -14,9 +15,14 @@ import com.alibaba.excel.read.metadata.holder.xls.XlsReadSheetHolder; * * @author Jiaju Zhuang */ -public class TextObjectRecordHandler implements IgnorableXlsRecordHandler { +public class TextObjectRecordHandler extends AbstractXlsRecordHandler implements IgnorableXlsRecordHandler { private static final Logger LOGGER = LoggerFactory.getLogger(TextObjectRecordHandler.class); + @Override + public boolean support(XlsReadContext xlsReadContext, Record record) { + return xlsReadContext.readWorkbookHolder().getExtraReadSet().contains(CellExtraTypeEnum.COMMENT); + } + @Override public void processRecord(XlsReadContext xlsReadContext, Record record) { TextObjectRecord tor = (TextObjectRecord)record; diff --git a/src/main/java/com/alibaba/excel/analysis/v07/XlsxHandlerFactory.java b/src/main/java/com/alibaba/excel/analysis/v07/XlsxHandlerFactory.java deleted file mode 100644 index 1785036a..00000000 --- a/src/main/java/com/alibaba/excel/analysis/v07/XlsxHandlerFactory.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.alibaba.excel.analysis.v07; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.poi.xssf.model.StylesTable; - -import com.alibaba.excel.analysis.v07.handlers.CountRowCellHandler; -import com.alibaba.excel.analysis.v07.handlers.DefaultCellHandler; -import com.alibaba.excel.analysis.v07.handlers.ProcessResultCellHandler; -import com.alibaba.excel.analysis.v07.handlers.XlsxCellHandler; -import com.alibaba.excel.context.AnalysisContext; - -/** - * Build handler - * - * @author Dan Zheng - */ -public class XlsxHandlerFactory { - public static List buildCellHandlers(AnalysisContext analysisContext, StylesTable stylesTable) { - List result = new ArrayList(); - result.add(new CountRowCellHandler(analysisContext)); - DefaultCellHandler defaultCellHandler = new DefaultCellHandler(analysisContext, stylesTable); - result.add(defaultCellHandler); - result.add(new ProcessResultCellHandler(analysisContext, defaultCellHandler)); - return result; - } -} diff --git a/src/main/java/com/alibaba/excel/analysis/v07/XlsxRowResultHolder.java b/src/main/java/com/alibaba/excel/analysis/v07/XlsxRowResultHolder.java deleted file mode 100644 index d13da731..00000000 --- a/src/main/java/com/alibaba/excel/analysis/v07/XlsxRowResultHolder.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.alibaba.excel.analysis.v07; - -import java.util.Map; - -import com.alibaba.excel.metadata.CellData; - -/** - * Result holder - * - * @author jipengfei - */ -public interface XlsxRowResultHolder { - /** - * Clear Result - */ - void clearResult(); - - /** - * Append current 'cellValue' - * - * @param ch - * @param start - * @param length - */ - void appendCurrentCellValue(char[] ch, int start, int length); - - /** - * Get row content - * - * @return - */ - Map getCurRowContent(); -} diff --git a/src/main/java/com/alibaba/excel/analysis/v07/XlsxSaxAnalyser.java b/src/main/java/com/alibaba/excel/analysis/v07/XlsxSaxAnalyser.java index 205b6480..a0a9af0e 100644 --- a/src/main/java/com/alibaba/excel/analysis/v07/XlsxSaxAnalyser.java +++ b/src/main/java/com/alibaba/excel/analysis/v07/XlsxSaxAnalyser.java @@ -15,7 +15,10 @@ import javax.xml.parsers.SAXParserFactory; import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.PackageAccess; import org.apache.poi.openxml4j.opc.PackagePart; +import org.apache.poi.ss.util.CellAddress; import org.apache.poi.xssf.eventusermodel.XSSFReader; +import org.apache.poi.xssf.model.CommentsTable; +import org.apache.poi.xssf.usermodel.XSSFComment; import org.apache.poi.xssf.usermodel.XSSFRelation; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorkbook; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorkbookPr; @@ -29,7 +32,9 @@ import com.alibaba.excel.analysis.v07.handlers.sax.SharedStringsTableHandler; import com.alibaba.excel.analysis.v07.handlers.sax.XlsxRowHandler; import com.alibaba.excel.cache.ReadCache; import com.alibaba.excel.context.xlsx.XlsxReadContext; +import com.alibaba.excel.enums.CellExtraTypeEnum; import com.alibaba.excel.exception.ExcelAnalysisException; +import com.alibaba.excel.metadata.CellExtra; import com.alibaba.excel.read.metadata.ReadSheet; import com.alibaba.excel.read.metadata.holder.xlsx.XlsxReadWorkbookHolder; import com.alibaba.excel.util.CollectionUtils; @@ -45,6 +50,10 @@ public class XlsxSaxAnalyser implements ExcelReadExecutor { private XlsxReadContext xlsxReadContext; private List sheetList; private Map sheetMap; + /** + * excel comments key: sheetNo value: CommentsTable + */ + private Map commentsTableMap; public XlsxSaxAnalyser(XlsxReadContext xlsxReadContext, InputStream decryptedStream) throws Exception { this.xlsxReadContext = xlsxReadContext; @@ -72,7 +81,8 @@ public class XlsxSaxAnalyser implements ExcelReadExecutor { xlsxReadWorkbookHolder.setStylesTable(xssfReader.getStylesTable()); sheetList = new ArrayList(); sheetMap = new HashMap(); - XSSFReader.SheetIterator ite = (XSSFReader.SheetIterator) xssfReader.getSheetsData(); + commentsTableMap = new HashMap(); + XSSFReader.SheetIterator ite = (XSSFReader.SheetIterator)xssfReader.getSheetsData(); int index = 0; if (!ite.hasNext()) { throw new ExcelAnalysisException("Can not find any sheet!"); @@ -81,11 +91,18 @@ public class XlsxSaxAnalyser implements ExcelReadExecutor { InputStream inputStream = ite.next(); sheetList.add(new ReadSheet(index, ite.getSheetName())); sheetMap.put(index, inputStream); + if (xlsxReadContext.readWorkbookHolder().getExtraReadSet().contains(CellExtraTypeEnum.COMMENT)) { + CommentsTable commentsTable = ite.getSheetComments(); + if (null != commentsTable) { + commentsTableMap.put(index, commentsTable); + } + } index++; } } - private void defaultReadCache(XlsxReadWorkbookHolder xlsxReadWorkbookHolder, PackagePart sharedStringsTablePackagePart) { + private void defaultReadCache(XlsxReadWorkbookHolder xlsxReadWorkbookHolder, + PackagePart sharedStringsTablePackagePart) { ReadCache readCache = xlsxReadWorkbookHolder.getReadCacheSelector().readCache(sharedStringsTablePackagePart); xlsxReadWorkbookHolder.setReadCache(readCache); readCache.init(xlsxReadContext); @@ -108,7 +125,7 @@ public class XlsxSaxAnalyser implements ExcelReadExecutor { } private void analysisSharedStringsTable(InputStream sharedStringsTableInputStream, - XlsxReadWorkbookHolder xlsxReadWorkbookHolder) throws Exception { + XlsxReadWorkbookHolder xlsxReadWorkbookHolder) throws Exception { ContentHandler handler = new SharedStringsTableHandler(xlsxReadWorkbookHolder.getReadCache()); parseXmlSource(sharedStringsTableInputStream, handler); xlsxReadWorkbookHolder.getReadCache().putFinished(); @@ -182,9 +199,28 @@ public class XlsxSaxAnalyser implements ExcelReadExecutor { 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); } } } + + private void readComments(ReadSheet readSheet) { + if (!xlsxReadContext.readWorkbookHolder().getExtraReadSet().contains(CellExtraTypeEnum.COMMENT)) { + return; + } + CommentsTable commentsTable = commentsTableMap.get(readSheet.getSheetNo()); + if (commentsTable == null) { + return; + } + Map cellComments = commentsTable.getCellComments(); + for (XSSFComment xssfComment : cellComments.values()) { + CellExtra cellExtra = new CellExtra(CellExtraTypeEnum.COMMENT, xssfComment.getString().toString(), + xssfComment.getRow(), xssfComment.getColumn()); + xlsxReadContext.readSheetHolder().setCellExtra(cellExtra); + xlsxReadContext.analysisEventProcessor().extra(xlsxReadContext); + } + } } diff --git a/src/main/java/com/alibaba/excel/analysis/v07/handlers/AbstractCellValueTagHandler.java b/src/main/java/com/alibaba/excel/analysis/v07/handlers/AbstractCellValueTagHandler.java new file mode 100644 index 00000000..0c60d665 --- /dev/null +++ b/src/main/java/com/alibaba/excel/analysis/v07/handlers/AbstractCellValueTagHandler.java @@ -0,0 +1,64 @@ +package com.alibaba.excel.analysis.v07.handlers; + +import java.math.BigDecimal; + +import com.alibaba.excel.context.xlsx.XlsxReadContext; +import com.alibaba.excel.enums.CellDataTypeEnum; +import com.alibaba.excel.metadata.CellData; +import com.alibaba.excel.read.metadata.holder.xlsx.XlsxReadSheetHolder; +import com.alibaba.excel.util.BooleanUtils; + +/** + * Cell Value Handler + * + * @author jipengfei + */ +public abstract class AbstractCellValueTagHandler extends AbstractXlsxTagHandler { + + @Override + public void endElement(XlsxReadContext xlsxReadContext, String name) { + XlsxReadSheetHolder xlsxReadSheetHolder = xlsxReadContext.xlsxReadSheetHolder(); + CellData tempCellData = xlsxReadSheetHolder.getTempCellData(); + StringBuilder tempData = xlsxReadSheetHolder.getTempData(); + CellDataTypeEnum oldType = tempCellData.getType(); + switch (oldType) { + case DIRECT_STRING: + case STRING: + case ERROR: + tempCellData.setStringValue(tempData.toString()); + break; + case BOOLEAN: + tempCellData.setBooleanValue(BooleanUtils.valueOf(tempData.toString())); + break; + case NUMBER: + case EMPTY: + tempCellData.setType(CellDataTypeEnum.NUMBER); + tempCellData.setNumberValue(new BigDecimal(tempData.toString())); + break; + default: + throw new IllegalStateException("Cannot set values now"); + } + + // set string value + setStringValue(xlsxReadContext); + + if (tempCellData.getStringValue() != null + && xlsxReadContext.currentReadHolder().globalConfiguration().getAutoTrim()) { + tempCellData.setStringValue(tempCellData.getStringValue()); + } + + tempCellData.checkEmpty(); + xlsxReadSheetHolder.getCellMap().put(xlsxReadSheetHolder.getColumnIndex(), tempCellData); + } + + @Override + public void characters(XlsxReadContext xlsxReadContext, char[] ch, int start, int length) { + xlsxReadContext.xlsxReadSheetHolder().getTempData().append(ch, start, length); + } + + /** + * Set string value. + */ + protected abstract void setStringValue(XlsxReadContext xlsxReadContext); + +} diff --git a/src/main/java/com/alibaba/excel/analysis/v07/handlers/AbstractXlsxTagHandler.java b/src/main/java/com/alibaba/excel/analysis/v07/handlers/AbstractXlsxTagHandler.java new file mode 100644 index 00000000..169fe00e --- /dev/null +++ b/src/main/java/com/alibaba/excel/analysis/v07/handlers/AbstractXlsxTagHandler.java @@ -0,0 +1,32 @@ +package com.alibaba.excel.analysis.v07.handlers; + +import org.xml.sax.Attributes; + +import com.alibaba.excel.context.xlsx.XlsxReadContext; + +/** + * Abstract tag handler + * + * @author Jiaju Zhuang + */ +public abstract class AbstractXlsxTagHandler implements XlsxTagHandler { + @Override + public boolean support(XlsxReadContext xlsxReadContext) { + return true; + } + + @Override + public void startElement(XlsxReadContext xlsxReadContext, String name, Attributes attributes) { + + } + + @Override + public void endElement(XlsxReadContext xlsxReadContext, String name) { + + } + + @Override + public void characters(XlsxReadContext xlsxReadContext, char[] ch, int start, int length) { + + } +} diff --git a/src/main/java/com/alibaba/excel/analysis/v07/handlers/CellFormulaTagHandler.java b/src/main/java/com/alibaba/excel/analysis/v07/handlers/CellFormulaTagHandler.java new file mode 100644 index 00000000..e153a3b1 --- /dev/null +++ b/src/main/java/com/alibaba/excel/analysis/v07/handlers/CellFormulaTagHandler.java @@ -0,0 +1,32 @@ +package com.alibaba.excel.analysis.v07.handlers; + +import org.xml.sax.Attributes; + +import com.alibaba.excel.context.xlsx.XlsxReadContext; +import com.alibaba.excel.read.metadata.holder.xlsx.XlsxReadSheetHolder; + +/** + * Cell Handler + * + * @author jipengfei + */ +public class CellFormulaTagHandler extends AbstractXlsxTagHandler { + + @Override + public void startElement(XlsxReadContext xlsxReadContext, String name, Attributes attributes) { + XlsxReadSheetHolder xlsxReadSheetHolder = xlsxReadContext.xlsxReadSheetHolder(); + xlsxReadSheetHolder.getTempCellData().setFormula(Boolean.TRUE); + xlsxReadSheetHolder.setTempFormula(new StringBuilder()); + } + + @Override + public void endElement(XlsxReadContext xlsxReadContext, String name) { + XlsxReadSheetHolder xlsxReadSheetHolder = xlsxReadContext.xlsxReadSheetHolder(); + xlsxReadSheetHolder.getTempCellData().setFormulaValue(xlsxReadSheetHolder.getTempFormula().toString()); + } + + @Override + public void characters(XlsxReadContext xlsxReadContext, char[] ch, int start, int length) { + xlsxReadContext.xlsxReadSheetHolder().getTempFormula().append(ch, start, length); + } +} diff --git a/src/main/java/com/alibaba/excel/analysis/v07/handlers/CellInlineStringValueTagHandler.java b/src/main/java/com/alibaba/excel/analysis/v07/handlers/CellInlineStringValueTagHandler.java new file mode 100644 index 00000000..277348a7 --- /dev/null +++ b/src/main/java/com/alibaba/excel/analysis/v07/handlers/CellInlineStringValueTagHandler.java @@ -0,0 +1,23 @@ +package com.alibaba.excel.analysis.v07.handlers; + +import org.apache.poi.xssf.usermodel.XSSFRichTextString; + +import com.alibaba.excel.context.xlsx.XlsxReadContext; +import com.alibaba.excel.metadata.CellData; + +/** + * Cell inline string value handler + * + * @author jipengfei + */ +public class CellInlineStringValueTagHandler extends AbstractCellValueTagHandler { + + @Override + protected void setStringValue(XlsxReadContext xlsxReadContext) { + // This is a special form of string + CellData tempCellData = xlsxReadContext.xlsxReadSheetHolder().getTempCellData(); + XSSFRichTextString richTextString = new XSSFRichTextString(tempCellData.getStringValue()); + tempCellData.setStringValue(richTextString.toString()); + } + +} diff --git a/src/main/java/com/alibaba/excel/analysis/v07/handlers/CellTagHandler.java b/src/main/java/com/alibaba/excel/analysis/v07/handlers/CellTagHandler.java new file mode 100644 index 00000000..8ef07865 --- /dev/null +++ b/src/main/java/com/alibaba/excel/analysis/v07/handlers/CellTagHandler.java @@ -0,0 +1,53 @@ +package com.alibaba.excel.analysis.v07.handlers; + +import static com.alibaba.excel.constant.ExcelXmlConstants.CELL_DATA_FORMAT_TAG; +import static com.alibaba.excel.constant.ExcelXmlConstants.CELL_VALUE_TYPE_TAG; + +import org.apache.poi.xssf.usermodel.XSSFCellStyle; +import org.xml.sax.Attributes; + +import com.alibaba.excel.constant.BuiltinFormats; +import com.alibaba.excel.constant.ExcelXmlConstants; +import com.alibaba.excel.context.xlsx.XlsxReadContext; +import com.alibaba.excel.enums.CellDataTypeEnum; +import com.alibaba.excel.metadata.CellData; +import com.alibaba.excel.read.metadata.holder.xlsx.XlsxReadSheetHolder; +import com.alibaba.excel.util.PositionUtils; + +/** + * Cell Handler + * + * @author jipengfei + */ +public class CellTagHandler extends AbstractXlsxTagHandler { + + @Override + public void startElement(XlsxReadContext xlsxReadContext, String name, Attributes attributes) { + XlsxReadSheetHolder xlsxReadSheetHolder = xlsxReadContext.xlsxReadSheetHolder(); + xlsxReadSheetHolder.setColumnIndex(PositionUtils.getCol(attributes.getValue(ExcelXmlConstants.POSITION))); + + // t="s" ,it's means String + // t="str" ,it's means String,but does not need to be read in the 'sharedStrings.xml' + // t="inlineStr" ,it's means String + // t="b" ,it's means Boolean + // t="e" ,it's means Error + // t="n" ,it's means Number + // t is null ,it's means Empty or Number + CellDataTypeEnum type = CellDataTypeEnum.buildFromCellType(attributes.getValue(CELL_VALUE_TYPE_TAG)); + xlsxReadSheetHolder.setTempCellData(new CellData(type)); + xlsxReadSheetHolder.setTempData(new StringBuilder()); + + // Put in data transformation information + String dateFormatIndex = attributes.getValue(CELL_DATA_FORMAT_TAG); + if (dateFormatIndex != null) { + int dateFormatIndexInteger = Integer.parseInt(dateFormatIndex); + XSSFCellStyle xssfCellStyle = + xlsxReadContext.xlsxReadWorkbookHolder().getStylesTable().getStyleAt(dateFormatIndexInteger); + int dataFormat = xssfCellStyle.getDataFormat(); + xlsxReadSheetHolder.getTempCellData().setDataFormat(dataFormat); + xlsxReadSheetHolder.getTempCellData().setDataFormatString(BuiltinFormats.getBuiltinFormat(dataFormat, + xssfCellStyle.getDataFormatString(), xlsxReadSheetHolder.getGlobalConfiguration().getLocale())); + } + } + +} diff --git a/src/main/java/com/alibaba/excel/analysis/v07/handlers/CellValueTagHandler.java b/src/main/java/com/alibaba/excel/analysis/v07/handlers/CellValueTagHandler.java new file mode 100644 index 00000000..09c9264e --- /dev/null +++ b/src/main/java/com/alibaba/excel/analysis/v07/handlers/CellValueTagHandler.java @@ -0,0 +1,34 @@ +package com.alibaba.excel.analysis.v07.handlers; + +import com.alibaba.excel.context.xlsx.XlsxReadContext; +import com.alibaba.excel.enums.CellDataTypeEnum; +import com.alibaba.excel.metadata.CellData; + +/** + * Cell Value Handler + * + * @author jipengfei + */ +public class CellValueTagHandler extends AbstractCellValueTagHandler { + + @Override + protected void setStringValue(XlsxReadContext xlsxReadContext) { + // Have to go "sharedStrings.xml" and get it + CellData tempCellData = xlsxReadContext.xlsxReadSheetHolder().getTempCellData(); + switch (tempCellData.getType()) { + case STRING: + String stringValue = xlsxReadContext.readWorkbookHolder().getReadCache() + .get(Integer.valueOf(tempCellData.getStringValue())); + if (stringValue != null && xlsxReadContext.currentReadHolder().globalConfiguration().getAutoTrim()) { + stringValue = stringValue.trim(); + } + tempCellData.setStringValue(stringValue); + break; + case DIRECT_STRING: + tempCellData.setType(CellDataTypeEnum.STRING); + break; + default: + } + } + +} diff --git a/src/main/java/com/alibaba/excel/analysis/v07/handlers/CountRowCellHandler.java b/src/main/java/com/alibaba/excel/analysis/v07/handlers/CountTagHandler.java similarity index 68% rename from src/main/java/com/alibaba/excel/analysis/v07/handlers/CountRowCellHandler.java rename to src/main/java/com/alibaba/excel/analysis/v07/handlers/CountTagHandler.java index dbc0a7e4..c1eb3233 100644 --- a/src/main/java/com/alibaba/excel/analysis/v07/handlers/CountRowCellHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v07/handlers/CountTagHandler.java @@ -11,19 +11,14 @@ import com.alibaba.excel.context.xlsx.XlsxReadContext; * * @author jipengfei */ -public class CountRowCellHandler implements XlsxCellHandler { - +public class CountTagHandler extends AbstractXlsxTagHandler { @Override - public void startHandle(XlsxReadContext xlsxReadContext, String name, Attributes attributes) { + public void startElement(XlsxReadContext xlsxReadContext, String name, Attributes attributes) { String d = attributes.getValue(DIMENSION_REF); String totalStr = d.substring(d.indexOf(":") + 1, d.length()); String c = totalStr.toUpperCase().replaceAll("[A-Z]", ""); xlsxReadContext.readSheetHolder().setApproximateTotalRowNumber(Integer.parseInt(c)); } - @Override - public void endHandle(XlsxReadContext xlsxReadContext, String name) { - } - } diff --git a/src/main/java/com/alibaba/excel/analysis/v07/handlers/DefaultCellHandler.java b/src/main/java/com/alibaba/excel/analysis/v07/handlers/DefaultCellHandler.java deleted file mode 100644 index baa3990d..00000000 --- a/src/main/java/com/alibaba/excel/analysis/v07/handlers/DefaultCellHandler.java +++ /dev/null @@ -1,169 +0,0 @@ -package com.alibaba.excel.analysis.v07.handlers; - -import static com.alibaba.excel.constant.ExcelXmlConstants.CELL_DATA_FORMAT_TAG; -import static com.alibaba.excel.constant.ExcelXmlConstants.CELL_FORMULA_TAG; -import static com.alibaba.excel.constant.ExcelXmlConstants.CELL_INLINE_STRING_VALUE_TAG; -import static com.alibaba.excel.constant.ExcelXmlConstants.CELL_TAG; -import static com.alibaba.excel.constant.ExcelXmlConstants.CELL_VALUE_TAG; -import static com.alibaba.excel.constant.ExcelXmlConstants.CELL_VALUE_TYPE_TAG; - -import java.math.BigDecimal; -import java.util.Deque; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.Map; - -import org.apache.poi.xssf.usermodel.XSSFCellStyle; -import org.apache.poi.xssf.usermodel.XSSFRichTextString; -import org.xml.sax.Attributes; - -import com.alibaba.excel.analysis.v07.XlsxRowResultHolder; -import com.alibaba.excel.constant.BuiltinFormats; -import com.alibaba.excel.constant.ExcelXmlConstants; -import com.alibaba.excel.context.AnalysisContext; -import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; -import com.alibaba.excel.util.BooleanUtils; -import com.alibaba.excel.util.PositionUtils; - -/** - * Cell Handler - * - * @author jipengfei - */ -public class DefaultCellHandler implements XlsxCellHandler, XlsxRowResultHolder { - private final AnalysisContext analysisContext; - private Deque currentTagDeque = new LinkedList(); - private int curCol; - private Map curRowContent = new LinkedHashMap(); - private CellData currentCellData; - private StringBuilder dataStringBuilder; - private StringBuilder formulaStringBuilder; - - @Override - public void clearResult() { - curRowContent = new LinkedHashMap(); - } - - @Override - public boolean support(String name) { - return CELL_VALUE_TAG.equals(name) || CELL_FORMULA_TAG.equals(name) || CELL_INLINE_STRING_VALUE_TAG.equals(name) - || CELL_TAG.equals(name); - } - - @Override - public void startHandle(String name, Attributes attributes) { - currentTagDeque.push(name); - // start a cell - if (CELL_TAG.equals(name)) { - curCol = PositionUtils.getCol(attributes.getValue(ExcelXmlConstants.POSITION)); - - // t="s" ,it's means String - // t="str" ,it's means String,but does not need to be read in the 'sharedStrings.xml' - // t="inlineStr" ,it's means String - // t="b" ,it's means Boolean - // t="e" ,it's means Error - // t="n" ,it's means Number - // t is null ,it's means Empty or Number - CellDataTypeEnum type = CellDataTypeEnum.buildFromCellType(attributes.getValue(CELL_VALUE_TYPE_TAG)); - currentCellData = new CellData(type); - dataStringBuilder = new StringBuilder(); - - // Put in data transformation information - String dateFormatIndex = attributes.getValue(CELL_DATA_FORMAT_TAG); - if (dateFormatIndex != null) { - int dateFormatIndexInteger = Integer.parseInt(dateFormatIndex); - XSSFCellStyle xssfCellStyle = stylesTable.getStyleAt(dateFormatIndexInteger); - int dataFormat = xssfCellStyle.getDataFormat(); - currentCellData.setDataFormat(dataFormat); - currentCellData.setDataFormatString( - BuiltinFormats.getBuiltinFormat(dataFormat, xssfCellStyle.getDataFormatString(), - analysisContext.readSheetHolder().getGlobalConfiguration().getLocale())); - } - } - // cell is formula - if (CELL_FORMULA_TAG.equals(name)) { - currentCellData.setFormula(Boolean.TRUE); - formulaStringBuilder = new StringBuilder(); - } - } - - @Override - public void endHandle(String name) { - currentTagDeque.pop(); - // cell is formula - if (CELL_FORMULA_TAG.equals(name)) { - currentCellData.setFormulaValue(formulaStringBuilder.toString()); - return; - } - if (CELL_VALUE_TAG.equals(name) || CELL_INLINE_STRING_VALUE_TAG.equals(name)) { - CellDataTypeEnum oldType = currentCellData.getType(); - switch (oldType) { - case DIRECT_STRING: - case STRING: - case ERROR: - currentCellData.setStringValue(dataStringBuilder.toString()); - break; - case BOOLEAN: - currentCellData.setBooleanValue(BooleanUtils.valueOf(dataStringBuilder.toString())); - break; - case NUMBER: - case EMPTY: - currentCellData.setType(CellDataTypeEnum.NUMBER); - currentCellData.setNumberValue(new BigDecimal(dataStringBuilder.toString())); - break; - default: - throw new IllegalStateException("Cannot set values now"); - } - - if (CELL_VALUE_TAG.equals(name)) { - // Have to go "sharedStrings.xml" and get it - if (currentCellData.getType() == CellDataTypeEnum.STRING) { - String stringValue = analysisContext.readWorkbookHolder().getReadCache() - .get(Integer.valueOf(currentCellData.getStringValue())); - if (stringValue != null - && analysisContext.currentReadHolder().globalConfiguration().getAutoTrim()) { - stringValue = stringValue.trim(); - } - currentCellData.setStringValue(stringValue); - } else if (currentCellData.getType() == CellDataTypeEnum.DIRECT_STRING) { - currentCellData.setType(CellDataTypeEnum.STRING); - } - } - // This is a special form of string - if (CELL_INLINE_STRING_VALUE_TAG.equals(name)) { - XSSFRichTextString richTextString = new XSSFRichTextString(currentCellData.getStringValue()); - String stringValue = richTextString.toString(); - if (stringValue != null && analysisContext.currentReadHolder().globalConfiguration().getAutoTrim()) { - stringValue = stringValue.trim(); - } - currentCellData.setStringValue(stringValue); - } - - currentCellData.checkEmpty(); - curRowContent.put(curCol, currentCellData); - } - } - - @Override - public void appendCurrentCellValue(char[] ch, int start, int length) { - String currentTag = currentTagDeque.peek(); - if (currentTag == null) { - return; - } - if (CELL_FORMULA_TAG.equals(currentTag)) { - formulaStringBuilder.append(ch, start, length); - return; - } - if (!CELL_VALUE_TAG.equals(currentTag) && !CELL_INLINE_STRING_VALUE_TAG.equals(currentTag)) { - return; - } - dataStringBuilder.append(ch, start, length); - } - - @Override - public Map getCurRowContent() { - return curRowContent; - } - -} diff --git a/src/main/java/com/alibaba/excel/analysis/v07/handlers/HyperlinkTagHandler.java b/src/main/java/com/alibaba/excel/analysis/v07/handlers/HyperlinkTagHandler.java new file mode 100644 index 00000000..ee0154e7 --- /dev/null +++ b/src/main/java/com/alibaba/excel/analysis/v07/handlers/HyperlinkTagHandler.java @@ -0,0 +1,35 @@ +package com.alibaba.excel.analysis.v07.handlers; + +import org.xml.sax.Attributes; + +import com.alibaba.excel.constant.ExcelXmlConstants; +import com.alibaba.excel.context.xlsx.XlsxReadContext; +import com.alibaba.excel.enums.CellExtraTypeEnum; +import com.alibaba.excel.metadata.CellExtra; +import com.alibaba.excel.util.StringUtils; + +/** + * Cell Handler + * + * @author Jiaju Zhuang + */ +public class HyperlinkTagHandler extends AbstractXlsxTagHandler { + + @Override + public boolean support(XlsxReadContext xlsxReadContext) { + return xlsxReadContext.readWorkbookHolder().getExtraReadSet().contains(CellExtraTypeEnum.HYPERLINK); + } + + @Override + public void startElement(XlsxReadContext xlsxReadContext, String name, Attributes attributes) { + String ref = attributes.getValue(ExcelXmlConstants.ATTRIBUTE_REF); + String location = attributes.getValue(ExcelXmlConstants.ATTRIBUTE_LOCATION); + if (StringUtils.isEmpty(ref)) { + return; + } + CellExtra cellExtra = new CellExtra(CellExtraTypeEnum.HYPERLINK, location, ref); + xlsxReadContext.readSheetHolder().setCellExtra(cellExtra); + xlsxReadContext.analysisEventProcessor().extra(xlsxReadContext); + } + +} diff --git a/src/main/java/com/alibaba/excel/analysis/v07/handlers/MergeCellTagHandler.java b/src/main/java/com/alibaba/excel/analysis/v07/handlers/MergeCellTagHandler.java new file mode 100644 index 00000000..8b0fa041 --- /dev/null +++ b/src/main/java/com/alibaba/excel/analysis/v07/handlers/MergeCellTagHandler.java @@ -0,0 +1,34 @@ +package com.alibaba.excel.analysis.v07.handlers; + +import org.xml.sax.Attributes; + +import com.alibaba.excel.constant.ExcelXmlConstants; +import com.alibaba.excel.context.xlsx.XlsxReadContext; +import com.alibaba.excel.enums.CellExtraTypeEnum; +import com.alibaba.excel.metadata.CellExtra; +import com.alibaba.excel.util.StringUtils; + +/** + * Cell Handler + * + * @author Jiaju Zhuang + */ +public class MergeCellTagHandler extends AbstractXlsxTagHandler { + + @Override + public boolean support(XlsxReadContext xlsxReadContext) { + return xlsxReadContext.readWorkbookHolder().getExtraReadSet().contains(CellExtraTypeEnum.MERGE); + } + + @Override + public void startElement(XlsxReadContext xlsxReadContext, String name, Attributes attributes) { + String ref = attributes.getValue(ExcelXmlConstants.ATTRIBUTE_REF); + if (StringUtils.isEmpty(ref)) { + return; + } + CellExtra cellExtra = new CellExtra(CellExtraTypeEnum.MERGE, null, ref); + xlsxReadContext.readSheetHolder().setCellExtra(cellExtra); + xlsxReadContext.analysisEventProcessor().extra(xlsxReadContext); + } + +} diff --git a/src/main/java/com/alibaba/excel/analysis/v07/handlers/ProcessResultCellHandler.java b/src/main/java/com/alibaba/excel/analysis/v07/handlers/ProcessResultCellHandler.java deleted file mode 100644 index 51a71231..00000000 --- a/src/main/java/com/alibaba/excel/analysis/v07/handlers/ProcessResultCellHandler.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.alibaba.excel.analysis.v07.handlers; - -import org.xml.sax.Attributes; - -import com.alibaba.excel.constant.ExcelXmlConstants; -import com.alibaba.excel.context.xlsx.XlsxReadContext; -import com.alibaba.excel.enums.RowTypeEnum; -import com.alibaba.excel.read.metadata.holder.ReadRowHolder; -import com.alibaba.excel.util.PositionUtils; - -/** - * Cell Handler - * - * @author jipengfei - */ -public class ProcessResultCellHandler implements XlsxCellHandler { - - @Override - public void startHandle(XlsxReadContext xlsxReadContext, String name, Attributes attributes) { - xlsxReadContext.readRowHolder( - new ReadRowHolder(PositionUtils.getRowByRowTagt(attributes.getValue(ExcelXmlConstants.POSITION)), RowTypeEnum.DATA, - xlsxReadContext.readSheetHolder().getGlobalConfiguration())); - } - - @Override - public void endHandle(XlsxReadContext xlsxReadContext, String name) { - xlsxReadContext.analysisEventProcessor().endRow(xlsxReadContext); - } - -} diff --git a/src/main/java/com/alibaba/excel/analysis/v07/handlers/RowTagHandler.java b/src/main/java/com/alibaba/excel/analysis/v07/handlers/RowTagHandler.java new file mode 100644 index 00000000..372a0a7d --- /dev/null +++ b/src/main/java/com/alibaba/excel/analysis/v07/handlers/RowTagHandler.java @@ -0,0 +1,35 @@ +package com.alibaba.excel.analysis.v07.handlers; + +import java.util.LinkedHashMap; + +import org.xml.sax.Attributes; + +import com.alibaba.excel.constant.ExcelXmlConstants; +import com.alibaba.excel.context.xlsx.XlsxReadContext; +import com.alibaba.excel.enums.RowTypeEnum; +import com.alibaba.excel.metadata.Cell; +import com.alibaba.excel.read.metadata.holder.ReadRowHolder; +import com.alibaba.excel.util.PositionUtils; + +/** + * Cell Handler + * + * @author jipengfei + */ +public class RowTagHandler extends AbstractXlsxTagHandler { + + @Override + public void startElement(XlsxReadContext xlsxReadContext, String name, Attributes attributes) { + xlsxReadContext.readRowHolder( + new ReadRowHolder(PositionUtils.getRowByRowTagt(attributes.getValue(ExcelXmlConstants.POSITION)), + RowTypeEnum.DATA, xlsxReadContext.readSheetHolder().getGlobalConfiguration(), null)); + } + + @Override + public void endElement(XlsxReadContext xlsxReadContext, String name) { + xlsxReadContext.readRowHolder().setCellMap(xlsxReadContext.xlsxReadSheetHolder().getCellMap()); + xlsxReadContext.analysisEventProcessor().endRow(xlsxReadContext); + xlsxReadContext.xlsxReadSheetHolder().setCellMap(new LinkedHashMap()); + } + +} diff --git a/src/main/java/com/alibaba/excel/analysis/v07/handlers/XlsxCellHandler.java b/src/main/java/com/alibaba/excel/analysis/v07/handlers/XlsxCellHandler.java deleted file mode 100644 index 3ec2fd85..00000000 --- a/src/main/java/com/alibaba/excel/analysis/v07/handlers/XlsxCellHandler.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.alibaba.excel.analysis.v07.handlers; - -import org.xml.sax.Attributes; - -import com.alibaba.excel.context.xlsx.XlsxReadContext; - -/** - * Cell handler - * - * @author Dan Zheng - */ -public interface XlsxCellHandler { - /** - * Start handle - * - * @param xlsxReadContext xlsxReadContext - * @param name Tag name - * @param attributes Tag attributes - */ - void startHandle(XlsxReadContext xlsxReadContext, String name, Attributes attributes); - - /** - * End handle - * - * @param xlsxReadContext xlsxReadContext - * @param name Tag name - */ - void endHandle(XlsxReadContext xlsxReadContext, String name); -} diff --git a/src/main/java/com/alibaba/excel/analysis/v07/handlers/XlsxTagHandler.java b/src/main/java/com/alibaba/excel/analysis/v07/handlers/XlsxTagHandler.java new file mode 100644 index 00000000..3bd353a7 --- /dev/null +++ b/src/main/java/com/alibaba/excel/analysis/v07/handlers/XlsxTagHandler.java @@ -0,0 +1,53 @@ +package com.alibaba.excel.analysis.v07.handlers; + +import org.xml.sax.Attributes; + +import com.alibaba.excel.context.xlsx.XlsxReadContext; + +/** + * Tag handler + * + * @author Dan Zheng + */ +public interface XlsxTagHandler { + + /** + * Whether to support + * + * @param xlsxReadContext + */ + boolean support(XlsxReadContext xlsxReadContext); + + /** + * Start handle + * + * @param xlsxReadContext + * xlsxReadContext + * @param name + * Tag name + * @param attributes + * Tag attributes + */ + void startElement(XlsxReadContext xlsxReadContext, String name, Attributes attributes); + + /** + * End handle + * + * @param xlsxReadContext + * xlsxReadContext + * @param name + * Tag name + */ + void endElement(XlsxReadContext xlsxReadContext, String name); + + /** + * Read data + * + * @param xlsxReadContext + * @param ch + * @param start + * @param length + */ + void characters(XlsxReadContext xlsxReadContext, char[] ch, int start, int length); + +} diff --git a/src/main/java/com/alibaba/excel/analysis/v07/handlers/sax/XlsxRowHandler.java b/src/main/java/com/alibaba/excel/analysis/v07/handlers/sax/XlsxRowHandler.java index 90e760a6..0a4adb4e 100644 --- a/src/main/java/com/alibaba/excel/analysis/v07/handlers/sax/XlsxRowHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v07/handlers/sax/XlsxRowHandler.java @@ -7,9 +7,15 @@ import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; -import com.alibaba.excel.analysis.v07.handlers.CountRowCellHandler; -import com.alibaba.excel.analysis.v07.handlers.ProcessResultCellHandler; -import com.alibaba.excel.analysis.v07.handlers.XlsxCellHandler; +import com.alibaba.excel.analysis.v07.handlers.CellFormulaTagHandler; +import com.alibaba.excel.analysis.v07.handlers.CellInlineStringValueTagHandler; +import com.alibaba.excel.analysis.v07.handlers.CellTagHandler; +import com.alibaba.excel.analysis.v07.handlers.CellValueTagHandler; +import com.alibaba.excel.analysis.v07.handlers.CountTagHandler; +import com.alibaba.excel.analysis.v07.handlers.HyperlinkTagHandler; +import com.alibaba.excel.analysis.v07.handlers.MergeCellTagHandler; +import com.alibaba.excel.analysis.v07.handlers.RowTagHandler; +import com.alibaba.excel.analysis.v07.handlers.XlsxTagHandler; import com.alibaba.excel.constant.ExcelXmlConstants; import com.alibaba.excel.context.xlsx.XlsxReadContext; @@ -18,11 +24,18 @@ import com.alibaba.excel.context.xlsx.XlsxReadContext; */ public class XlsxRowHandler extends DefaultHandler { private XlsxReadContext xlsxReadContext; - private static final Map XLSX_CELL_HANDLER_MAP = new HashMap(16); + private static final Map XLSX_CELL_HANDLER_MAP = new HashMap(16); static { - XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.DIMENSION, new CountRowCellHandler()); - XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.ROW_TAG, new ProcessResultCellHandler()); + XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.CELL_FORMULA_TAG, new CellFormulaTagHandler()); + XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.CELL_INLINE_STRING_VALUE_TAG, + new CellInlineStringValueTagHandler()); + XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.CELL_TAG, new CellTagHandler()); + XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.CELL_VALUE_TAG, new CellValueTagHandler()); + XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.DIMENSION, new CountTagHandler()); + XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.HYPERLINK_TAG, new HyperlinkTagHandler()); + XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.MERGE_CELL_TAG, new MergeCellTagHandler()); + XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.ROW_TAG, new RowTagHandler()); } public XlsxRowHandler(XlsxReadContext xlsxReadContext) { @@ -31,28 +44,35 @@ public class XlsxRowHandler extends DefaultHandler { @Override public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException { - XlsxCellHandler handler = XLSX_CELL_HANDLER_MAP.get(name); + XlsxTagHandler handler = XLSX_CELL_HANDLER_MAP.get(name); if (handler == null) { return; } - handler.startHandle(xlsxReadContext, name, attributes); + xlsxReadContext.xlsxReadSheetHolder().getTagDeque().push(name); + handler.startElement(xlsxReadContext, name, attributes); } @Override public void characters(char[] ch, int start, int length) throws SAXException { - if (rowResultHolder != null) { - rowResultHolder.appendCurrentCellValue(ch, start, length); + String currentTag = xlsxReadContext.xlsxReadSheetHolder().getTagDeque().peek(); + if (currentTag == null) { + return; } + XlsxTagHandler handler = XLSX_CELL_HANDLER_MAP.get(currentTag); + if (handler == null) { + return; + } + handler.characters(xlsxReadContext, ch, start, length); } @Override public void endElement(String uri, String localName, String name) throws SAXException { - XlsxCellHandler handler = XLSX_CELL_HANDLER_MAP.get(name); + XlsxTagHandler handler = XLSX_CELL_HANDLER_MAP.get(name); if (handler == null) { return; } - handler.endHandle(xlsxReadContext, name); + handler.endElement(xlsxReadContext, name); + xlsxReadContext.xlsxReadSheetHolder().getTagDeque().pop(); } - } diff --git a/src/main/java/com/alibaba/excel/constant/ExcelXmlConstants.java b/src/main/java/com/alibaba/excel/constant/ExcelXmlConstants.java index f01a33b3..5cb6662a 100644 --- a/src/main/java/com/alibaba/excel/constant/ExcelXmlConstants.java +++ b/src/main/java/com/alibaba/excel/constant/ExcelXmlConstants.java @@ -22,4 +22,19 @@ public class ExcelXmlConstants { */ public static final String CELL_INLINE_STRING_VALUE_TAG = "t"; + public static final String MERGE_CELL_TAG = "mergeCell"; + public static final String HYPERLINK_TAG = "hyperlink"; + + /** + * Cell range split + */ + public static final String CELL_RANGE_SPLIT = ":"; + /** + * ref attribute + */ + public static final String ATTRIBUTE_REF = "ref"; + /** + * location attribute + */ + public static final String ATTRIBUTE_LOCATION = "location"; } diff --git a/src/main/java/com/alibaba/excel/context/AnalysisContext.java b/src/main/java/com/alibaba/excel/context/AnalysisContext.java index b4414598..684fb6e0 100644 --- a/src/main/java/com/alibaba/excel/context/AnalysisContext.java +++ b/src/main/java/com/alibaba/excel/context/AnalysisContext.java @@ -92,20 +92,6 @@ public interface AnalysisContext { */ void readSheetList(List readSheetList); - /** - * Read all sheets - * - * @return - */ - Boolean readAll(); - - /** - * Read all sheets - * - * @return - */ - void readAll(Boolean readAll); - /** * get current sheet * diff --git a/src/main/java/com/alibaba/excel/context/AnalysisContextImpl.java b/src/main/java/com/alibaba/excel/context/AnalysisContextImpl.java index 2b5a766e..ab27e87e 100644 --- a/src/main/java/com/alibaba/excel/context/AnalysisContextImpl.java +++ b/src/main/java/com/alibaba/excel/context/AnalysisContextImpl.java @@ -137,16 +137,6 @@ public class AnalysisContextImpl implements AnalysisContext { } - @Override - public Boolean readAll() { - return null; - } - - @Override - public void readAll(Boolean readAll) { - - } - @Override public Sheet getCurrentSheet() { Sheet sheet = new Sheet(readSheetHolder.getSheetNo() + 1); diff --git a/src/main/java/com/alibaba/excel/enums/CellExtraTypeEnum.java b/src/main/java/com/alibaba/excel/enums/CellExtraTypeEnum.java new file mode 100644 index 00000000..1c13b7c0 --- /dev/null +++ b/src/main/java/com/alibaba/excel/enums/CellExtraTypeEnum.java @@ -0,0 +1,21 @@ +package com.alibaba.excel.enums; + +/** + * Extra data type + * + * @author Jiaju Zhuang + **/ +public enum CellExtraTypeEnum { + /** + * Comment + */ + COMMENT, + /** + * Hyperlink + */ + HYPERLINK, + /** + * Merge + */ + MERGE,; +} diff --git a/src/main/java/com/alibaba/excel/enums/ExtraReadEnum.java b/src/main/java/com/alibaba/excel/enums/ExtraReadEnum.java deleted file mode 100644 index 2dee2bfe..00000000 --- a/src/main/java/com/alibaba/excel/enums/ExtraReadEnum.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.alibaba.excel.enums; - -/** - * Read some extra data - * - * @author Jiaju Zhuang - **/ -public enum ExtraReadEnum { - /** - * Read the comment - */ - COMMENT,; -} diff --git a/src/main/java/com/alibaba/excel/enums/RowTypeEnum.java b/src/main/java/com/alibaba/excel/enums/RowTypeEnum.java index 75dfc673..e371cbdc 100644 --- a/src/main/java/com/alibaba/excel/enums/RowTypeEnum.java +++ b/src/main/java/com/alibaba/excel/enums/RowTypeEnum.java @@ -10,10 +10,6 @@ public enum RowTypeEnum { * data */ DATA, - /** - * extra - */ - EXTRA, /** * empty */ diff --git a/src/main/java/com/alibaba/excel/event/AbstractIgnoreExceptionReadListener.java b/src/main/java/com/alibaba/excel/event/AbstractIgnoreExceptionReadListener.java index 22a95f03..1e93397e 100644 --- a/src/main/java/com/alibaba/excel/event/AbstractIgnoreExceptionReadListener.java +++ b/src/main/java/com/alibaba/excel/event/AbstractIgnoreExceptionReadListener.java @@ -1,6 +1,7 @@ package com.alibaba.excel.event; import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.metadata.CellExtra; import com.alibaba.excel.read.listener.ReadListener; /** @@ -20,6 +21,17 @@ public abstract class AbstractIgnoreExceptionReadListener implements ReadList @Override public void onException(Exception exception, AnalysisContext context) {} + /** + * The current method is called when extra information is returned + * + * @param extra + * extra information + * @param context + * analysis context + */ + @Override + public void extra(CellExtra extra, AnalysisContext context) {} + @Override public boolean hasNext(AnalysisContext context) { return true; diff --git a/src/main/java/com/alibaba/excel/event/AnalysisEventListener.java b/src/main/java/com/alibaba/excel/event/AnalysisEventListener.java index 176bd798..4b1b802a 100644 --- a/src/main/java/com/alibaba/excel/event/AnalysisEventListener.java +++ b/src/main/java/com/alibaba/excel/event/AnalysisEventListener.java @@ -4,6 +4,7 @@ import java.util.Map; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.metadata.CellData; +import com.alibaba.excel.metadata.CellExtra; import com.alibaba.excel.read.listener.ReadListener; import com.alibaba.excel.util.ConverterUtils; @@ -27,6 +28,17 @@ public abstract class AnalysisEventListener implements ReadListener { */ public void invokeHeadMap(Map headMap, AnalysisContext context) {} + /** + * The current method is called when extra information is returned + * + * @param extra + * extra information + * @param context + * analysis context + */ + @Override + public void extra(CellExtra extra, AnalysisContext context) {} + /** * All listeners receive this method when any one Listener does an error report. If an exception is thrown here, the * entire read will terminate. diff --git a/src/main/java/com/alibaba/excel/metadata/CellExtra.java b/src/main/java/com/alibaba/excel/metadata/CellExtra.java index 3570eb96..3a9c2b3b 100644 --- a/src/main/java/com/alibaba/excel/metadata/CellExtra.java +++ b/src/main/java/com/alibaba/excel/metadata/CellExtra.java @@ -1,18 +1,121 @@ package com.alibaba.excel.metadata; +import org.apache.poi.ss.util.CellReference; + +import com.alibaba.excel.constant.ExcelXmlConstants; +import com.alibaba.excel.enums.CellExtraTypeEnum; + /** * Cell extra information. * * @author Jiaju Zhuang */ public class CellExtra extends AbstractCell { - private String note; + /** + * Cell extra type + */ + private CellExtraTypeEnum type; + /** + * Cell extra data + */ + private String text; + /** + * First row index,if this object is an interval + */ + private Integer firstRowIndex; + /** + * First column index,if this object is an interval + */ + private Integer firstColumnIndex; + /** + * Last row index,if this object is an interval + */ + private Integer lastRowIndex; + /** + * Last column index,if this object is an interval + */ + private Integer lastColumnIndex; + + public CellExtra(CellExtraTypeEnum type, String text, String range) { + super(); + this.type = type; + this.text = text; + String[] ranges = range.split(ExcelXmlConstants.CELL_RANGE_SPLIT); + CellReference first = new CellReference(ranges[0]); + CellReference last = first; + this.firstRowIndex = first.getRow(); + this.firstColumnIndex = (int)first.getCol(); + setRowIndex(this.firstRowIndex); + setColumnIndex(this.firstColumnIndex); + if (ranges.length > 1) { + last = new CellReference(ranges[1]); + } + this.lastRowIndex = last.getRow(); + this.lastColumnIndex = (int)last.getCol(); + } + + public CellExtra(CellExtraTypeEnum type, String text, Integer rowIndex, Integer columnIndex) { + this(type, text, rowIndex, columnIndex, rowIndex, columnIndex); + } + + public CellExtra(CellExtraTypeEnum type, String text, Integer firstRowIndex, Integer firstColumnIndex, + Integer lastRowIndex, Integer lastColumnIndex) { + super(); + setRowIndex(firstRowIndex); + setColumnIndex(firstColumnIndex); + this.type = type; + this.text = text; + this.firstRowIndex = firstRowIndex; + this.firstColumnIndex = firstColumnIndex; + this.lastRowIndex = lastRowIndex; + this.lastColumnIndex = lastColumnIndex; + } + + public CellExtraTypeEnum getType() { + return type; + } + + public void setType(CellExtraTypeEnum type) { + this.type = type; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + public Integer getFirstRowIndex() { + return firstRowIndex; + } + + public void setFirstRowIndex(Integer firstRowIndex) { + this.firstRowIndex = firstRowIndex; + } + + public Integer getFirstColumnIndex() { + return firstColumnIndex; + } + + public void setFirstColumnIndex(Integer firstColumnIndex) { + this.firstColumnIndex = firstColumnIndex; + } + + public Integer getLastRowIndex() { + return lastRowIndex; + } + + public void setLastRowIndex(Integer lastRowIndex) { + this.lastRowIndex = lastRowIndex; + } - public String getNote() { - return note; + public Integer getLastColumnIndex() { + return lastColumnIndex; } - public void setNote(String note) { - this.note = note; + public void setLastColumnIndex(Integer lastColumnIndex) { + this.lastColumnIndex = lastColumnIndex; } } diff --git a/src/main/java/com/alibaba/excel/read/builder/ExcelReaderBuilder.java b/src/main/java/com/alibaba/excel/read/builder/ExcelReaderBuilder.java index ae3b79c1..342d9433 100644 --- a/src/main/java/com/alibaba/excel/read/builder/ExcelReaderBuilder.java +++ b/src/main/java/com/alibaba/excel/read/builder/ExcelReaderBuilder.java @@ -2,6 +2,8 @@ package com.alibaba.excel.read.builder; import java.io.File; import java.io.InputStream; +import java.util.HashSet; +import java.util.List; import javax.xml.parsers.SAXParserFactory; @@ -9,9 +11,10 @@ import com.alibaba.excel.ExcelReader; import com.alibaba.excel.cache.ReadCache; import com.alibaba.excel.cache.selector.ReadCacheSelector; import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.enums.CellExtraTypeEnum; import com.alibaba.excel.event.AnalysisEventListener; +import com.alibaba.excel.event.SyncReadListener; import com.alibaba.excel.read.listener.ModelBuildEventListener; -import com.alibaba.excel.read.listener.ReadListener; import com.alibaba.excel.read.metadata.ReadWorkbook; import com.alibaba.excel.support.ExcelTypeEnum; @@ -158,6 +161,21 @@ public class ExcelReaderBuilder extends AbstractExcelReaderParameterBuilder()); + } + readWorkbook.getExtraReadSet().add(extraType); + return this; + } + /** * Whether to use the default listener, which is used by default. *

@@ -175,11 +193,24 @@ public class ExcelReaderBuilder extends AbstractExcelReaderParameterBuilder List doReadAllSync() { ExcelReader excelReader = build(); + SyncReadListener syncReadListener = new SyncReadListener(); + registerReadListener(syncReadListener); excelReader.readAll(); excelReader.finish(); - return excelReader; + return (List)syncReadListener.getList(); } public ExcelReaderSheetBuilder sheet() { diff --git a/src/main/java/com/alibaba/excel/read/listener/ReadListener.java b/src/main/java/com/alibaba/excel/read/listener/ReadListener.java index 142c531b..f1d341f5 100644 --- a/src/main/java/com/alibaba/excel/read/listener/ReadListener.java +++ b/src/main/java/com/alibaba/excel/read/listener/ReadListener.java @@ -5,6 +5,7 @@ import java.util.Map; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.event.Listener; import com.alibaba.excel.metadata.CellData; +import com.alibaba.excel.metadata.CellExtra; /** * Interface to listen for read results @@ -40,6 +41,16 @@ public interface ReadListener extends Listener { */ void invoke(T data, AnalysisContext context); + /** + * The current method is called when extra information is returned + * + * @param extra + * extra information + * @param context + * analysis context + */ + void extra(CellExtra extra, AnalysisContext context); + /** * if have something to do after all analysis * diff --git a/src/main/java/com/alibaba/excel/read/metadata/ReadWorkbook.java b/src/main/java/com/alibaba/excel/read/metadata/ReadWorkbook.java index c08ab18e..c9e4db93 100644 --- a/src/main/java/com/alibaba/excel/read/metadata/ReadWorkbook.java +++ b/src/main/java/com/alibaba/excel/read/metadata/ReadWorkbook.java @@ -9,7 +9,7 @@ import javax.xml.parsers.SAXParserFactory; import com.alibaba.excel.cache.ReadCache; import com.alibaba.excel.cache.selector.ReadCacheSelector; import com.alibaba.excel.context.AnalysisContext; -import com.alibaba.excel.enums.ExtraReadEnum; +import com.alibaba.excel.enums.CellExtraTypeEnum; import com.alibaba.excel.event.AnalysisEventListener; import com.alibaba.excel.read.listener.ModelBuildEventListener; import com.alibaba.excel.support.ExcelTypeEnum; @@ -88,9 +88,9 @@ public class ReadWorkbook extends ReadBasicParameter { /** * Read some additional fields. None are read by default. * - * @see ExtraReadEnum + * @see CellExtraTypeEnum */ - private Set extraReadSet; + private Set extraReadSet; /** * The default is all excel objects.Default is true. *

@@ -221,11 +221,11 @@ public class ReadWorkbook extends ReadBasicParameter { this.useDefaultListener = useDefaultListener; } - public Set getExtraReadSet() { + public Set getExtraReadSet() { return extraReadSet; } - public void setExtraReadSet(Set extraReadSet) { + public void setExtraReadSet(Set extraReadSet) { this.extraReadSet = extraReadSet; } } diff --git a/src/main/java/com/alibaba/excel/read/metadata/holder/ReadRowHolder.java b/src/main/java/com/alibaba/excel/read/metadata/holder/ReadRowHolder.java index da745096..d81df87c 100644 --- a/src/main/java/com/alibaba/excel/read/metadata/holder/ReadRowHolder.java +++ b/src/main/java/com/alibaba/excel/read/metadata/holder/ReadRowHolder.java @@ -35,10 +35,12 @@ public class ReadRowHolder implements Holder { */ private GlobalConfiguration globalConfiguration; - public ReadRowHolder(Integer rowIndex, RowTypeEnum rowType, GlobalConfiguration globalConfiguration) { + public ReadRowHolder(Integer rowIndex, RowTypeEnum rowType, GlobalConfiguration globalConfiguration, + Map cellMap) { this.rowIndex = rowIndex; this.rowType = rowType; this.globalConfiguration = globalConfiguration; + this.cellMap = cellMap; } public GlobalConfiguration getGlobalConfiguration() { diff --git a/src/main/java/com/alibaba/excel/read/metadata/holder/ReadSheetHolder.java b/src/main/java/com/alibaba/excel/read/metadata/holder/ReadSheetHolder.java index 84dd4c4a..87185dc2 100644 --- a/src/main/java/com/alibaba/excel/read/metadata/holder/ReadSheetHolder.java +++ b/src/main/java/com/alibaba/excel/read/metadata/holder/ReadSheetHolder.java @@ -1,6 +1,12 @@ package com.alibaba.excel.read.metadata.holder; +import java.util.LinkedHashMap; +import java.util.Map; + import com.alibaba.excel.enums.HolderEnum; +import com.alibaba.excel.metadata.Cell; +import com.alibaba.excel.metadata.CellData; +import com.alibaba.excel.metadata.CellExtra; import com.alibaba.excel.read.metadata.ReadSheet; /** @@ -29,6 +35,22 @@ public class ReadSheetHolder extends AbstractReadHolder { * Gets the total number of rows , data may be inaccurate */ private Integer approximateTotalRowNumber; + /** + * Data storage of the current row. + */ + private Map cellMap; + /** + * Data storage of the current extra cell. + */ + private CellExtra cellExtra; + /** + * Index of the current row. + */ + private Integer rowIndex; + /** + * Current CellData + */ + private CellData tempCellData; public ReadSheetHolder(ReadSheet readSheet, ReadWorkbookHolder readWorkbookHolder) { super(readSheet, readWorkbookHolder, readWorkbookHolder.getReadWorkbook().getConvertAllFiled()); @@ -36,6 +58,7 @@ public class ReadSheetHolder extends AbstractReadHolder { this.parentReadWorkbookHolder = readWorkbookHolder; this.sheetNo = readSheet.getSheetNo(); this.sheetName = readSheet.getSheetName(); + this.cellMap = new LinkedHashMap(); } public ReadSheet getReadSheet() { @@ -71,7 +94,6 @@ public class ReadSheetHolder extends AbstractReadHolder { } /** - * * Approximate total number of rows * * @return @@ -95,6 +117,38 @@ public class ReadSheetHolder extends AbstractReadHolder { this.approximateTotalRowNumber = approximateTotalRowNumber; } + public Map getCellMap() { + return cellMap; + } + + public void setCellMap(Map cellMap) { + this.cellMap = cellMap; + } + + public Integer getRowIndex() { + return rowIndex; + } + + public void setRowIndex(Integer rowIndex) { + this.rowIndex = rowIndex; + } + + public CellData getTempCellData() { + return tempCellData; + } + + public void setTempCellData(CellData tempCellData) { + this.tempCellData = tempCellData; + } + + public CellExtra getCellExtra() { + return cellExtra; + } + + public void setCellExtra(CellExtra cellExtra) { + this.cellExtra = cellExtra; + } + @Override public HolderEnum holderType() { return HolderEnum.SHEET; diff --git a/src/main/java/com/alibaba/excel/read/metadata/holder/ReadWorkbookHolder.java b/src/main/java/com/alibaba/excel/read/metadata/holder/ReadWorkbookHolder.java index 1c1b2420..7ad89726 100644 --- a/src/main/java/com/alibaba/excel/read/metadata/holder/ReadWorkbookHolder.java +++ b/src/main/java/com/alibaba/excel/read/metadata/holder/ReadWorkbookHolder.java @@ -7,17 +7,12 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -import javax.xml.parsers.SAXParserFactory; - -import org.apache.poi.openxml4j.opc.OPCPackage; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; - import com.alibaba.excel.cache.ReadCache; import com.alibaba.excel.cache.selector.EternalReadCacheSelector; import com.alibaba.excel.cache.selector.ReadCacheSelector; import com.alibaba.excel.cache.selector.SimpleReadCacheSelector; import com.alibaba.excel.context.AnalysisContext; -import com.alibaba.excel.enums.ExtraReadEnum; +import com.alibaba.excel.enums.CellExtraTypeEnum; import com.alibaba.excel.enums.HolderEnum; import com.alibaba.excel.event.AnalysisEventListener; import com.alibaba.excel.exception.ExcelAnalysisException; @@ -91,9 +86,9 @@ public class ReadWorkbookHolder extends AbstractReadHolder { /** * Read some additional fields. None are read by default. * - * @see ExtraReadEnum + * @see CellExtraTypeEnum */ - private Set extraReadSet; + private Set extraReadSet; /** * Actual sheet data */ @@ -101,7 +96,7 @@ public class ReadWorkbookHolder extends AbstractReadHolder { /** * Parameter sheet data */ - private List parametersheetDataList; + private List parameterSheetDataList; /** * Read all */ @@ -152,11 +147,6 @@ public class ReadWorkbookHolder extends AbstractReadHolder { this.autoCloseStream = readWorkbook.getAutoCloseStream(); } - this.excelType = readWorkbook.getExcelType(); - - if (ExcelTypeEnum.XLS == excelType && getGlobalConfiguration().getUse1904windowing() == null) { - getGlobalConfiguration().setUse1904windowing(Boolean.FALSE); - } this.customObject = readWorkbook.getCustomObject(); if (readWorkbook.getIgnoreEmptyRow() == null) { this.ignoreEmptyRow = Boolean.TRUE; @@ -181,7 +171,7 @@ public class ReadWorkbookHolder extends AbstractReadHolder { this.defaultReturnMap = readWorkbook.getDefaultReturnMap(); } if (readWorkbook.getExtraReadSet() == null) { - this.extraReadSet = new HashSet(); + this.extraReadSet = new HashSet(); } else { this.extraReadSet = readWorkbook.getExtraReadSet(); } @@ -309,11 +299,11 @@ public class ReadWorkbookHolder extends AbstractReadHolder { this.password = password; } - public Set getExtraReadSet() { + public Set getExtraReadSet() { return extraReadSet; } - public void setExtraReadSet(Set extraReadSet) { + public void setExtraReadSet(Set extraReadSet) { this.extraReadSet = extraReadSet; } @@ -325,12 +315,12 @@ public class ReadWorkbookHolder extends AbstractReadHolder { this.actualSheetDataList = actualSheetDataList; } - public List getParametersheetDataList() { - return parametersheetDataList; + public List getParameterSheetDataList() { + return parameterSheetDataList; } - public void setParametersheetDataList(List parametersheetDataList) { - this.parametersheetDataList = parametersheetDataList; + public void setParameterSheetDataList(List parameterSheetDataList) { + this.parameterSheetDataList = parameterSheetDataList; } public Boolean getReadAll() { diff --git a/src/main/java/com/alibaba/excel/read/metadata/holder/xls/XlsReadSheetHolder.java b/src/main/java/com/alibaba/excel/read/metadata/holder/xls/XlsReadSheetHolder.java index a77a8d38..d0171ffc 100644 --- a/src/main/java/com/alibaba/excel/read/metadata/holder/xls/XlsReadSheetHolder.java +++ b/src/main/java/com/alibaba/excel/read/metadata/holder/xls/XlsReadSheetHolder.java @@ -1,12 +1,9 @@ package com.alibaba.excel.read.metadata.holder.xls; import java.util.HashMap; -import java.util.LinkedHashMap; import java.util.Map; import com.alibaba.excel.enums.RowTypeEnum; -import com.alibaba.excel.metadata.Cell; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.read.metadata.ReadSheet; import com.alibaba.excel.read.metadata.holder.ReadSheetHolder; import com.alibaba.excel.read.metadata.holder.ReadWorkbookHolder; @@ -21,22 +18,10 @@ public class XlsReadSheetHolder extends ReadSheetHolder { * Row type.Temporary storage, last set in ReadRowHolder. */ private RowTypeEnum tempRowType; - /** - * Data storage of the current row. - */ - private Map cellMap; - /** - * Index of the current row. - */ - private Integer rowIndex; /** * Ignore record. */ private Boolean ignoreRecord; - /** - * Temp Cell Data. - */ - private CellData tempCellData; /** * Temp object index. */ @@ -48,7 +33,6 @@ public class XlsReadSheetHolder extends ReadSheetHolder { public XlsReadSheetHolder(ReadSheet readSheet, ReadWorkbookHolder readWorkbookHolder) { super(readSheet, readWorkbookHolder); - cellMap = new LinkedHashMap(); ignoreRecord = Boolean.FALSE; tempRowType = RowTypeEnum.EMPTY; objectCacheMap = new HashMap(16); @@ -62,22 +46,6 @@ public class XlsReadSheetHolder extends ReadSheetHolder { this.tempRowType = tempRowType; } - public Map getCellMap() { - return cellMap; - } - - public void setCellMap(Map cellMap) { - this.cellMap = cellMap; - } - - public Integer getRowIndex() { - return rowIndex; - } - - public void setRowIndex(Integer rowIndex) { - this.rowIndex = rowIndex; - } - public Boolean getIgnoreRecord() { return ignoreRecord; } @@ -86,14 +54,6 @@ public class XlsReadSheetHolder extends ReadSheetHolder { this.ignoreRecord = ignoreRecord; } - public CellData getTempCellData() { - return tempCellData; - } - - public void setTempCellData(CellData tempCellData) { - this.tempCellData = tempCellData; - } - public Integer getTempObjectIndex() { return tempObjectIndex; } diff --git a/src/main/java/com/alibaba/excel/read/metadata/holder/xls/XlsReadWorkbookHolder.java b/src/main/java/com/alibaba/excel/read/metadata/holder/xls/XlsReadWorkbookHolder.java index c4b698cb..70c1c03a 100644 --- a/src/main/java/com/alibaba/excel/read/metadata/holder/xls/XlsReadWorkbookHolder.java +++ b/src/main/java/com/alibaba/excel/read/metadata/holder/xls/XlsReadWorkbookHolder.java @@ -1,5 +1,6 @@ package com.alibaba.excel.read.metadata.holder.xls; +import java.util.ArrayList; import java.util.List; import org.apache.poi.hssf.eventusermodel.FormatTrackingHSSFListener; @@ -9,6 +10,7 @@ import org.apache.poi.poifs.filesystem.POIFSFileSystem; import com.alibaba.excel.read.metadata.ReadWorkbook; import com.alibaba.excel.read.metadata.holder.ReadWorkbookHolder; +import com.alibaba.excel.support.ExcelTypeEnum; /** * Workbook holder @@ -27,7 +29,7 @@ public class XlsReadWorkbookHolder extends ReadWorkbookHolder { /** * HSSFWorkbook */ - private HSSFWorkbook hsffWorkbook; + private HSSFWorkbook hssfWorkbook; /** * Bound sheet record list. */ @@ -43,6 +45,12 @@ public class XlsReadWorkbookHolder extends ReadWorkbookHolder { public XlsReadWorkbookHolder(ReadWorkbook readWorkbook) { super(readWorkbook); + this.boundSheetRecordList = new ArrayList(); + this.needReadSheet = Boolean.TRUE; + setExcelType(ExcelTypeEnum.XLS); + if (getGlobalConfiguration().getUse1904windowing() == null) { + getGlobalConfiguration().setUse1904windowing(Boolean.FALSE); + } } public POIFSFileSystem getPoifsFileSystem() { @@ -61,12 +69,12 @@ public class XlsReadWorkbookHolder extends ReadWorkbookHolder { this.formatTrackingHSSFListener = formatTrackingHSSFListener; } - public HSSFWorkbook getHsffWorkbook() { - return hsffWorkbook; + public HSSFWorkbook getHssfWorkbook() { + return hssfWorkbook; } - public void setHsffWorkbook(HSSFWorkbook hsffWorkbook) { - this.hsffWorkbook = hsffWorkbook; + public void setHssfWorkbook(HSSFWorkbook hssfWorkbook) { + this.hssfWorkbook = hssfWorkbook; } public List getBoundSheetRecordList() { diff --git a/src/main/java/com/alibaba/excel/read/metadata/holder/xlsx/XlsxReadSheetHolder.java b/src/main/java/com/alibaba/excel/read/metadata/holder/xlsx/XlsxReadSheetHolder.java index 2e1174d7..46b92818 100644 --- a/src/main/java/com/alibaba/excel/read/metadata/holder/xlsx/XlsxReadSheetHolder.java +++ b/src/main/java/com/alibaba/excel/read/metadata/holder/xlsx/XlsxReadSheetHolder.java @@ -1,5 +1,8 @@ package com.alibaba.excel.read.metadata.holder.xlsx; +import java.util.Deque; +import java.util.LinkedList; + import com.alibaba.excel.read.metadata.ReadSheet; import com.alibaba.excel.read.metadata.holder.ReadSheetHolder; import com.alibaba.excel.read.metadata.holder.ReadWorkbookHolder; @@ -10,10 +13,57 @@ import com.alibaba.excel.read.metadata.holder.ReadWorkbookHolder; * @author Jiaju Zhuang */ public class XlsxReadSheetHolder extends ReadSheetHolder { - - + /** + * Record the label of the current operation to prevent NPE. + */ + private Deque tagDeque; + /** + * Current Column + */ + private Integer columnIndex; + /** + * Data for current label. + */ + private StringBuilder tempData; + /** + * Formula for current label. + */ + private StringBuilder tempFormula; public XlsxReadSheetHolder(ReadSheet readSheet, ReadWorkbookHolder readWorkbookHolder) { super(readSheet, readWorkbookHolder); + this.tagDeque = new LinkedList(); + } + + public Deque getTagDeque() { + return tagDeque; + } + + public void setTagDeque(Deque tagDeque) { + this.tagDeque = tagDeque; + } + + public Integer getColumnIndex() { + return columnIndex; + } + + public void setColumnIndex(Integer columnIndex) { + this.columnIndex = columnIndex; + } + + public StringBuilder getTempData() { + return tempData; + } + + public void setTempData(StringBuilder tempData) { + this.tempData = tempData; + } + + public StringBuilder getTempFormula() { + return tempFormula; + } + + public void setTempFormula(StringBuilder tempFormula) { + this.tempFormula = tempFormula; } } diff --git a/src/main/java/com/alibaba/excel/read/metadata/holder/xlsx/XlsxReadWorkbookHolder.java b/src/main/java/com/alibaba/excel/read/metadata/holder/xlsx/XlsxReadWorkbookHolder.java index 9542366c..066131d3 100644 --- a/src/main/java/com/alibaba/excel/read/metadata/holder/xlsx/XlsxReadWorkbookHolder.java +++ b/src/main/java/com/alibaba/excel/read/metadata/holder/xlsx/XlsxReadWorkbookHolder.java @@ -7,6 +7,7 @@ import org.apache.poi.xssf.model.StylesTable; import com.alibaba.excel.read.metadata.ReadWorkbook; import com.alibaba.excel.read.metadata.holder.ReadWorkbookHolder; +import com.alibaba.excel.support.ExcelTypeEnum; /** * Workbook holder @@ -37,6 +38,7 @@ public class XlsxReadWorkbookHolder extends ReadWorkbookHolder { public XlsxReadWorkbookHolder(ReadWorkbook readWorkbook) { super(readWorkbook); this.saxParserFactoryName = readWorkbook.getXlsxSAXParserFactoryName(); + setExcelType(ExcelTypeEnum.XLSX); } public OPCPackage getOpcPackage() { diff --git a/src/main/java/com/alibaba/excel/read/processor/AnalysisEventProcessor.java b/src/main/java/com/alibaba/excel/read/processor/AnalysisEventProcessor.java index cd485382..360ae97d 100644 --- a/src/main/java/com/alibaba/excel/read/processor/AnalysisEventProcessor.java +++ b/src/main/java/com/alibaba/excel/read/processor/AnalysisEventProcessor.java @@ -9,6 +9,13 @@ import com.alibaba.excel.context.AnalysisContext; * @author jipengfei */ public interface AnalysisEventProcessor { + /** + * Read extra information + * + * @param analysisContext + */ + void extra(AnalysisContext analysisContext); + /** * End row * diff --git a/src/main/java/com/alibaba/excel/read/processor/DefaultAnalysisEventProcessor.java b/src/main/java/com/alibaba/excel/read/processor/DefaultAnalysisEventProcessor.java index 6b5b0af8..ddd19504 100644 --- a/src/main/java/com/alibaba/excel/read/processor/DefaultAnalysisEventProcessor.java +++ b/src/main/java/com/alibaba/excel/read/processor/DefaultAnalysisEventProcessor.java @@ -9,6 +9,7 @@ import org.slf4j.LoggerFactory; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.enums.HeadKindEnum; +import com.alibaba.excel.enums.RowTypeEnum; import com.alibaba.excel.exception.ExcelAnalysisException; import com.alibaba.excel.exception.ExcelAnalysisStopException; import com.alibaba.excel.metadata.CellData; @@ -28,29 +29,22 @@ import com.alibaba.excel.util.StringUtils; public class DefaultAnalysisEventProcessor implements AnalysisEventProcessor { private static final Logger LOGGER = LoggerFactory.getLogger(DefaultAnalysisEventProcessor.class); + @Override + public void extra(AnalysisContext analysisContext) { + dealExtra(analysisContext); + } + @Override public void endRow(AnalysisContext analysisContext) { - switch (analysisContext.readRowHolder().getRowType()) { - case EMPTY: - if (LOGGER.isDebugEnabled()) { - LOGGER.warn("Empty row!"); - } - if (analysisContext.readWorkbookHolder().getIgnoreEmptyRow()) { - return; - } - // Need to continue to notify invoke. - dealData(analysisContext); - break; - case DATA: - dealData(analysisContext); - break; - case EXTRA: - dealExtra(analysisContext); - break; - default: - throw new ExcelAnalysisException("Wrong row type."); + if (RowTypeEnum.EMPTY.equals(analysisContext.readRowHolder().getRowType())) { + if (LOGGER.isDebugEnabled()) { + LOGGER.warn("Empty row!"); + } + if (analysisContext.readWorkbookHolder().getIgnoreEmptyRow()) { + return; + } } - + dealData(analysisContext); } @Override @@ -61,13 +55,34 @@ public class DefaultAnalysisEventProcessor implements AnalysisEventProcessor { } private void dealExtra(AnalysisContext analysisContext) { + for (ReadListener readListener : analysisContext.currentReadHolder().readListenerList()) { + try { + readListener.extra(analysisContext.readSheetHolder().getCellExtra(), analysisContext); + } catch (Exception e) { + onException(analysisContext, e); + break; + } + if (!readListener.hasNext(analysisContext)) { + throw new ExcelAnalysisStopException(); + } + } + } - + private void onException(AnalysisContext analysisContext, Exception e) { + for (ReadListener readListenerException : analysisContext.currentReadHolder().readListenerList()) { + try { + readListenerException.onException(e, analysisContext); + } catch (RuntimeException re) { + throw re; + } catch (Exception e1) { + throw new ExcelAnalysisException(e1.getMessage(), e1); + } + } } private void dealData(AnalysisContext analysisContext) { ReadRowHolder readRowHolder = analysisContext.readRowHolder(); - Map cellDataMap = (Map) readRowHolder.getCellMap(); + Map cellDataMap = (Map)readRowHolder.getCellMap(); readRowHolder.setCurrentRowAnalysisResult(cellDataMap); int rowIndex = readRowHolder.getRowIndex(); int currentHeadRowNumber = analysisContext.readSheetHolder().getHeadRowNumber(); @@ -78,7 +93,6 @@ public class DefaultAnalysisEventProcessor implements AnalysisEventProcessor { if (!isData && currentHeadRowNumber == rowIndex + 1) { buildHead(analysisContext, cellDataMap); } - // Now is data for (ReadListener readListener : analysisContext.currentReadHolder().readListenerList()) { try { @@ -88,15 +102,7 @@ public class DefaultAnalysisEventProcessor implements AnalysisEventProcessor { readListener.invokeHead(cellDataMap, analysisContext); } } catch (Exception e) { - for (ReadListener readListenerException : analysisContext.currentReadHolder().readListenerList()) { - try { - readListenerException.onException(e, analysisContext); - } catch (RuntimeException re) { - throw re; - } catch (Exception e1) { - throw new ExcelAnalysisException(e1.getMessage(), e1); - } - } + onException(analysisContext, e); break; } if (!readListener.hasNext(analysisContext)) { diff --git a/src/main/java/com/alibaba/excel/util/SheetUtils.java b/src/main/java/com/alibaba/excel/util/SheetUtils.java index fb2c59e5..c2c727c7 100644 --- a/src/main/java/com/alibaba/excel/util/SheetUtils.java +++ b/src/main/java/com/alibaba/excel/util/SheetUtils.java @@ -5,6 +5,7 @@ import org.slf4j.LoggerFactory; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.read.metadata.ReadSheet; +import com.alibaba.excel.read.metadata.holder.ReadWorkbookHolder; /** * Sheet utils @@ -14,21 +15,22 @@ import com.alibaba.excel.read.metadata.ReadSheet; public class SheetUtils { private static final Logger LOGGER = LoggerFactory.getLogger(SheetUtils.class); - private SheetUtils() { - } + private SheetUtils() {} /** * Match the parameters to the actual sheet * - * @param readSheet actual sheet + * @param readSheet + * actual sheet * @param analysisContext * @return */ public static ReadSheet match(ReadSheet readSheet, AnalysisContext analysisContext) { - if (analysisContext.readAll()) { + ReadWorkbookHolder readWorkbookHolder = analysisContext.readWorkbookHolder(); + if (readWorkbookHolder.getReadAll()) { return readSheet; } - for (ReadSheet parameterReadSheet : analysisContext.readSheetList()) { + for (ReadSheet parameterReadSheet : readWorkbookHolder.getParameterSheetDataList()) { if (parameterReadSheet == null) { continue; } @@ -45,7 +47,7 @@ public class SheetUtils { if (!StringUtils.isEmpty(parameterSheetName)) { boolean autoTrim = (parameterReadSheet.getAutoTrim() != null && parameterReadSheet.getAutoTrim()) || (parameterReadSheet.getAutoTrim() == null - && analysisContext.readWorkbookHolder().getGlobalConfiguration().getAutoTrim()); + && analysisContext.readWorkbookHolder().getGlobalConfiguration().getAutoTrim()); if (autoTrim) { parameterSheetName = parameterSheetName.trim(); } diff --git a/src/test/java/com/alibaba/easyexcel/test/core/extra/ExtraData.java b/src/test/java/com/alibaba/easyexcel/test/core/extra/ExtraData.java new file mode 100644 index 00000000..61822fa8 --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/core/extra/ExtraData.java @@ -0,0 +1,14 @@ +package com.alibaba.easyexcel.test.core.extra; + +import lombok.Data; + +/** + * @author Jiaju Zhuang + */ +@Data +public class ExtraData { + + private String row1; + + private String row2; +} diff --git a/src/test/java/com/alibaba/easyexcel/test/core/extra/ExtraDataListener.java b/src/test/java/com/alibaba/easyexcel/test/core/extra/ExtraDataListener.java new file mode 100644 index 00000000..9039ab06 --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/core/extra/ExtraDataListener.java @@ -0,0 +1,55 @@ +package com.alibaba.easyexcel.test.core.extra; + +import org.junit.Assert; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.event.AnalysisEventListener; +import com.alibaba.excel.metadata.CellExtra; +import com.alibaba.fastjson.JSON; + +/** + * @author Jiaju Zhuang + */ +public class ExtraDataListener extends AnalysisEventListener { + private static final Logger LOGGER = LoggerFactory.getLogger(ExtraData.class); + + @Override + public void invoke(ExtraData data, AnalysisContext context) {} + + @Override + public void doAfterAllAnalysed(AnalysisContext context) {} + + @Override + public void extra(CellExtra extra, AnalysisContext context) { + LOGGER.info("extra data:{}", JSON.toJSONString(extra)); + switch (extra.getType()) { + case COMMENT: + Assert.assertEquals("批注的内容", extra.getText()); + Assert.assertEquals(4, (int)extra.getRowIndex()); + Assert.assertEquals(0, (int)extra.getColumnIndex()); + break; + case HYPERLINK: + if ("Sheet1!A1".equals(extra.getText())) { + Assert.assertEquals(1, (int)extra.getRowIndex()); + Assert.assertEquals(0, (int)extra.getColumnIndex()); + } else if ("Sheet2!A1".equals(extra.getText())) { + Assert.assertEquals(2, (int)extra.getFirstRowIndex()); + Assert.assertEquals(0, (int)extra.getFirstColumnIndex()); + Assert.assertEquals(3, (int)extra.getLastRowIndex()); + Assert.assertEquals(1, (int)extra.getLastColumnIndex()); + } else { + Assert.fail("Unknown hyperlink!"); + } + break; + case MERGE: + Assert.assertEquals(5, (int)extra.getFirstRowIndex()); + Assert.assertEquals(0, (int)extra.getFirstColumnIndex()); + Assert.assertEquals(6, (int)extra.getLastRowIndex()); + Assert.assertEquals(1, (int)extra.getLastColumnIndex()); + break; + default: + } + } +} diff --git a/src/test/java/com/alibaba/easyexcel/test/core/extra/ExtraDataTest.java b/src/test/java/com/alibaba/easyexcel/test/core/extra/ExtraDataTest.java new file mode 100644 index 00000000..cf7418d5 --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/core/extra/ExtraDataTest.java @@ -0,0 +1,44 @@ +package com.alibaba.easyexcel.test.core.extra; + +import java.io.File; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.alibaba.easyexcel.test.util.TestFileUtil; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.enums.CellExtraTypeEnum; + +/** + * + * @author Jiaju Zhuang + */ +public class ExtraDataTest { + private static final Logger LOGGER = LoggerFactory.getLogger(ExtraDataTest.class); + private static File file03; + private static File file07; + + @BeforeClass + public static void init() { + file03 = TestFileUtil.readFile("extra" + File.separator + "extra.xls"); + file07 = TestFileUtil.readFile("extra" + File.separator + "extra.xlsx"); + } + + @Test + public void t01Read07() { + read(file07); + } + + @Test + public void t02Read03() { + read(file03); + } + + private void read(File file) { + EasyExcel.read(file, ExtraData.class, new ExtraDataListener()).extraRead(CellExtraTypeEnum.COMMENT) + .extraRead(CellExtraTypeEnum.HYPERLINK).extraRead(CellExtraTypeEnum.MERGE).sheet().doRead(); + } + +} diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java b/src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java index ece5aa0e..30325d14 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java @@ -3,6 +3,7 @@ package com.alibaba.easyexcel.test.temp; import java.io.File; import java.util.List; +import org.apache.poi.hssf.util.CellReference; import org.junit.Ignore; import org.junit.Test; import org.slf4j.Logger; @@ -31,6 +32,11 @@ public class Lock2Test { } } + @Test + public void testc() throws Exception { + LOGGER.info("reslut:{}", JSON.toJSONString(new CellReference("B3"))); + } + @Test public void simpleRead() { // 写法1: diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/read/CommentTest.java b/src/test/java/com/alibaba/easyexcel/test/temp/read/CommentTest.java index bcb1d999..21e0d9c3 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/read/CommentTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/read/CommentTest.java @@ -25,7 +25,7 @@ public class CommentTest { @Test public void comment() throws Exception { File file = new File("D:\\test\\comment.xls"); - List> datas = EasyExcel.read(file).sheet(0).doReadSync(); + List> datas = EasyExcel.read(file).doReadAllSync(); for (Map data : datas) { LOGGER.info("数据:{}", JSON.toJSONString(data.get(0))); } diff --git a/src/test/resources/demo/demo.xlsx b/src/test/resources/demo/demo.xlsx index 48d3f87abd209ef857fe68ace222647bf9254ab7..662bb971758c6b080d73ef14103731501d635c7b 100644 GIT binary patch literal 10173 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 diff --git a/src/test/resources/extra/extra.xls b/src/test/resources/extra/extra.xls new file mode 100644 index 0000000000000000000000000000000000000000..89f389beda341657656eec9d513f776412f4a59d GIT binary patch literal 19968 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 3.4.0(jdk6) * 修复xls 用Map接收时多次接收会是同一个对象的bug * 修复浮点型数据导入到excel 会丢失精度的bug -* 新增支持接收批注 +* 新增支持读取批注、超链接、合并单元格 * 如果是`RuntimeException`则不再封装对象 +* 新增`CellData`可以获取行列号 # 2.1.4