From 9b782f258d87bae776e840ab7d959ed34dd356c8 Mon Sep 17 00:00:00 2001 From: kaiux Date: Wed, 23 Oct 2019 16:12:11 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=AF=B9Excel=E6=89=B9?= =?UTF-8?q?=E6=B3=A8=E7=9A=84=E8=AF=BB=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../excel/analysis/v03/XlsSaxAnalyser.java | 38 ++++++++ .../excel/analysis/v07/XlsxCellHandler.java | 8 ++ .../excel/analysis/v07/XlsxRowHandler.java | 26 ++++++ .../excel/analysis/v07/XlsxSaxAnalyser.java | 17 +++- .../v07/handlers/CountRowCellHandler.java | 5 ++ .../v07/handlers/DefaultCellHandler.java | 5 ++ .../handlers/ProcessResultCellHandler.java | 5 ++ .../read/metadata/holder/ReadRowHolder.java | 32 +++++++ .../demo/read/DemoCellCommentsListener.java | 85 ++++++++++++++++++ .../easyexcel/test/demo/read/ReadTest.java | 17 ++++ src/test/resources/demo/demo.xlsx | Bin 10117 -> 12291 bytes 11 files changed, 237 insertions(+), 1 deletion(-) create mode 100644 src/test/java/com/alibaba/easyexcel/test/demo/read/DemoCellCommentsListener.java 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 21977a4..e5df4bf 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java @@ -3,10 +3,12 @@ package com.alibaba.excel.analysis.v03; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; +import com.alibaba.excel.util.StringUtils; import org.apache.poi.hssf.eventusermodel.EventWorkbookBuilder; import org.apache.poi.hssf.eventusermodel.FormatTrackingHSSFListener; import org.apache.poi.hssf.eventusermodel.HSSFEventFactory; @@ -19,6 +21,11 @@ import org.apache.poi.hssf.record.BoundSheetRecord; import org.apache.poi.hssf.record.Record; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.ss.usermodel.Comment; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.usermodel.WorkbookFactory; +import org.apache.poi.ss.util.CellAddress; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -74,11 +81,18 @@ public class XlsSaxAnalyser implements HSSFListener, ExcelReadExecutor { private HSSFWorkbook stubWorkbook; private List recordHandlers = new ArrayList(); private AnalysisContext analysisContext; + private Workbook poiWorkbook; + private Map rowComments; public XlsSaxAnalyser(AnalysisContext context, POIFSFileSystem poifsFileSystem) { this.analysisContext = context; this.records = new TreeMap(); this.poifsFileSystem = poifsFileSystem; + try { + this.poiWorkbook = WorkbookFactory.create(poifsFileSystem); + } catch (IOException e) { + e.printStackTrace(); + } analysisContext.readWorkbookHolder().setPoifsFileSystem(poifsFileSystem); } @@ -139,6 +153,7 @@ public class XlsSaxAnalyser implements HSSFListener, ExcelReadExecutor { thisRow = handler.getRow(); thisColumn = handler.getColumn(); cellData = handler.getCellData(); + handleComments(thisRow, thisColumn); if (cellData != null) { cellData.checkEmpty(); if (CellDataTypeEnum.EMPTY != cellData.getType()) { @@ -170,6 +185,26 @@ public class XlsSaxAnalyser implements HSSFListener, ExcelReadExecutor { processLastCellOfRow(record); } + public void handleComments(int row, int col) { + if (null == this.poiWorkbook || null == analysisContext.readSheetHolder() || row < 0 || col < 0) { + return; + } + Sheet currentSheet = poiWorkbook.getSheetAt(analysisContext.readSheetHolder().getSheetNo()); + Map cellComments = currentSheet.getCellComments(); + if (CollectionUtils.isEmpty(cellComments)) { + return; + } + Comment comment = cellComments.get(new CellAddress(row, col)); + if (null == comment) { + return; + } + String commentsStr = comment.getString().toString(); + if (!StringUtils.isEmpty(commentsStr)) { + rowComments = rowComments == null ? new HashMap(8) : rowComments; + rowComments.put(col, commentsStr); + } + } + private boolean ignoreRecord(Record record) { return analysisContext.readWorkbookHolder().getIgnoreRecord03() && record.getSid() != BoundSheetRecord.sid && record.getSid() != BOFRecord.sid; @@ -188,6 +223,9 @@ public class XlsSaxAnalyser implements HSSFListener, ExcelReadExecutor { } analysisContext.readRowHolder( new ReadRowHolder(lastRowNumber, analysisContext.readSheetHolder().getGlobalConfiguration())); + if (!CollectionUtils.isEmpty(rowComments)) { + analysisContext.readRowHolder().setRowComments(rowComments); + } analysisContext.readSheetHolder().notifyEndOneRow(new EachRowAnalysisFinishEvent(records), analysisContext); records.clear(); lastColumnNumber = -1; diff --git a/src/main/java/com/alibaba/excel/analysis/v07/XlsxCellHandler.java b/src/main/java/com/alibaba/excel/analysis/v07/XlsxCellHandler.java index a4db7f4..3068725 100644 --- a/src/main/java/com/alibaba/excel/analysis/v07/XlsxCellHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v07/XlsxCellHandler.java @@ -34,4 +34,12 @@ public interface XlsxCellHandler { * Tag name */ void endHandle(String name); + + /** + * Set the comment of the cell + * + * @param comment + * cell comment + */ + void handleComments(String comment); } diff --git a/src/main/java/com/alibaba/excel/analysis/v07/XlsxRowHandler.java b/src/main/java/com/alibaba/excel/analysis/v07/XlsxRowHandler.java index ececb47..b6702c1 100644 --- a/src/main/java/com/alibaba/excel/analysis/v07/XlsxRowHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v07/XlsxRowHandler.java @@ -2,7 +2,12 @@ package com.alibaba.excel.analysis.v07; import java.util.List; +import com.alibaba.excel.constant.ExcelXmlConstants; +import com.alibaba.excel.util.StringUtils; +import org.apache.poi.ss.util.CellAddress; +import org.apache.poi.xssf.model.CommentsTable; import org.apache.poi.xssf.model.StylesTable; +import org.apache.poi.xssf.usermodel.XSSFComment; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; @@ -17,6 +22,12 @@ public class XlsxRowHandler extends DefaultHandler { private List cellHandlers; private XlsxRowResultHolder rowResultHolder; + private CommentsTable commentsTable; + + public XlsxRowHandler(AnalysisContext analysisContext, StylesTable stylesTable, CommentsTable commentsTable) { + this(analysisContext, stylesTable); + this.commentsTable = commentsTable; + } public XlsxRowHandler(AnalysisContext analysisContext, StylesTable stylesTable) { this.cellHandlers = XlsxHandlerFactory.buildCellHandlers(analysisContext, stylesTable); @@ -33,6 +44,7 @@ public class XlsxRowHandler extends DefaultHandler { for (XlsxCellHandler cellHandler : cellHandlers) { if (cellHandler.support(name)) { cellHandler.startHandle(name, attributes); + handleComment(cellHandler, attributes.getValue(ExcelXmlConstants.POSITION)); } } } @@ -52,4 +64,18 @@ public class XlsxRowHandler extends DefaultHandler { rowResultHolder.appendCurrentCellValue(ch, start, length); } } + + private void handleComment(XlsxCellHandler cellHandler, String address) { + if (StringUtils.isEmpty(address) || null == commentsTable) { + return; + } + XSSFComment xssfComment = commentsTable.getCellComments().get(new CellAddress(address)); + if (null == xssfComment) { + return; + } + String comments = xssfComment.getString().toString(); + if (!StringUtils.isEmpty(comments)) { + cellHandler.handleComments(comments); + } + } } 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 dd468b4..591932e 100644 --- a/src/main/java/com/alibaba/excel/analysis/v07/XlsxSaxAnalyser.java +++ b/src/main/java/com/alibaba/excel/analysis/v07/XlsxSaxAnalyser.java @@ -17,6 +17,7 @@ import org.apache.poi.openxml4j.opc.PackageAccess; import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.xssf.eventusermodel.XSSFReader; +import org.apache.poi.xssf.model.CommentsTable; import org.apache.poi.xssf.model.StylesTable; import org.apache.poi.xssf.usermodel.XSSFRelation; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorkbook; @@ -46,6 +47,14 @@ public class XlsxSaxAnalyser implements ExcelReadExecutor { private AnalysisContext analysisContext; private List sheetList; private Map sheetMap; + + /** + * excel comments + * key: sheetNo + * value: CommentsTanle + */ + private Map commentsTableMap; + /** * Current style information */ @@ -77,6 +86,7 @@ public class XlsxSaxAnalyser implements ExcelReadExecutor { stylesTable = xssfReader.getStylesTable(); sheetList = new ArrayList(); sheetMap = new HashMap(); + commentsTableMap = new HashMap(); XSSFReader.SheetIterator ite = (XSSFReader.SheetIterator)xssfReader.getSheetsData(); int index = 0; if (!ite.hasNext()) { @@ -86,6 +96,10 @@ public class XlsxSaxAnalyser implements ExcelReadExecutor { InputStream inputStream = ite.next(); sheetList.add(new ReadSheet(index, ite.getSheetName())); sheetMap.put(index, inputStream); + CommentsTable commentsTable = ite.getSheetComments(); + if (null != commentsTable) { + commentsTableMap.put(index, commentsTable); + } index++; } } @@ -181,7 +195,8 @@ public class XlsxSaxAnalyser implements ExcelReadExecutor { analysisContext.readWorkbookHolder().getGlobalConfiguration()); if (readSheet != null) { analysisContext.currentSheet(readSheet); - parseXmlSource(sheetMap.get(readSheet.getSheetNo()), new XlsxRowHandler(analysisContext, stylesTable)); + Integer sheetNo = readSheet.getSheetNo(); + parseXmlSource(sheetMap.get(sheetNo), new XlsxRowHandler(analysisContext, stylesTable, commentsTableMap.get(sheetNo))); // The last sheet is read analysisContext.readSheetHolder().notifyAfterAllAnalysed(analysisContext); } diff --git a/src/main/java/com/alibaba/excel/analysis/v07/handlers/CountRowCellHandler.java b/src/main/java/com/alibaba/excel/analysis/v07/handlers/CountRowCellHandler.java index ea63409..c92ec6c 100644 --- a/src/main/java/com/alibaba/excel/analysis/v07/handlers/CountRowCellHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v07/handlers/CountRowCellHandler.java @@ -39,4 +39,9 @@ public class CountRowCellHandler implements XlsxCellHandler { } + @Override + public void handleComments(String comment) { + + } + } 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 index 0d44a95..2dc0fdb 100644 --- a/src/main/java/com/alibaba/excel/analysis/v07/handlers/DefaultCellHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v07/handlers/DefaultCellHandler.java @@ -160,6 +160,11 @@ public class DefaultCellHandler implements XlsxCellHandler, XlsxRowResultHolder } } + @Override + public void handleComments(String comment) { + analysisContext.readRowHolder().addComments(curCol, comment); + } + @Override public void appendCurrentCellValue(char[] ch, int start, int length) { String currentTag = currentTagDeque.peek(); 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 index 9581646..32b75ed 100644 --- a/src/main/java/com/alibaba/excel/analysis/v07/handlers/ProcessResultCellHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v07/handlers/ProcessResultCellHandler.java @@ -45,4 +45,9 @@ public class ProcessResultCellHandler implements XlsxCellHandler { rowResultHandler.clearResult(); } + @Override + public void handleComments(String comment) { + + } + } 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 9916015..24079f7 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 @@ -3,6 +3,10 @@ package com.alibaba.excel.read.metadata.holder; import com.alibaba.excel.enums.HolderEnum; import com.alibaba.excel.metadata.GlobalConfiguration; import com.alibaba.excel.metadata.Holder; +import com.alibaba.excel.util.CollectionUtils; + +import java.util.HashMap; +import java.util.Map; /** * sheet holder @@ -24,6 +28,34 @@ public class ReadRowHolder implements Holder { */ private GlobalConfiguration globalConfiguration; + /** + * Return row comments + * key: col index + * value: comments + */ + private Map rowComments; + + public Map getRowComments() { + return rowComments; + } + + public void setRowComments(Map rowComments) { + this.rowComments = rowComments; + } + + public void addComments(Integer index, String comments) { + this.rowComments = this.rowComments == null ? new HashMap(8) : this.rowComments; + this.rowComments.put(index, comments); + } + + public String getComments(Integer index) { + if (CollectionUtils.isEmpty(rowComments)) { + return null; + } else { + return rowComments.get(index); + } + } + public ReadRowHolder(Integer rowIndex, GlobalConfiguration globalConfiguration) { this.rowIndex = rowIndex; this.globalConfiguration = globalConfiguration; diff --git a/src/test/java/com/alibaba/easyexcel/test/demo/read/DemoCellCommentsListener.java b/src/test/java/com/alibaba/easyexcel/test/demo/read/DemoCellCommentsListener.java new file mode 100644 index 0000000..733005c --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/demo/read/DemoCellCommentsListener.java @@ -0,0 +1,85 @@ +package com.alibaba.easyexcel.test.demo.read; + +import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.event.AnalysisEventListener; +import com.alibaba.excel.exception.ExcelDataConvertException; +import com.alibaba.excel.util.CollectionUtils; +import com.alibaba.fastjson.JSON; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * 读取单元格的批注 + * + * @author: kaiux + * @date: 2019-10-23 14:10 + **/ +public class DemoCellCommentsListener extends AnalysisEventListener { + private static final Logger LOGGER = LoggerFactory.getLogger(DemoCellCommentsListener.class); + /** + * 每隔5条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收 + */ + private static final int BATCH_COUNT = 5; + List list = new ArrayList(); + + /** + * 在转换异常 获取其他异常下会调用本接口。抛出异常则停止读取。如果这里不抛出异常则 继续读取下一行。 + * + * @param exception + * @param context + * @throws Exception + */ + @Override + public void onException(Exception exception, AnalysisContext context) { + LOGGER.error("解析失败,但是继续解析下一行:{}", exception.getMessage()); + if (exception instanceof ExcelDataConvertException) { + ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException) exception; + LOGGER.error("第{}行,第{}列解析异常", excelDataConvertException.getRowIndex(), + excelDataConvertException.getColumnIndex()); + } + } + + /** + * 这里会一行行的返回头 + * + * @param headMap + * @param context + */ + @Override + public void invokeHeadMap(Map headMap, AnalysisContext context) { + Map rowComments = context.readRowHolder().getRowComments(); + LOGGER.info("解析到一条头数据:{}", JSON.toJSONString(headMap)); + if (!CollectionUtils.isEmpty(rowComments)) { + for (Integer i : rowComments.keySet()) { + LOGGER.info("解析到头数据低{}列包含批注:{}", i, rowComments.get(i)); + } + } + } + + @Override + public void invoke(DemoData data, AnalysisContext context) { + LOGGER.info("解析到一条数据:{}", JSON.toJSONString(data)); + if (list.size() >= BATCH_COUNT) { + saveData(); + list.clear(); + } + } + + @Override + public void doAfterAllAnalysed(AnalysisContext context) { + saveData(); + LOGGER.info("所有数据解析完成!"); + } + + /** + * 加上存储数据库 + */ + private void saveData() { + LOGGER.info("{}条数据,开始存储数据库!", list.size()); + LOGGER.info("存储数据库成功!"); + } +} diff --git a/src/test/java/com/alibaba/easyexcel/test/demo/read/ReadTest.java b/src/test/java/com/alibaba/easyexcel/test/demo/read/ReadTest.java index 9ebafa4..112c529 100644 --- a/src/test/java/com/alibaba/easyexcel/test/demo/read/ReadTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/demo/read/ReadTest.java @@ -161,6 +161,23 @@ public class ReadTest { EasyExcel.read(fileName, DemoData.class, new DemoHeadDataListener()).sheet().doRead(); } + /** + * 读取单元格批注 + * + *

+ * 1. 创建excel对应的实体对象 参照{@link DemoData} + *

+ * 2. 由于默认异步读取excel,所以需要创建excel一行一行的回调监听器,参照{@link DemoHeadDataListener} + *

+ * 3. 直接读即可 + */ + @Test + public void commentsRead() { + String fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx"; + // 这里 需要指定读用哪个class去读,然后读取第一个sheet + EasyExcel.read(fileName, DemoData.class, new DemoCellCommentsListener()).sheet().doRead(); + } + /** * 读取公式和单元格类型 * diff --git a/src/test/resources/demo/demo.xlsx b/src/test/resources/demo/demo.xlsx index 303733cf81ddf2a0f6760f487d0552aec56f2bef..48d3f87abd209ef857fe68ace222647bf9254ab7 100644 GIT binary patch literal 12291 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 literal 10117 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 WSxJcJpaX#V^pbwkM*8ac+y4XORCGoF