diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md
index 0ff24019..4ea8cee6 100644
--- a/.github/ISSUE_TEMPLATE/bug.md
+++ b/.github/ISSUE_TEMPLATE/bug.md
@@ -7,6 +7,8 @@ assignees: zhuangjiaju
---
+**建议先去看文档**
+[快速开始](https://www.yuque.com/easyexcel/doc/easyexcel) 、[常见问题](https://www.yuque.com/easyexcel/faq)
**触发场景描述**
**触发Bug的代码**
diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md
index 06adf1ae..51cea2b3 100644
--- a/.github/ISSUE_TEMPLATE/question.md
+++ b/.github/ISSUE_TEMPLATE/question.md
@@ -1,12 +1,14 @@
---
name: question
-about: 有使用疑问,请先阅读“快速使用”,上面无法解决再提交问题。处理完请关闭问题。
+about: 有使用疑问,请先阅读“快速开始”,上面无法解决再提交问题。处理完请关闭问题。
title: ''
labels: help wanted
assignees: ''
---
+**建议先去看文档**
+[快速开始](https://www.yuque.com/easyexcel/doc/easyexcel) 、[常见问题](https://www.yuque.com/easyexcel/faq)
**异常代码**
```java
这里写你的代码
diff --git a/.github/ISSUE_TEMPLATE/suggest.md b/.github/ISSUE_TEMPLATE/suggest.md
index cf4948d1..1aeecd86 100644
--- a/.github/ISSUE_TEMPLATE/suggest.md
+++ b/.github/ISSUE_TEMPLATE/suggest.md
@@ -7,4 +7,6 @@ assignees: ''
---
+**建议先去看文档**
+[快速开始](https://www.yuque.com/easyexcel/doc/easyexcel) 、[常见问题](https://www.yuque.com/easyexcel/faq)
**建议描述**
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 00000000..724ecec4
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,8 @@
+## 前言
+非常感谢您愿意协助EasyExcel的开发,EasyExcel成长离不开大家的贡献。但是为了合作的更有效率,希望我们在贡献代码的时候能按照如下约定。
+## 提前沟通
+尽量把自己的想法和实现思路提前沟通,可以通过issue,钉钉,QQ都可以,可能很多问题我们内部已经讨论过,由于各种原因后续不会支持,但是您这边又开发好了,这样容易浪费您的时间。
+## 代码规范
+目前代码规范已经集成了自动校验,然后源代码尽量不要有中文注释。在新增功能的时候,尽量注意补充junit。core代表每次travis-ci都会跑的测试案例,然后demo用于对外看到,temp里面随便写。
+## 提交分支
+建议提交到最新的版本号.x上面,比如 3.x之类的版本,为了方便其他同学阅读源代码,所以目前的思路是master和maven center的最新版本代码保持一致,然后您提交过来的代码我们可能会稍微做一些修改。所以提交到开发分支会比较好。fork也可以直接fork该分支。
diff --git a/README.md b/README.md
index ecd2000b..9664d654 100644
--- a/README.md
+++ b/README.md
@@ -1,26 +1,32 @@
-easyexcel
+EasyExcel
======================
[![Build Status](https://travis-ci.org/alibaba/easyexcel.svg?branch=master)](https://travis-ci.org/alibaba/easyexcel)
[![Maven central](https://maven-badges.herokuapp.com/maven-central/com.alibaba/easyexcel/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.alibaba/easyexcel)
[![License](http://img.shields.io/:license-apache-brightgreen.svg)](http://www.apache.org/licenses/LICENSE-2.0.html)
-[QQ群: 662022184](//shang.qq.com/wpa/qunwpa?idkey=53d9d821b0833e3c14670f007488a61e300f00ff4f1b81fd950590d90dd80f80)
-[钉钉群: 21960511](https://qr.dingtalk.com/action/joingroup?code=v1,k1,cchz6k12ci9B08NNqhNRFGXocNVHrZtW0kaOtTKg/Rk=&_dt_no_comment=1&origin=11)
-[官方网站: https://alibaba-easyexcel.github.io/](https://alibaba-easyexcel.github.io/)
+[QQ1群(已满): 662022184](https://jq.qq.com/?_wv=1027&k=1T21jJxh)
+[QQ2群: 1097936804](https://jq.qq.com/?_wv=1027&k=j5zEy6Xl)
+[钉钉1群(已满): 21960511](https://qr.dingtalk.com/action/joingroup?code=v1,k1,cchz6k12ci9B08NNqhNRFGXocNVHrZtW0kaOtTKg/Rk=&_dt_no_comment=1&origin=11)
+[钉钉2群(已满): 32796397](https://qr.dingtalk.com/action/joingroup?code=v1,k1,jyU9GtEuNU5S0QTyklqYcYJ8qDZtUuTPMM7uPZTS8Hs=&_dt_no_comment=1&origin=11)
+[钉钉3群(已满): 33797247](https://qr.dingtalk.com/action/joingroup?code=v1,k1,3UGlEScTGQaHpW2cIRo+gkxJ9EVZ5fz26M6nW3uFP30=&_dt_no_comment=1&origin=11)
+[钉钉4群: 33491624](https://qr.dingtalk.com/action/joingroup?code=v1,k1,V14Pb65Too70rQkEaJ9ohb6lZBZbtp6jIL/q9EWh9vA=&_dt_no_comment=1&origin=11)
+[官方网站: https://yuque.com/easyexcel](https://www.yuque.com/easyexcel/doc/easyexcel)
+
+[常见问题](https://www.yuque.com/easyexcel/faq)
#### 因为公司不方便用QQ,所以建议加钉钉群
-# JAVA解析Excel工具easyexcel
-Java解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定程度的解决一些内存溢出的问题,但POI还是有一些缺陷,比如07版Excel解压缩以及解压后存储都是在内存中完成的,内存消耗依然很大。easyexcel重写了poi对07版Excel的解析,能够原本一个3M的excel用POI sax依然需要100M左右内存降低到几M,并且再大的excel不会出现内存溢出,03版依赖POI的sax模式。在上层做了模型转换的封装,让使用者更加简单方便
+# JAVA解析Excel工具EasyExcel
+Java解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定程度的解决一些内存溢出的问题,但POI还是有一些缺陷,比如07版Excel解压缩以及解压后存储都是在内存中完成的,内存消耗依然很大。easyexcel重写了poi对07版Excel的解析,一个3M的excel用POI sax解析依然需要100M左右内存,改用easyexcel可以降低到几M,并且再大的excel也不会出现内存溢出;03版依赖POI的sax模式,在上层做了模型转换的封装,让使用者更加简单方便
## 64M内存1分钟内读取75M(46W行25列)的Excel
-当然还有急速模式能更快,但是内存占用会在100M多一点
+当然还有极速模式能更快,但是内存占用会在100M多一点
![img](img/readme/large.png)
## 相关文档
-* [快速使用](https://alibaba-easyexcel.github.io/)
+* [快速开始](https://www.yuque.com/easyexcel/doc/easyexcel)
* [关于软件](/abouteasyexcel.md)
* [更新记事](/update.md)
-* [贡献代码](https://alibaba-easyexcel.github.io/support/contribute.html)
+* [贡献代码](https://www.yuque.com/easyexcel/doc/contribute)
## 维护者
玉霄、庄家钜、怀宇
@@ -63,20 +69,23 @@ DEMO代码地址:[https://github.com/alibaba/easyexcel/blob/master/src/test/ja
### web上传、下载
DEMO代码地址:[https://github.com/alibaba/easyexcel/blob/master/src/test/java/com/alibaba/easyexcel/test/demo/web/WebTest.java](/src/test/java/com/alibaba/easyexcel/test/demo/web/WebTest.java)
```java
- /**
+ /**
* 文件下载(失败了会返回一个有部分数据的Excel)
- *
1. 创建excel对应的实体对象 参照{@link DownloadData}
- *
2. 设置返回的 参数
- *
3. 直接写,这里注意,finish的时候会自动关闭OutputStream,当然你外面再关闭流问题不大
+ *
+ * 1. 创建excel对应的实体对象 参照{@link DownloadData}
+ *
+ * 2. 设置返回的 参数
+ *
+ * 3. 直接写,这里注意,finish的时候会自动关闭OutputStream,当然你外面再关闭流问题不大
*/
@GetMapping("download")
public void download(HttpServletResponse response) throws IOException {
// 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman
- response.setContentType("application/vnd.ms-excel");
+ response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
- String fileName = URLEncoder.encode("测试", "UTF-8");
- response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
+ String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");
+ response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
EasyExcel.write(response.getOutputStream(), DownloadData.class).sheet("模板").doWrite(data());
}
diff --git a/pom.xml b/pom.xml
index 51f63232..b5ae5cbf 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
4.0.0
com.alibaba
easyexcel
- 2.2.0-beta2
+ 3.0.0-beta1
jar
easyexcel
@@ -16,7 +16,7 @@
UTF-8
- 1.6
+ 1.8
true
true
@@ -60,22 +60,22 @@
org.apache.poi
poi
- 3.17
+ 4.1.2
org.apache.poi
poi-ooxml
- 3.17
+ 4.1.2
org.apache.poi
poi-ooxml-schemas
- 3.17
+ 4.1.2
cglib
cglib
- 3.1
+ 3.3.0
org.slf4j
@@ -85,8 +85,15 @@
org.ehcache
ehcache
- 3.4.0
+ 3.8.1
+
+ org.projectlombok
+ lombok
+ 1.18.20
+ provided
+
+
ch.qos.logback
@@ -97,13 +104,7 @@
com.alibaba
fastjson
- 1.2.58
- test
-
-
- org.projectlombok
- lombok
- 1.18.8
+ 1.2.71
test
@@ -121,7 +122,7 @@
junit
junit
- 4.12
+ 4.13.1
test
@@ -162,6 +163,8 @@
com/alibaba/excel/event/AnalysisEventListener.java
com/alibaba/excel/metadata/DataFormatter.java
com/alibaba/excel/util/DateUtils.java
+ com/alibaba/excel/metadata/format/DataFormatter.java
+ com/alibaba/excel/metadata/format/ExcelGeneralNumberFormat.java
@@ -185,8 +188,8 @@
org.apache.maven.plugins
maven-compiler-plugin
-
- 1.6
+
+ 1.8
@@ -230,6 +233,19 @@
+
+ org.projectlombok
+ lombok-maven-plugin
+ 1.18.20.0
+
+
+ generate-sources
+
+ delombok
+
+
+
+
diff --git a/src/main/java/com/alibaba/excel/ExcelReader.java b/src/main/java/com/alibaba/excel/ExcelReader.java
index 07a373b7..7af49eb6 100644
--- a/src/main/java/com/alibaba/excel/ExcelReader.java
+++ b/src/main/java/com/alibaba/excel/ExcelReader.java
@@ -136,6 +136,8 @@ public class ExcelReader {
readWorkbook.setReadCache(new MapCache());
readWorkbook.setConvertAllFiled(Boolean.FALSE);
readWorkbook.setDefaultReturnMap(Boolean.FALSE);
+ // The previous logic was that Article 0 started reading
+ readWorkbook.setHeadRowNumber(0);
excelAnalyser = new ExcelAnalyserImpl(readWorkbook);
}
@@ -274,7 +276,9 @@ public class ExcelReader {
* Complete the entire read file.Release the cache and close stream.
*/
public void finish() {
- excelAnalyser.finish();
+ if (excelAnalyser != null) {
+ excelAnalyser.finish();
+ }
}
/**
diff --git a/src/main/java/com/alibaba/excel/ExcelWriter.java b/src/main/java/com/alibaba/excel/ExcelWriter.java
index a0b4795b..2f5b61d2 100644
--- a/src/main/java/com/alibaba/excel/ExcelWriter.java
+++ b/src/main/java/com/alibaba/excel/ExcelWriter.java
@@ -3,6 +3,8 @@ package com.alibaba.excel;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import org.slf4j.Logger;
@@ -142,7 +144,7 @@ public class ExcelWriter {
* Write to this sheet
* @return this current writer
*/
- public ExcelWriter write(List data, WriteSheet writeSheet) {
+ public ExcelWriter write(Collection> data, WriteSheet writeSheet) {
return write(data, writeSheet, null);
}
@@ -157,7 +159,7 @@ public class ExcelWriter {
* Write to this table
* @return this
*/
- public ExcelWriter write(List data, WriteSheet writeSheet, WriteTable writeTable) {
+ public ExcelWriter write(Collection> data, WriteSheet writeSheet, WriteTable writeTable) {
excelBuilder.addContent(data, writeSheet, writeTable);
return this;
}
@@ -194,7 +196,7 @@ public class ExcelWriter {
* @param sheet
* Write to this sheet
* @return this current writer
- * @deprecated please use {@link ExcelWriter#write(List, WriteSheet)}
+ * @deprecated please use {@link ExcelWriter#write(Collection, WriteSheet)}
*/
@Deprecated
public ExcelWriter write(List data, Sheet sheet) {
@@ -211,7 +213,7 @@ public class ExcelWriter {
* @param table
* Write to this table
* @return this
- * @deprecated * @deprecated please use {@link ExcelWriter#write(List, WriteSheet,WriteTable)}
+ * @deprecated * @deprecated please use {@link ExcelWriter#write(Collection, WriteSheet,WriteTable)}
*/
@Deprecated
public ExcelWriter write(List data, Sheet sheet, Table table) {
@@ -246,7 +248,7 @@ public class ExcelWriter {
* @param sheet
* Write to this sheet
* @return this current writer
- * @deprecated please use {@link ExcelWriter#write(List, WriteSheet)}
+ * @deprecated please use {@link ExcelWriter#write(Collection, WriteSheet)}
*/
@Deprecated
public ExcelWriter write0(List data, Sheet sheet) {
@@ -263,7 +265,7 @@ public class ExcelWriter {
* @param table
* Write to this table
* @return this
- * @deprecated * @deprecated please use {@link ExcelWriter#write(List, WriteSheet,WriteTable)}
+ * @deprecated * @deprecated please use {@link ExcelWriter#write(Collection, WriteSheet,WriteTable)}
*/
@Deprecated
public ExcelWriter write0(List data, Sheet sheet, Table table) {
@@ -278,7 +280,7 @@ public class ExcelWriter {
* @param sheet
* Write to this sheet
* @return this current writer
- * @deprecated please use {@link ExcelWriter#write(List, WriteSheet)}
+ * @deprecated please use {@link ExcelWriter#write(Collection, WriteSheet)}
*/
@Deprecated
public ExcelWriter write1(List data, Sheet sheet) {
@@ -295,7 +297,7 @@ public class ExcelWriter {
* @param table
* Write to this table
* @return this
- * @deprecated * @deprecated please use {@link ExcelWriter#write(List, WriteSheet,WriteTable)}
+ * @deprecated * @deprecated please use {@link ExcelWriter#write(Collection, WriteSheet,WriteTable)}
*/
@Deprecated
public ExcelWriter write1(List data, Sheet sheet, Table table) {
@@ -325,7 +327,9 @@ public class ExcelWriter {
* Close IO
*/
public void finish() {
- excelBuilder.finish(false);
+ if (excelBuilder != null) {
+ excelBuilder.finish(false);
+ }
}
/**
diff --git a/src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java b/src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java
index 5487ee10..e049dbfc 100644
--- a/src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java
+++ b/src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java
@@ -3,6 +3,7 @@ package com.alibaba.excel.analysis;
import java.io.InputStream;
import java.util.List;
+import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
import org.apache.poi.poifs.crypt.Decryptor;
import org.apache.poi.poifs.filesystem.DocumentFactoryHelper;
@@ -26,7 +27,6 @@ import com.alibaba.excel.read.metadata.holder.ReadWorkbookHolder;
import com.alibaba.excel.read.metadata.holder.xls.XlsReadWorkbookHolder;
import com.alibaba.excel.read.metadata.holder.xlsx.XlsxReadWorkbookHolder;
import com.alibaba.excel.support.ExcelTypeEnum;
-import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.excel.util.DateUtils;
import com.alibaba.excel.util.FileUtils;
import com.alibaba.excel.util.NumberDataFormatterUtils;
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 2b92253e..83f98647 100644
--- a/src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java
+++ b/src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java
@@ -70,12 +70,12 @@ import com.alibaba.excel.read.metadata.holder.xls.XlsReadWorkbookHolder;
*
* * To turn an excel file into a CSV or similar, then see * the XLS2CSVmra example *
*
- * * * @see XLS2CSVmra
+ * * * @see XLS2CSVmra
*
* @author jipengfei
*/
public class XlsSaxAnalyser implements HSSFListener, ExcelReadExecutor {
+
private static final Logger LOGGER = LoggerFactory.getLogger(XlsSaxAnalyser.class);
private static final short DUMMY_RECORD_SID = -1;
private XlsReadContext xlsReadContext;
@@ -138,11 +138,6 @@ public class XlsSaxAnalyser implements HSSFListener, ExcelReadExecutor {
} catch (IOException e) {
throw new ExcelAnalysisException(e);
}
- // Sometimes tables lack the end record of the last column
- if (!xlsReadContext.xlsReadSheetHolder().getCellMap().isEmpty()) {
- // Forge a termination data
- processRecord(new LastCellOfRowDummyRecord(xlsReadContext.xlsReadSheetHolder().getRowIndex() + 1, -1));
- }
}
@Override
@@ -151,8 +146,8 @@ public class XlsSaxAnalyser implements HSSFListener, ExcelReadExecutor {
if (handler == null) {
return;
}
- boolean ignoreRecord = (handler instanceof IgnorableXlsRecordHandler)
- && xlsReadContext.xlsReadSheetHolder() != null && xlsReadContext.xlsReadSheetHolder().getIgnoreRecord();
+ boolean ignoreRecord =
+ (handler instanceof IgnorableXlsRecordHandler) && xlsReadContext.xlsReadWorkbookHolder().getIgnoreRecord();
if (ignoreRecord) {
// No need to read the current sheet
return;
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 66e3ab76..3e6713c4 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
@@ -22,10 +22,11 @@ public class BofRecordHandler extends AbstractXlsRecordHandler {
@Override
public void processRecord(XlsReadContext xlsReadContext, Record record) {
- BOFRecord br = (BOFRecord)record;
+ BOFRecord br = (BOFRecord) record;
XlsReadWorkbookHolder xlsReadWorkbookHolder = xlsReadContext.xlsReadWorkbookHolder();
if (br.getType() == BOFRecord.TYPE_WORKBOOK) {
xlsReadWorkbookHolder.setReadSheetIndex(null);
+ xlsReadWorkbookHolder.setIgnoreRecord(Boolean.FALSE);
return;
}
if (br.getType() != BOFRecord.TYPE_WORKSHEET) {
@@ -38,15 +39,15 @@ public class BofRecordHandler extends AbstractXlsRecordHandler {
readSheetIndex = 0;
xlsReadWorkbookHolder.setReadSheetIndex(readSheetIndex);
}
- ReadSheet readSheet = xlsReadWorkbookHolder.getActualSheetDataList().get(readSheetIndex);
- assert readSheet != null : "Can't find the sheet.";
+ ReadSheet actualReadSheet = xlsReadWorkbookHolder.getActualSheetDataList().get(readSheetIndex);
+ assert actualReadSheet != null : "Can't find the sheet.";
// Copy the parameter to the current sheet
- readSheet = SheetUtils.match(readSheet, xlsReadContext);
+ ReadSheet readSheet = SheetUtils.match(actualReadSheet, xlsReadContext);
if (readSheet != null) {
xlsReadContext.currentSheet(readSheet);
- xlsReadContext.xlsReadSheetHolder().setIgnoreRecord(Boolean.FALSE);
+ xlsReadContext.xlsReadWorkbookHolder().setIgnoreRecord(Boolean.FALSE);
} else {
- xlsReadContext.xlsReadSheetHolder().setIgnoreRecord(Boolean.TRUE);
+ xlsReadContext.xlsReadWorkbookHolder().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/EofRecordHandler.java b/src/main/java/com/alibaba/excel/analysis/v03/handlers/EofRecordHandler.java
index 0ca7313e..32b5b882 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
@@ -1,9 +1,16 @@
package com.alibaba.excel.analysis.v03.handlers;
+import java.util.LinkedHashMap;
+
+import org.apache.poi.hssf.eventusermodel.dummyrecord.LastCellOfRowDummyRecord;
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.metadata.Cell;
+import com.alibaba.excel.read.metadata.holder.ReadRowHolder;
+import com.alibaba.excel.read.metadata.holder.xls.XlsReadSheetHolder;
/**
* Record handler
@@ -14,8 +21,21 @@ public class EofRecordHandler extends AbstractXlsRecordHandler implements Ignora
@Override
public void processRecord(XlsReadContext xlsReadContext, Record record) {
- if (xlsReadContext.readSheetHolder() != null) {
- xlsReadContext.analysisEventProcessor().endSheet(xlsReadContext);
+ if (xlsReadContext.readSheetHolder() == null) {
+ return;
+ }
+ // Sometimes tables lack the end record of the last column
+ if (!xlsReadContext.xlsReadSheetHolder().getCellMap().isEmpty()) {
+ XlsReadSheetHolder xlsReadSheetHolder = xlsReadContext.xlsReadSheetHolder();
+ // Forge a termination data
+ xlsReadContext.readRowHolder(new ReadRowHolder(xlsReadContext.xlsReadSheetHolder().getRowIndex() + 1,
+ xlsReadSheetHolder.getTempRowType(),
+ xlsReadContext.readSheetHolder().getGlobalConfiguration(), xlsReadSheetHolder.getCellMap()));
+ xlsReadContext.analysisEventProcessor().endRow(xlsReadContext);
+ xlsReadSheetHolder.setCellMap(new LinkedHashMap());
+ xlsReadSheetHolder.setTempRowType(RowTypeEnum.EMPTY);
}
+
+ xlsReadContext.analysisEventProcessor().endSheet(xlsReadContext);
}
}
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 099b3087..5f18b841 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
@@ -3,20 +3,21 @@ package com.alibaba.excel.analysis.v03.handlers;
import java.math.BigDecimal;
import java.util.Map;
-import org.apache.poi.hssf.model.HSSFFormulaParser;
-import org.apache.poi.hssf.record.FormulaRecord;
-import org.apache.poi.hssf.record.Record;
-import org.apache.poi.ss.usermodel.CellType;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
import com.alibaba.excel.analysis.v03.IgnorableXlsRecordHandler;
import com.alibaba.excel.constant.BuiltinFormats;
import com.alibaba.excel.context.xls.XlsReadContext;
import com.alibaba.excel.enums.CellDataTypeEnum;
+import com.alibaba.excel.enums.RowTypeEnum;
import com.alibaba.excel.metadata.Cell;
import com.alibaba.excel.metadata.CellData;
+import org.apache.poi.hssf.model.HSSFFormulaParser;
+import org.apache.poi.hssf.record.FormulaRecord;
+import org.apache.poi.hssf.record.Record;
+import org.apache.poi.ss.usermodel.CellType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
/**
* Record handler
*
@@ -30,7 +31,7 @@ public class FormulaRecordHandler extends AbstractXlsRecordHandler implements Ig
public void processRecord(XlsReadContext xlsReadContext, Record record) {
FormulaRecord frec = (FormulaRecord)record;
Map cellMap = xlsReadContext.xlsReadSheetHolder().getCellMap();
- CellData tempCellData = new CellData();
+ CellData> tempCellData = new CellData<>();
tempCellData.setRowIndex(frec.getRow());
tempCellData.setColumnIndex((int)frec.getColumn());
CellType cellType = CellType.forInt(frec.getCachedResultType());
@@ -43,6 +44,7 @@ public class FormulaRecordHandler extends AbstractXlsRecordHandler implements Ig
}
tempCellData.setFormula(Boolean.TRUE);
tempCellData.setFormulaValue(formulaValue);
+ xlsReadContext.xlsReadSheetHolder().setTempRowType(RowTypeEnum.DATA);
switch (cellType) {
case STRING:
// Formula result is a string
@@ -55,8 +57,9 @@ public class FormulaRecordHandler extends AbstractXlsRecordHandler implements Ig
tempCellData.setNumberValue(BigDecimal.valueOf(frec.getValue()));
Integer dataFormat =
xlsReadContext.xlsReadWorkbookHolder().getFormatTrackingHSSFListener().getFormatIndex(frec);
- tempCellData.setDataFormat(dataFormat);
- tempCellData.setDataFormatString(BuiltinFormats.getBuiltinFormat(dataFormat,
+ Short dataFormatShort = dataFormat.shortValue();
+ tempCellData.setDataFormat(dataFormatShort);
+ tempCellData.setDataFormatString(BuiltinFormats.getBuiltinFormat(dataFormatShort,
xlsReadContext.xlsReadWorkbookHolder().getFormatTrackingHSSFListener().getFormatString(frec),
xlsReadContext.readSheetHolder().getGlobalConfiguration().getLocale()));
cellMap.put((int)frec.getColumn(), tempCellData);
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 50608095..f9e27c7a 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
@@ -2,15 +2,15 @@ package com.alibaba.excel.analysis.v03.handlers;
import java.math.BigDecimal;
-import org.apache.poi.hssf.record.NumberRecord;
-import org.apache.poi.hssf.record.Record;
-
import com.alibaba.excel.analysis.v03.IgnorableXlsRecordHandler;
import com.alibaba.excel.constant.BuiltinFormats;
import com.alibaba.excel.context.xls.XlsReadContext;
import com.alibaba.excel.enums.RowTypeEnum;
import com.alibaba.excel.metadata.CellData;
+import org.apache.poi.hssf.record.NumberRecord;
+import org.apache.poi.hssf.record.Record;
+
/**
* Record handler
*
@@ -21,8 +21,9 @@ public class NumberRecordHandler extends AbstractXlsRecordHandler implements Ign
@Override
public void processRecord(XlsReadContext xlsReadContext, Record record) {
NumberRecord nr = (NumberRecord)record;
- CellData cellData = CellData.newInstance(BigDecimal.valueOf(nr.getValue()), nr.getRow(), (int)nr.getColumn());
- Integer dataFormat = xlsReadContext.xlsReadWorkbookHolder().getFormatTrackingHSSFListener().getFormatIndex(nr);
+ CellData>cellData = CellData.newInstance(BigDecimal.valueOf(nr.getValue()), nr.getRow(), (int)nr.getColumn());
+ short dataFormat = (short)xlsReadContext.xlsReadWorkbookHolder().getFormatTrackingHSSFListener().getFormatIndex(
+ nr);
cellData.setDataFormat(dataFormat);
cellData.setDataFormatString(BuiltinFormats.getBuiltinFormat(dataFormat,
xlsReadContext.xlsReadWorkbookHolder().getFormatTrackingHSSFListener().getFormatString(nr),
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 3b95cfdb..2408d219 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
@@ -23,7 +23,7 @@ public class StringRecordHandler extends AbstractXlsRecordHandler implements Ign
// String for formula
StringRecord srec = (StringRecord)record;
XlsReadSheetHolder xlsReadSheetHolder = xlsReadContext.xlsReadSheetHolder();
- CellData tempCellData = xlsReadSheetHolder.getTempCellData();
+ CellData>tempCellData = xlsReadSheetHolder.getTempCellData();
if (tempCellData == null) {
LOGGER.warn("String type formula but no value found.");
return;
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 a0a9af0e..1b6e6a8b 100644
--- a/src/main/java/com/alibaba/excel/analysis/v07/XlsxSaxAnalyser.java
+++ b/src/main/java/com/alibaba/excel/analysis/v07/XlsxSaxAnalyser.java
@@ -9,9 +9,26 @@ import java.util.List;
import java.util.Map;
import java.util.UUID;
+import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
+import com.alibaba.excel.analysis.ExcelReadExecutor;
+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.FileUtils;
+import com.alibaba.excel.util.SheetUtils;
+import com.alibaba.excel.util.StringUtils;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackageAccess;
import org.apache.poi.openxml4j.opc.PackagePart;
@@ -25,26 +42,13 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorkbookPr;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.WorkbookDocument;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
-import com.alibaba.excel.analysis.ExcelReadExecutor;
-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;
-import com.alibaba.excel.util.FileUtils;
-import com.alibaba.excel.util.SheetUtils;
-import com.alibaba.excel.util.StringUtils;
-
/**
* @author jipengfei
*/
+@Slf4j
public class XlsxSaxAnalyser implements ExcelReadExecutor {
private XlsxReadContext xlsxReadContext;
@@ -78,7 +82,9 @@ public class XlsxSaxAnalyser implements ExcelReadExecutor {
XSSFReader xssfReader = new XSSFReader(pkg);
analysisUse1904WindowDate(xssfReader, xlsxReadWorkbookHolder);
- xlsxReadWorkbookHolder.setStylesTable(xssfReader.getStylesTable());
+ // set style table
+ setStylesTable(xlsxReadWorkbookHolder, xssfReader);
+
sheetList = new ArrayList();
sheetMap = new HashMap();
commentsTableMap = new HashMap();
@@ -101,6 +107,17 @@ public class XlsxSaxAnalyser implements ExcelReadExecutor {
}
}
+ private void setStylesTable(XlsxReadWorkbookHolder xlsxReadWorkbookHolder, XSSFReader xssfReader) {
+ try {
+ xlsxReadWorkbookHolder.setStylesTable(xssfReader.getStylesTable());
+ } catch (Exception e) {
+ log.warn(
+ "Currently excel cannot get style information, but it doesn't affect the data analysis.You can try to"
+ + " save the file with office again or ignore the current error.",
+ e);
+ }
+ }
+
private void defaultReadCache(XlsxReadWorkbookHolder xlsxReadWorkbookHolder,
PackagePart sharedStringsTablePackagePart) {
ReadCache readCache = xlsxReadWorkbookHolder.getReadCacheSelector().readCache(sharedStringsTablePackagePart);
@@ -147,9 +164,10 @@ public class XlsxSaxAnalyser implements ExcelReadExecutor {
xlsxReadWorkbookHolder.setTempFile(readTempFile);
File tempFile = new File(readTempFile.getPath(), UUID.randomUUID().toString() + ".xlsx");
if (decryptedStream != null) {
- FileUtils.writeToFile(tempFile, decryptedStream);
+ FileUtils.writeToFile(tempFile, decryptedStream, false);
} else {
- FileUtils.writeToFile(tempFile, xlsxReadWorkbookHolder.getInputStream());
+ FileUtils.writeToFile(tempFile, xlsxReadWorkbookHolder.getInputStream(),
+ xlsxReadWorkbookHolder.getAutoCloseStream());
}
return OPCPackage.open(tempFile, PackageAccess.READ);
}
@@ -177,9 +195,7 @@ public class XlsxSaxAnalyser implements ExcelReadExecutor {
xmlReader.setContentHandler(handler);
xmlReader.parse(inputSource);
inputStream.close();
- } catch (ExcelAnalysisException e) {
- throw e;
- } catch (Exception e) {
+ } catch (IOException | ParserConfigurationException | SAXException e) {
throw new ExcelAnalysisException(e);
} finally {
if (inputStream != null) {
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
index 3521e46a..770355b0 100644
--- a/src/main/java/com/alibaba/excel/analysis/v07/handlers/AbstractCellValueTagHandler.java
+++ b/src/main/java/com/alibaba/excel/analysis/v07/handlers/AbstractCellValueTagHandler.java
@@ -7,6 +7,7 @@ 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;
+import com.alibaba.excel.util.StringUtils;
/**
* Cell Value Handler
@@ -20,6 +21,7 @@ public abstract class AbstractCellValueTagHandler extends AbstractXlsxTagHandler
XlsxReadSheetHolder xlsxReadSheetHolder = xlsxReadContext.xlsxReadSheetHolder();
CellData tempCellData = xlsxReadSheetHolder.getTempCellData();
StringBuilder tempData = xlsxReadSheetHolder.getTempData();
+ String tempDataString = tempData.toString();
CellDataTypeEnum oldType = tempCellData.getType();
switch (oldType) {
case DIRECT_STRING:
@@ -28,10 +30,18 @@ public abstract class AbstractCellValueTagHandler extends AbstractXlsxTagHandler
tempCellData.setStringValue(tempData.toString());
break;
case BOOLEAN:
+ if(StringUtils.isEmpty(tempDataString)){
+ tempCellData.setType(CellDataTypeEnum.EMPTY);
+ break;
+ }
tempCellData.setBooleanValue(BooleanUtils.valueOf(tempData.toString()));
break;
case NUMBER:
case EMPTY:
+ if(StringUtils.isEmpty(tempDataString)){
+ tempCellData.setType(CellDataTypeEnum.EMPTY);
+ break;
+ }
tempCellData.setType(CellDataTypeEnum.NUMBER);
tempCellData.setNumberValue(new BigDecimal(tempData.toString()));
break;
@@ -44,7 +54,7 @@ public abstract class AbstractCellValueTagHandler extends AbstractXlsxTagHandler
if (tempCellData.getStringValue() != null
&& xlsxReadContext.currentReadHolder().globalConfiguration().getAutoTrim()) {
- tempCellData.setStringValue(tempCellData.getStringValue());
+ tempCellData.setStringValue(tempCellData.getStringValue().trim());
}
tempCellData.checkEmpty();
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
index 277348a7..3058e8e8 100644
--- a/src/main/java/com/alibaba/excel/analysis/v07/handlers/CellInlineStringValueTagHandler.java
+++ b/src/main/java/com/alibaba/excel/analysis/v07/handlers/CellInlineStringValueTagHandler.java
@@ -15,7 +15,7 @@ public class CellInlineStringValueTagHandler extends AbstractCellValueTagHandler
@Override
protected void setStringValue(XlsxReadContext xlsxReadContext) {
// This is a special form of string
- CellData tempCellData = xlsxReadContext.xlsxReadSheetHolder().getTempCellData();
+ 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
index fe5a6421..135153e0 100644
--- a/src/main/java/com/alibaba/excel/analysis/v07/handlers/CellTagHandler.java
+++ b/src/main/java/com/alibaba/excel/analysis/v07/handlers/CellTagHandler.java
@@ -1,8 +1,5 @@
package com.alibaba.excel.analysis.v07.handlers;
-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;
@@ -12,6 +9,10 @@ import com.alibaba.excel.read.metadata.holder.xlsx.XlsxReadSheetHolder;
import com.alibaba.excel.util.PositionUtils;
import com.alibaba.excel.util.StringUtils;
+import org.apache.poi.xssf.model.StylesTable;
+import org.apache.poi.xssf.usermodel.XSSFCellStyle;
+import org.xml.sax.Attributes;
+
/**
* Cell Handler
*
@@ -46,9 +47,12 @@ public class CellTagHandler extends AbstractXlsxTagHandler {
} else {
dateFormatIndexInteger = Integer.parseInt(dateFormatIndex);
}
- XSSFCellStyle xssfCellStyle =
- xlsxReadContext.xlsxReadWorkbookHolder().getStylesTable().getStyleAt(dateFormatIndexInteger);
- int dataFormat = xssfCellStyle.getDataFormat();
+ StylesTable stylesTable = xlsxReadContext.xlsxReadWorkbookHolder().getStylesTable();
+ if (stylesTable == null) {
+ return;
+ }
+ XSSFCellStyle xssfCellStyle = stylesTable.getStyleAt(dateFormatIndexInteger);
+ short 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
index 09c9264e..7e685c97 100644
--- a/src/main/java/com/alibaba/excel/analysis/v07/handlers/CellValueTagHandler.java
+++ b/src/main/java/com/alibaba/excel/analysis/v07/handlers/CellValueTagHandler.java
@@ -3,6 +3,7 @@ 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;
+import com.alibaba.excel.util.StringUtils;
/**
* Cell Value Handler
@@ -17,6 +18,10 @@ public class CellValueTagHandler extends AbstractCellValueTagHandler {
CellData tempCellData = xlsxReadContext.xlsxReadSheetHolder().getTempCellData();
switch (tempCellData.getType()) {
case STRING:
+ // In some cases, although cell type is a string, it may be an empty tag
+ if(StringUtils.isEmpty(tempCellData.getStringValue())){
+ break;
+ }
String stringValue = xlsxReadContext.readWorkbookHolder().getReadCache()
.get(Integer.valueOf(tempCellData.getStringValue()));
if (stringValue != null && xlsxReadContext.currentReadHolder().globalConfiguration().getAutoTrim()) {
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
index 61f38733..37965254 100644
--- a/src/main/java/com/alibaba/excel/analysis/v07/handlers/RowTagHandler.java
+++ b/src/main/java/com/alibaba/excel/analysis/v07/handlers/RowTagHandler.java
@@ -2,8 +2,6 @@ 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;
@@ -12,6 +10,9 @@ import com.alibaba.excel.read.metadata.holder.ReadRowHolder;
import com.alibaba.excel.read.metadata.holder.xlsx.XlsxReadSheetHolder;
import com.alibaba.excel.util.PositionUtils;
+import org.apache.commons.collections4.MapUtils;
+import org.xml.sax.Attributes;
+
/**
* Cell Handler
*
@@ -25,15 +26,13 @@ public class RowTagHandler extends AbstractXlsxTagHandler {
int rowIndex = PositionUtils.getRowByRowTagt(attributes.getValue(ExcelXmlConstants.ATTRIBUTE_R),
xlsxReadSheetHolder.getRowIndex());
Integer lastRowIndex = xlsxReadContext.readSheetHolder().getRowIndex();
- if (lastRowIndex != null) {
- while (lastRowIndex + 1 < rowIndex) {
- xlsxReadContext.readRowHolder(new ReadRowHolder(lastRowIndex + 1, RowTypeEnum.EMPTY,
- xlsxReadSheetHolder.getGlobalConfiguration(), new LinkedHashMap()));
- xlsxReadContext.analysisEventProcessor().endRow(xlsxReadContext);
- xlsxReadSheetHolder.setColumnIndex(null);
- xlsxReadSheetHolder.setCellMap(new LinkedHashMap());
- lastRowIndex++;
- }
+ while (lastRowIndex + 1 < rowIndex) {
+ xlsxReadContext.readRowHolder(new ReadRowHolder(lastRowIndex + 1, RowTypeEnum.EMPTY,
+ xlsxReadSheetHolder.getGlobalConfiguration(), new LinkedHashMap()));
+ xlsxReadContext.analysisEventProcessor().endRow(xlsxReadContext);
+ xlsxReadSheetHolder.setColumnIndex(null);
+ xlsxReadSheetHolder.setCellMap(new LinkedHashMap());
+ lastRowIndex++;
}
xlsxReadSheetHolder.setRowIndex(rowIndex);
}
@@ -41,11 +40,12 @@ public class RowTagHandler extends AbstractXlsxTagHandler {
@Override
public void endElement(XlsxReadContext xlsxReadContext, String name) {
XlsxReadSheetHolder xlsxReadSheetHolder = xlsxReadContext.xlsxReadSheetHolder();
- xlsxReadContext.readRowHolder(new ReadRowHolder(xlsxReadSheetHolder.getRowIndex(), RowTypeEnum.DATA,
+ RowTypeEnum rowType = MapUtils.isEmpty(xlsxReadSheetHolder.getCellMap()) ? RowTypeEnum.EMPTY : RowTypeEnum.DATA;
+ xlsxReadContext.readRowHolder(new ReadRowHolder(xlsxReadSheetHolder.getRowIndex(), rowType,
xlsxReadSheetHolder.getGlobalConfiguration(), xlsxReadSheetHolder.getCellMap()));
xlsxReadContext.analysisEventProcessor().endRow(xlsxReadContext);
xlsxReadSheetHolder.setColumnIndex(null);
- xlsxReadSheetHolder.setCellMap(new LinkedHashMap());
+ xlsxReadSheetHolder.setCellMap(new LinkedHashMap<>());
}
}
diff --git a/src/main/java/com/alibaba/excel/annotation/ExcelProperty.java b/src/main/java/com/alibaba/excel/annotation/ExcelProperty.java
index b107d32e..e2b169e3 100644
--- a/src/main/java/com/alibaba/excel/annotation/ExcelProperty.java
+++ b/src/main/java/com/alibaba/excel/annotation/ExcelProperty.java
@@ -23,7 +23,7 @@ public @interface ExcelProperty {
*
* write: It automatically merges when you have more than one head
*
- * read: When you have multiple heads, take the first one
+ * read: When you have multiple heads, take the last one
*
* @return The name of the sheet header
*/
@@ -32,12 +32,23 @@ public @interface ExcelProperty {
/**
* Index of column
*
- * Read or write it on the index of column,If it's equal to -1, it's sorted by Java class
+ * Read or write it on the index of column,If it's equal to -1, it's sorted by Java class.
+ *
+ * priority: index > order > default sort
*
* @return Index of column
*/
int index() default -1;
+ /**
+ * Defines the sort order for an column.
+ *
+ * priority: index > order > default sort
+ *
+ * @return Order of column
+ */
+ int order() default Integer.MAX_VALUE;
+
/**
* Force the current field to use this converter.
*
diff --git a/src/main/java/com/alibaba/excel/cache/Ehcache.java b/src/main/java/com/alibaba/excel/cache/Ehcache.java
index 4e757fcd..a5250900 100644
--- a/src/main/java/com/alibaba/excel/cache/Ehcache.java
+++ b/src/main/java/com/alibaba/excel/cache/Ehcache.java
@@ -1,50 +1,49 @@
package com.alibaba.excel.cache;
import java.io.File;
-import java.util.HashMap;
+import java.util.ArrayList;
import java.util.UUID;
+import com.alibaba.excel.context.AnalysisContext;
+import com.alibaba.excel.util.FileUtils;
+import com.alibaba.excel.util.ListUtils;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
import org.ehcache.CacheManager;
import org.ehcache.config.CacheConfiguration;
import org.ehcache.config.builders.CacheConfigurationBuilder;
import org.ehcache.config.builders.CacheManagerBuilder;
import org.ehcache.config.builders.ResourcePoolsBuilder;
import org.ehcache.config.units.MemoryUnit;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.alibaba.excel.context.AnalysisContext;
-import com.alibaba.excel.util.CollectionUtils;
-import com.alibaba.excel.util.FileUtils;
/**
* Default cache
*
* @author Jiaju Zhuang
*/
+@Slf4j
public class Ehcache implements ReadCache {
-
- private static final Logger LOGGER = LoggerFactory.getLogger(Ehcache.class);
- private static final int BATCH_COUNT = 1000;
- private static final int DEBUG_WRITE_SIZE = 100 * 10000;
- private static final int DEBUG_CACHE_MISS_SIZE = 1000;
+ public static final int BATCH_COUNT = 1000;
/**
* Key index
*/
- private int index = 0;
- private HashMap dataMap = new HashMap(BATCH_COUNT * 4 / 3 + 1);
- private static CacheManager fileCacheManager;
- private static CacheConfiguration fileCacheConfiguration;
- private static CacheManager activeCacheManager;
- private CacheConfiguration activeCacheConfiguration;
+ private int activeIndex = 0;
+ public static final int DEBUG_CACHE_MISS_SIZE = 1000;
+ public static final int DEBUG_WRITE_SIZE = 100 * 10000;
+ private ArrayList dataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
+ private static final CacheManager FILE_CACHE_MANAGER;
+ private static final CacheConfiguration FILE_CACHE_CONFIGURATION;
+ private static final CacheManager ACTIVE_CACHE_MANAGER;
+ private final CacheConfiguration activeCacheConfiguration;
/**
* Bulk storage data
*/
- private org.ehcache.Cache fileCache;
+ private org.ehcache.Cache fileCache;
/**
* Currently active cache
*/
- private org.ehcache.Cache activeCache;
+ private org.ehcache.Cache activeCache;
private String cacheAlias;
/**
* Count the number of cache misses
@@ -53,7 +52,7 @@ public class Ehcache implements ReadCache {
public Ehcache(int maxCacheActivateSize) {
activeCacheConfiguration = CacheConfigurationBuilder
- .newCacheConfigurationBuilder(Integer.class, HashMap.class,
+ .newCacheConfigurationBuilder(Integer.class, ArrayList.class,
ResourcePoolsBuilder.newResourcePoolsBuilder().heap(maxCacheActivateSize, MemoryUnit.MB))
.withSizeOfMaxObjectGraph(1000 * 1000L).withSizeOfMaxObjectSize(maxCacheActivateSize, MemoryUnit.MB)
.build();
@@ -61,11 +60,11 @@ public class Ehcache implements ReadCache {
static {
File cacheFile = FileUtils.createCacheTmpFile();
- fileCacheManager =
+ FILE_CACHE_MANAGER =
CacheManagerBuilder.newCacheManagerBuilder().with(CacheManagerBuilder.persistence(cacheFile)).build(true);
- activeCacheManager = CacheManagerBuilder.newCacheManagerBuilder().build(true);
- fileCacheConfiguration = CacheConfigurationBuilder
- .newCacheConfigurationBuilder(Integer.class, HashMap.class,
+ ACTIVE_CACHE_MANAGER = CacheManagerBuilder.newCacheManagerBuilder().build(true);
+ FILE_CACHE_CONFIGURATION = CacheConfigurationBuilder
+ .newCacheConfigurationBuilder(Integer.class, ArrayList.class,
ResourcePoolsBuilder.newResourcePoolsBuilder().disk(10, MemoryUnit.GB))
.withSizeOfMaxObjectGraph(1000 * 1000L).withSizeOfMaxObjectSize(10, MemoryUnit.GB).build();
}
@@ -73,21 +72,22 @@ public class Ehcache implements ReadCache {
@Override
public void init(AnalysisContext analysisContext) {
cacheAlias = UUID.randomUUID().toString();
- fileCache = fileCacheManager.createCache(cacheAlias, fileCacheConfiguration);
- activeCache = activeCacheManager.createCache(cacheAlias, activeCacheConfiguration);
+ fileCache = FILE_CACHE_MANAGER.createCache(cacheAlias, FILE_CACHE_CONFIGURATION);
+ activeCache = ACTIVE_CACHE_MANAGER.createCache(cacheAlias, activeCacheConfiguration);
}
@Override
public void put(String value) {
- dataMap.put(index, value);
- if ((index + 1) % BATCH_COUNT == 0) {
- fileCache.put(index / BATCH_COUNT, dataMap);
- dataMap = new HashMap(BATCH_COUNT * 4 / 3 + 1);
+ dataList.add(value);
+ if (dataList.size() >= BATCH_COUNT) {
+ fileCache.put(activeIndex, dataList);
+ activeIndex++;
+ dataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
}
- index++;
- if (LOGGER.isDebugEnabled()) {
- if (index % DEBUG_WRITE_SIZE == 0) {
- LOGGER.debug("Already put :{}", index);
+ if (log.isDebugEnabled()) {
+ int alreadyPut = activeIndex * BATCH_COUNT + dataList.size();
+ if (alreadyPut % DEBUG_WRITE_SIZE == 0) {
+ log.debug("Already put :{}", alreadyPut);
}
}
}
@@ -98,31 +98,31 @@ public class Ehcache implements ReadCache {
return null;
}
int route = key / BATCH_COUNT;
- HashMap dataMap = activeCache.get(route);
- if (dataMap == null) {
- dataMap = fileCache.get(route);
- activeCache.put(route, dataMap);
- if (LOGGER.isDebugEnabled()) {
+ ArrayList dataList = activeCache.get(route);
+ if (dataList == null) {
+ dataList = fileCache.get(route);
+ activeCache.put(route, dataList);
+ if (log.isDebugEnabled()) {
if (cacheMiss++ % DEBUG_CACHE_MISS_SIZE == 0) {
- LOGGER.debug("Cache misses count:{}", cacheMiss);
+ log.debug("Cache misses count:{}", cacheMiss);
}
}
}
- return dataMap.get(key);
+ return dataList.get(key % BATCH_COUNT);
}
@Override
public void putFinished() {
- if (CollectionUtils.isEmpty(dataMap)) {
+ if (CollectionUtils.isEmpty(dataList)) {
return;
}
- fileCache.put(index / BATCH_COUNT, dataMap);
+ fileCache.put(activeIndex, dataList);
}
@Override
public void destroy() {
- fileCacheManager.removeCache(cacheAlias);
- activeCacheManager.removeCache(cacheAlias);
+ FILE_CACHE_MANAGER.removeCache(cacheAlias);
+ ACTIVE_CACHE_MANAGER.removeCache(cacheAlias);
}
}
diff --git a/src/main/java/com/alibaba/excel/cache/MapCache.java b/src/main/java/com/alibaba/excel/cache/MapCache.java
index ae948fbc..f83a1233 100644
--- a/src/main/java/com/alibaba/excel/cache/MapCache.java
+++ b/src/main/java/com/alibaba/excel/cache/MapCache.java
@@ -1,26 +1,24 @@
package com.alibaba.excel.cache;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.ArrayList;
+import java.util.List;
import com.alibaba.excel.context.AnalysisContext;
/**
- *
* Putting temporary data directly into a map is a little more efficient but very memory intensive
*
* @author Jiaju Zhuang
*/
public class MapCache implements ReadCache {
- private Map cache = new HashMap();
- private int index = 0;
+ private List cache = new ArrayList<>();
@Override
public void init(AnalysisContext analysisContext) {}
@Override
public void put(String value) {
- cache.put(index++, value);
+ cache.add(value);
}
@Override
diff --git a/src/main/java/com/alibaba/excel/constant/BuiltinFormats.java b/src/main/java/com/alibaba/excel/constant/BuiltinFormats.java
index 95eb0b8f..b742cb6c 100644
--- a/src/main/java/com/alibaba/excel/constant/BuiltinFormats.java
+++ b/src/main/java/com/alibaba/excel/constant/BuiltinFormats.java
@@ -17,7 +17,9 @@ import java.util.Locale;
**/
public class BuiltinFormats {
- private static final String[] BUILTIN_FORMATS_CN = {
+ public static short GENERAL = 0;
+
+ public static final String[] BUILTIN_FORMATS_CN = {
// 0
"General",
// 1
@@ -189,7 +191,7 @@ public class BuiltinFormats {
// end
};
- private static final String[] BUILTIN_FORMATS_US = {
+ public static final String[] BUILTIN_FORMATS_US = {
// 0
"General",
// 1
@@ -361,7 +363,7 @@ public class BuiltinFormats {
// end
};
- public static String getBuiltinFormat(Integer index, String defaultFormat, Locale locale) {
+ public static String getBuiltinFormat(Short index, String defaultFormat, Locale locale) {
String[] builtinFormat = switchBuiltinFormats(locale);
if (index == null || index < 0 || index >= builtinFormat.length) {
return defaultFormat;
diff --git a/src/main/java/com/alibaba/excel/constant/OrderConstant.java b/src/main/java/com/alibaba/excel/constant/OrderConstant.java
new file mode 100644
index 00000000..a955025c
--- /dev/null
+++ b/src/main/java/com/alibaba/excel/constant/OrderConstant.java
@@ -0,0 +1,13 @@
+package com.alibaba.excel.constant;
+
+/**
+ * Order constant.
+ *
+ * @author Jiaju Zhuang
+ */
+public class OrderConstant {
+ /**
+ * Sorting of styles written to cells.
+ */
+ public static final int FILL_DATA_FORMAT = 10000;
+}
diff --git a/src/main/java/com/alibaba/excel/context/WriteContextImpl.java b/src/main/java/com/alibaba/excel/context/WriteContextImpl.java
index 8465cbd2..648a7fe9 100644
--- a/src/main/java/com/alibaba/excel/context/WriteContextImpl.java
+++ b/src/main/java/com/alibaba/excel/context/WriteContextImpl.java
@@ -6,22 +6,6 @@ import java.io.OutputStream;
import java.util.Map;
import java.util.UUID;
-import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
-import org.apache.poi.openxml4j.opc.OPCPackage;
-import org.apache.poi.openxml4j.opc.PackageAccess;
-import org.apache.poi.poifs.crypt.EncryptionInfo;
-import org.apache.poi.poifs.crypt.EncryptionMode;
-import org.apache.poi.poifs.crypt.Encryptor;
-import org.apache.poi.poifs.filesystem.POIFSFileSystem;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.ss.util.CellRangeAddress;
-import org.apache.poi.xssf.streaming.SXSSFWorkbook;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
import com.alibaba.excel.enums.WriteTypeEnum;
import com.alibaba.excel.exception.ExcelGenerateException;
import com.alibaba.excel.metadata.CellData;
@@ -42,6 +26,22 @@ import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import com.alibaba.excel.write.property.ExcelWriteHeadProperty;
+import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
+import org.apache.poi.openxml4j.opc.OPCPackage;
+import org.apache.poi.openxml4j.opc.PackageAccess;
+import org.apache.poi.poifs.crypt.EncryptionInfo;
+import org.apache.poi.poifs.crypt.EncryptionMode;
+import org.apache.poi.poifs.crypt.Encryptor;
+import org.apache.poi.poifs.filesystem.POIFSFileSystem;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.xssf.streaming.SXSSFWorkbook;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
/**
* A context is the main anchorage point of a excel writer.
*
@@ -50,6 +50,7 @@ import com.alibaba.excel.write.property.ExcelWriteHeadProperty;
public class WriteContextImpl implements WriteContext {
private static final Logger LOGGER = LoggerFactory.getLogger(WriteContextImpl.class);
+ private static final String NO_SHEETS="no sheets";
/**
* The Workbook currently written
@@ -111,15 +112,25 @@ public class WriteContextImpl implements WriteContext {
if (selectSheetFromCache(writeSheet)) {
return;
}
+
initCurrentSheetHolder(writeSheet);
+
+ // Workbook handler need to supplementary execution
+ WriteHandlerUtils.beforeWorkbookCreate(this, true);
+ WriteHandlerUtils.afterWorkbookCreate(this, true);
+
// Initialization current sheet
initSheet(writeType);
}
private boolean selectSheetFromCache(WriteSheet writeSheet) {
writeSheetHolder = null;
- if (writeSheet.getSheetNo() != null) {
- writeSheetHolder = writeWorkbookHolder.getHasBeenInitializedSheetIndexMap().get(writeSheet.getSheetNo());
+ Integer sheetNo = writeSheet.getSheetNo();
+ if (sheetNo == null && StringUtils.isEmpty(writeSheet.getSheetName())) {
+ sheetNo = 0;
+ }
+ if (sheetNo != null) {
+ writeSheetHolder = writeWorkbookHolder.getHasBeenInitializedSheetIndexMap().get(sheetNo);
}
if (writeSheetHolder == null && !StringUtils.isEmpty(writeSheet.getSheetName())) {
writeSheetHolder = writeWorkbookHolder.getHasBeenInitializedSheetNameMap().get(writeSheet.getSheetName());
@@ -153,17 +164,27 @@ public class WriteContextImpl implements WriteContext {
Sheet currentSheet;
try {
if (writeSheetHolder.getSheetNo() != null) {
- currentSheet = writeWorkbookHolder.getWorkbook().getSheetAt(writeSheetHolder.getSheetNo());
- writeSheetHolder
- .setCachedSheet(writeWorkbookHolder.getCachedWorkbook().getSheetAt(writeSheetHolder.getSheetNo()));
+ // When the add default sort order of appearance
+ if (WriteTypeEnum.ADD.equals(writeType) && writeWorkbookHolder.getTempTemplateInputStream() == null) {
+ currentSheet = createSheet();
+ } else {
+ currentSheet = writeWorkbookHolder.getWorkbook().getSheetAt(writeSheetHolder.getSheetNo());
+ writeSheetHolder
+ .setCachedSheet(
+ writeWorkbookHolder.getCachedWorkbook().getSheetAt(writeSheetHolder.getSheetNo()));
+ }
} else {
// sheet name must not null
currentSheet = writeWorkbookHolder.getWorkbook().getSheet(writeSheetHolder.getSheetName());
writeSheetHolder
.setCachedSheet(writeWorkbookHolder.getCachedWorkbook().getSheet(writeSheetHolder.getSheetName()));
}
- } catch (Exception e) {
- currentSheet = createSheet();
+ } catch (IllegalArgumentException e) {
+ if (e.getMessage() != null && e.getMessage().contains(NO_SHEETS)) {
+ currentSheet = createSheet();
+ } else {
+ throw e;
+ }
}
if (currentSheet == null) {
currentSheet = createSheet();
@@ -201,8 +222,8 @@ public class WriteContextImpl implements WriteContext {
if (currentWriteHolder.automaticMergeHead()) {
addMergedRegionToCurrentSheet(excelWriteHeadProperty, newRowIndex);
}
- for (int relativeRowIndex = 0, i = newRowIndex; i < excelWriteHeadProperty.getHeadRowNumber() + newRowIndex;
- i++, relativeRowIndex++) {
+ for (int relativeRowIndex = 0, i = newRowIndex; i < excelWriteHeadProperty.getHeadRowNumber()
+ + newRowIndex; i++, relativeRowIndex++) {
WriteHandlerUtils.beforeRowCreate(this, newRowIndex, relativeRowIndex, Boolean.TRUE);
Row row = WorkBookUtil.createRow(writeSheetHolder.getSheet(), i);
WriteHandlerUtils.afterRowCreate(this, row, relativeRowIndex, Boolean.TRUE);
@@ -227,7 +248,7 @@ public class WriteContextImpl implements WriteContext {
Cell cell = row.createCell(columnIndex);
WriteHandlerUtils.afterCellCreate(this, cell, head, relativeRowIndex, Boolean.TRUE);
cell.setCellValue(head.getHeadNameList().get(relativeRowIndex));
- WriteHandlerUtils.afterCellDispose(this, (CellData)null, cell, head, relativeRowIndex, Boolean.TRUE);
+ WriteHandlerUtils.afterCellDispose(this, (CellData) null, cell, head, relativeRowIndex, Boolean.TRUE);
}
}
@@ -251,7 +272,15 @@ public class WriteContextImpl implements WriteContext {
}
return;
}
+
initCurrentTableHolder(writeTable);
+
+ // Workbook and sheet handler need to supplementary execution
+ WriteHandlerUtils.beforeWorkbookCreate(this, true);
+ WriteHandlerUtils.afterWorkbookCreate(this, true);
+ WriteHandlerUtils.beforeSheetCreate(this, true);
+ WriteHandlerUtils.afterSheetCreate(this, true);
+
initHead(writeTableHolder.excelWriteHeadProperty());
}
@@ -322,7 +351,7 @@ public class WriteContextImpl implements WriteContext {
try {
Workbook workbook = writeWorkbookHolder.getWorkbook();
if (workbook instanceof SXSSFWorkbook) {
- ((SXSSFWorkbook)workbook).dispose();
+ ((SXSSFWorkbook) workbook).dispose();
}
} catch (Throwable t) {
throwable = t;
diff --git a/src/main/java/com/alibaba/excel/converters/AutoConverter.java b/src/main/java/com/alibaba/excel/converters/AutoConverter.java
index 800d2d85..07ad471f 100644
--- a/src/main/java/com/alibaba/excel/converters/AutoConverter.java
+++ b/src/main/java/com/alibaba/excel/converters/AutoConverter.java
@@ -10,10 +10,10 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty;
*
* @author Jiaju Zhuang
*/
-public class AutoConverter implements Converter {
+public class AutoConverter implements Converter