From 4e916b8403a192068575b5bf7559c4be623534e1 Mon Sep 17 00:00:00 2001 From: Hccake Date: Fri, 4 Nov 2022 22:56:22 +0800 Subject: [PATCH 1/2] =?UTF-8?q?:bug:=20buildHead=20=E5=BA=94=E5=9C=A8=20re?= =?UTF-8?q?adListener=20=E7=9A=84=20invokeHead=20=E5=85=A8=E9=83=A8?= =?UTF-8?q?=E6=89=A7=E8=A1=8C=E5=AE=8C=E6=88=90=E5=90=8E=E6=89=A7=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../read/processor/DefaultAnalysisEventProcessor.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/easyexcel-core/src/main/java/com/alibaba/excel/read/processor/DefaultAnalysisEventProcessor.java b/easyexcel-core/src/main/java/com/alibaba/excel/read/processor/DefaultAnalysisEventProcessor.java index 45edb7b7..dae61e28 100644 --- a/easyexcel-core/src/main/java/com/alibaba/excel/read/processor/DefaultAnalysisEventProcessor.java +++ b/easyexcel-core/src/main/java/com/alibaba/excel/read/processor/DefaultAnalysisEventProcessor.java @@ -88,11 +88,7 @@ public class DefaultAnalysisEventProcessor implements AnalysisEventProcessor { boolean isData = rowIndex >= currentHeadRowNumber; - // Last head column - if (!isData && currentHeadRowNumber == rowIndex + 1) { - buildHead(analysisContext, cellDataMap); - } - // Now is data + // invoke data or invoke head for (ReadListener readListener : analysisContext.currentReadHolder().readListenerList()) { try { if (isData) { @@ -108,6 +104,11 @@ public class DefaultAnalysisEventProcessor implements AnalysisEventProcessor { throw new ExcelAnalysisStopException(); } } + + // Last head column + if (!isData && currentHeadRowNumber == rowIndex + 1) { + buildHead(analysisContext, cellDataMap); + } } private void buildHead(AnalysisContext analysisContext, Map> cellDataMap) { From eec8954efdda9809e8b8dfe6bfebba44625eebe4 Mon Sep 17 00:00:00 2001 From: Hccake Date: Mon, 7 Nov 2022 13:14:41 +0800 Subject: [PATCH 2/2] =?UTF-8?q?:white=5Fcheck=5Fmark:=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=85=BC=E5=AE=B9=E6=80=A7=E8=A1=A8=E5=A4=B4=E4=B8=8A=E4=BC=A0?= =?UTF-8?q?=E7=A4=BA=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../demo/read/DemoCompatibleHeaderData.java | 23 +++++ .../DemoCompatibleHeaderDataListener.java | 97 +++++++++++++++++++ .../easyexcel/test/demo/read/ReadTest.java | 20 ++++ 3 files changed, 140 insertions(+) create mode 100644 easyexcel-test/src/test/java/com/alibaba/easyexcel/test/demo/read/DemoCompatibleHeaderData.java create mode 100644 easyexcel-test/src/test/java/com/alibaba/easyexcel/test/demo/read/DemoCompatibleHeaderDataListener.java diff --git a/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/demo/read/DemoCompatibleHeaderData.java b/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/demo/read/DemoCompatibleHeaderData.java new file mode 100644 index 00000000..944a781d --- /dev/null +++ b/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/demo/read/DemoCompatibleHeaderData.java @@ -0,0 +1,23 @@ +package com.alibaba.easyexcel.test.demo.read; + +import com.alibaba.excel.annotation.ExcelProperty; +import lombok.Data; + +import java.util.Date; + +/** + * 多种表头上传支持的测试实体类 + * @author hccake + */ +@Data +public class DemoCompatibleHeaderData { + + @ExcelProperty("String") + private String string; + + @ExcelProperty("Date") + private Date date; + + @ExcelProperty("DoubleData") + private Double doubleData; +} diff --git a/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/demo/read/DemoCompatibleHeaderDataListener.java b/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/demo/read/DemoCompatibleHeaderDataListener.java new file mode 100644 index 00000000..2525854c --- /dev/null +++ b/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/demo/read/DemoCompatibleHeaderDataListener.java @@ -0,0 +1,97 @@ +package com.alibaba.easyexcel.test.demo.read; + +import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.event.AnalysisEventListener; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.util.ListUtils; +import com.alibaba.fastjson.JSON; +import lombok.extern.slf4j.Slf4j; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 读取头,兼容中英文传入 + * + * @author hccake + */ +@Slf4j +public class DemoCompatibleHeaderDataListener extends AnalysisEventListener { + + /** + * 每隔5条存储数据库,实际使用中可以100条,然后清理list ,方便内存回收 + */ + private static final int BATCH_COUNT = 100; + /** + * 缓存的数据 + */ + private List cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT); + + /** + * 这里添加,各种表头到注解表头信息的映射 + */ + private Map headerMapping = new HashMap<>(8); + { + headerMapping.put("字符串标题", "String"); + headerMapping.put("日期标题", "Date"); + headerMapping.put("数字标题", "DoubleData"); + } + + + /** + * 这里会一行行的返回头 + * + * @param headMap + * @param context + */ + @Override + public void invokeHead(Map> headMap, AnalysisContext context) { + log.info("解析到一条头数据:{}", JSON.toJSONString(headMap)); + headMap.forEach((key, value) -> { + // 这里是根据 map 做的表头映射关系,实际可以根据自己的逻辑按需定制 + // 比如大小写转换,截取尾缀,删除空格,等等等等 + String stringValue = value.getStringValue(); + value.setStringValue(headerMapping.getOrDefault(stringValue, stringValue)); + }); + } + + + /** + * 这个每一条数据解析都会来调用 + * + * @param data one row value. Is is same as {@link AnalysisContext#readRowHolder()} + * @param context + */ + @Override + public void invoke(DemoCompatibleHeaderData data, AnalysisContext context) { + log.info("解析到一条数据:{}", JSON.toJSONString(data)); + cachedDataList.add(data); + // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM + if (cachedDataList.size() >= BATCH_COUNT) { + saveData(); + // 存储完成清理 list + cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT); + } + } + + /** + * 所有数据解析完成了 都会来调用 + * + * @param context + */ + @Override + public void doAfterAllAnalysed(AnalysisContext context) { + // 这里也要保存数据,确保最后遗留的数据也存储到数据库 + saveData(); + log.info("所有数据解析完成!"); + } + + /** + * 加上存储数据库 + */ + private void saveData() { + log.info("{}条数据,开始存储数据库!", cachedDataList.size()); + log.info("存储数据库成功!"); + } +} diff --git a/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/demo/read/ReadTest.java b/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/demo/read/ReadTest.java index 527ca6dc..ae10a631 100644 --- a/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/demo/read/ReadTest.java +++ b/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/demo/read/ReadTest.java @@ -200,6 +200,26 @@ public class ReadTest { .headRowNumber(1).doRead(); } + + /** + * 兼容性的表头上传,例如大小写同时支持,或者中英文同时支持 + * + *

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

+ * 2. 由于默认一行行的读取excel,所以需要创建excel一行一行的回调监听器,参照{@link DemoCompatibleHeaderDataListener}, + * 且监听器种需要复写 invokeHead 方法,用来对上传的表头做转换 + *

+ * 3. 直接读即可 + */ + @Test + public void compatibleHeaderRead() { + String fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx"; + // 这里 需要指定读用哪个class去读,然后读取第一个sheet + EasyExcel.read(fileName, DemoCompatibleHeaderData.class, new DemoCompatibleHeaderDataListener()).sheet().doRead(); + } + + /** * 读取表头数据 *