Browse Source

Merge branch '3.x' into master

developing
Jiaju Zhuang 4 years ago committed by GitHub
parent
commit
10bd7dc367
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 10
      README.md
  2. 46
      pom.xml
  3. 18
      src/main/java/com/alibaba/excel/ExcelWriter.java
  4. 2
      src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java
  5. 22
      src/main/java/com/alibaba/excel/analysis/v03/handlers/FormulaRecordHandler.java
  6. 11
      src/main/java/com/alibaba/excel/analysis/v03/handlers/NumberRecordHandler.java
  7. 2
      src/main/java/com/alibaba/excel/analysis/v03/handlers/StringRecordHandler.java
  8. 58
      src/main/java/com/alibaba/excel/analysis/v07/XlsxSaxAnalyser.java
  9. 12
      src/main/java/com/alibaba/excel/analysis/v07/handlers/AbstractCellValueTagHandler.java
  10. 2
      src/main/java/com/alibaba/excel/analysis/v07/handlers/CellInlineStringValueTagHandler.java
  11. 16
      src/main/java/com/alibaba/excel/analysis/v07/handlers/CellTagHandler.java
  12. 5
      src/main/java/com/alibaba/excel/analysis/v07/handlers/CellValueTagHandler.java
  13. 11
      src/main/java/com/alibaba/excel/analysis/v07/handlers/RowTagHandler.java
  14. 2
      src/main/java/com/alibaba/excel/annotation/ExcelProperty.java
  15. 92
      src/main/java/com/alibaba/excel/cache/Ehcache.java
  16. 10
      src/main/java/com/alibaba/excel/cache/MapCache.java
  17. 8
      src/main/java/com/alibaba/excel/constant/BuiltinFormats.java
  18. 13
      src/main/java/com/alibaba/excel/constant/OrderConstant.java
  19. 41
      src/main/java/com/alibaba/excel/context/WriteContextImpl.java
  20. 8
      src/main/java/com/alibaba/excel/converters/AutoConverter.java
  21. 78
      src/main/java/com/alibaba/excel/converters/Converter.java
  22. 14
      src/main/java/com/alibaba/excel/converters/ConverterKeyBuild.java
  23. 40
      src/main/java/com/alibaba/excel/converters/DefaultConverterLoader.java
  24. 10
      src/main/java/com/alibaba/excel/converters/bigdecimal/BigDecimalBooleanConverter.java
  25. 12
      src/main/java/com/alibaba/excel/converters/bigdecimal/BigDecimalNumberConverter.java
  26. 8
      src/main/java/com/alibaba/excel/converters/bigdecimal/BigDecimalStringConverter.java
  27. 8
      src/main/java/com/alibaba/excel/converters/booleanconverter/BooleanBooleanConverter.java
  28. 10
      src/main/java/com/alibaba/excel/converters/booleanconverter/BooleanNumberConverter.java
  29. 8
      src/main/java/com/alibaba/excel/converters/booleanconverter/BooleanStringConverter.java
  30. 8
      src/main/java/com/alibaba/excel/converters/bytearray/BoxingByteArrayImageConverter.java
  31. 8
      src/main/java/com/alibaba/excel/converters/bytearray/ByteArrayImageConverter.java
  32. 10
      src/main/java/com/alibaba/excel/converters/byteconverter/ByteBooleanConverter.java
  33. 12
      src/main/java/com/alibaba/excel/converters/byteconverter/ByteNumberConverter.java
  34. 8
      src/main/java/com/alibaba/excel/converters/byteconverter/ByteStringConverter.java
  35. 47
      src/main/java/com/alibaba/excel/converters/date/DateDateConverter.java
  36. 10
      src/main/java/com/alibaba/excel/converters/date/DateNumberConverter.java
  37. 10
      src/main/java/com/alibaba/excel/converters/date/DateStringConverter.java
  38. 10
      src/main/java/com/alibaba/excel/converters/doubleconverter/DoubleBooleanConverter.java
  39. 13
      src/main/java/com/alibaba/excel/converters/doubleconverter/DoubleNumberConverter.java
  40. 8
      src/main/java/com/alibaba/excel/converters/doubleconverter/DoubleStringConverter.java
  41. 8
      src/main/java/com/alibaba/excel/converters/file/FileImageConverter.java
  42. 10
      src/main/java/com/alibaba/excel/converters/floatconverter/FloatBooleanConverter.java
  43. 15
      src/main/java/com/alibaba/excel/converters/floatconverter/FloatNumberConverter.java
  44. 8
      src/main/java/com/alibaba/excel/converters/floatconverter/FloatStringConverter.java
  45. 8
      src/main/java/com/alibaba/excel/converters/inputstream/InputStreamImageConverter.java
  46. 10
      src/main/java/com/alibaba/excel/converters/integer/IntegerBooleanConverter.java
  47. 14
      src/main/java/com/alibaba/excel/converters/integer/IntegerNumberConverter.java
  48. 8
      src/main/java/com/alibaba/excel/converters/integer/IntegerStringConverter.java
  49. 10
      src/main/java/com/alibaba/excel/converters/longconverter/LongBooleanConverter.java
  50. 14
      src/main/java/com/alibaba/excel/converters/longconverter/LongNumberConverter.java
  51. 8
      src/main/java/com/alibaba/excel/converters/longconverter/LongStringConverter.java
  52. 10
      src/main/java/com/alibaba/excel/converters/shortconverter/ShortBooleanConverter.java
  53. 13
      src/main/java/com/alibaba/excel/converters/shortconverter/ShortNumberConverter.java
  54. 8
      src/main/java/com/alibaba/excel/converters/shortconverter/ShortStringConverter.java
  55. 8
      src/main/java/com/alibaba/excel/converters/string/StringBooleanConverter.java
  56. 8
      src/main/java/com/alibaba/excel/converters/string/StringErrorConverter.java
  57. 8
      src/main/java/com/alibaba/excel/converters/string/StringImageConverter.java
  58. 8
      src/main/java/com/alibaba/excel/converters/string/StringNumberConverter.java
  59. 8
      src/main/java/com/alibaba/excel/converters/string/StringStringConverter.java
  60. 8
      src/main/java/com/alibaba/excel/converters/url/UrlImageConverter.java
  61. 8
      src/main/java/com/alibaba/excel/enums/CellDataTypeEnum.java
  62. 2
      src/main/java/com/alibaba/excel/event/AnalysisEventListener.java
  63. 38
      src/main/java/com/alibaba/excel/exception/ExcelDataConvertException.java
  64. 8
      src/main/java/com/alibaba/excel/metadata/AbstractHolder.java
  65. 142
      src/main/java/com/alibaba/excel/metadata/CellData.java
  66. 2
      src/main/java/com/alibaba/excel/metadata/ConfigurationHolder.java
  67. 10
      src/main/java/com/alibaba/excel/metadata/format/DataFormatter.java
  68. 2
      src/main/java/com/alibaba/excel/metadata/property/ExcelHeadProperty.java
  69. 51
      src/main/java/com/alibaba/excel/read/listener/ModelBuildEventListener.java
  70. 2
      src/main/java/com/alibaba/excel/read/listener/ReadListener.java
  71. 18
      src/main/java/com/alibaba/excel/read/metadata/holder/AbstractReadHolder.java
  72. 6
      src/main/java/com/alibaba/excel/read/metadata/holder/ReadSheetHolder.java
  73. 4
      src/main/java/com/alibaba/excel/read/processor/DefaultAnalysisEventProcessor.java
  74. 75
      src/main/java/com/alibaba/excel/util/BooleanUtils.java
  75. 49
      src/main/java/com/alibaba/excel/util/ClassUtils.java
  76. 22
      src/main/java/com/alibaba/excel/util/CollectionUtils.java
  77. 49
      src/main/java/com/alibaba/excel/util/ConverterUtils.java
  78. 32
      src/main/java/com/alibaba/excel/util/DateUtils.java
  79. 145
      src/main/java/com/alibaba/excel/util/FieldUtils.java
  80. 24
      src/main/java/com/alibaba/excel/util/FileUtils.java
  81. 39
      src/main/java/com/alibaba/excel/util/IntUtils.java
  82. 121
      src/main/java/com/alibaba/excel/util/ListUtils.java
  83. 63
      src/main/java/com/alibaba/excel/util/MapUtils.java
  84. 54
      src/main/java/com/alibaba/excel/util/MemberUtils.java
  85. 2
      src/main/java/com/alibaba/excel/util/NumberDataFormatterUtils.java
  86. 24
      src/main/java/com/alibaba/excel/util/NumberUtils.java
  87. 87
      src/main/java/com/alibaba/excel/util/StringUtils.java
  88. 20
      src/main/java/com/alibaba/excel/util/StyleUtil.java
  89. 151
      src/main/java/com/alibaba/excel/util/Validate.java
  90. 25
      src/main/java/com/alibaba/excel/util/WorkBookUtil.java
  91. 38
      src/main/java/com/alibaba/excel/util/WriteHandlerUtils.java
  92. 7
      src/main/java/com/alibaba/excel/write/ExcelBuilder.java
  93. 10
      src/main/java/com/alibaba/excel/write/ExcelBuilderImpl.java
  94. 4
      src/main/java/com/alibaba/excel/write/builder/ExcelWriterSheetBuilder.java
  95. 4
      src/main/java/com/alibaba/excel/write/builder/ExcelWriterTableBuilder.java
  96. 59
      src/main/java/com/alibaba/excel/write/executor/AbstractExcelWriteExecutor.java
  97. 50
      src/main/java/com/alibaba/excel/write/executor/ExcelWriteAddExecutor.java
  98. 40
      src/main/java/com/alibaba/excel/write/executor/ExcelWriteFillExecutor.java
  99. 4
      src/main/java/com/alibaba/excel/write/handler/AbstractCellWriteHandler.java
  100. 6
      src/main/java/com/alibaba/excel/write/handler/AbstractRowWriteHandler.java
  101. Some files were not shown because too many files have changed in this diff Show More

10
README.md

@ -8,18 +8,18 @@ EasyExcel
[QQ2群: 1097936804](https://jq.qq.com/?_wv=1027&k=j5zEy6Xl) [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) [钉钉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) [钉钉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) [钉钉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://yuque.com/easyexcel](https://www.yuque.com/easyexcel/doc/easyexcel)
[常见问题](https://www.yuque.com/easyexcel/faq) [常见问题](https://www.yuque.com/easyexcel/faq)
#### 因为公司不方便用QQ,所以建议加钉钉群 #### 因为公司不方便用QQ,所以建议加钉钉群
# JAVA解析Excel工具EasyExcel # 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比较有名的框架有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 ## 64M内存1分钟内读取75M(46W行25列)的Excel
当然还有速模式能更快,但是内存占用会在100M多一点 当然还有速模式能更快,但是内存占用会在100M多一点
![img](img/readme/large.png) ![img](img/readme/large.png)
## 相关文档 ## 相关文档
@ -81,7 +81,7 @@ DEMO代码地址:[https://github.com/alibaba/easyexcel/blob/master/src/test/ja
@GetMapping("download") @GetMapping("download")
public void download(HttpServletResponse response) throws IOException { public void download(HttpServletResponse response) throws IOException {
// 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman // 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman
response.setContentType("application/vnd.ms-excel"); response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8");
// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系 // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20"); String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");

46
pom.xml

@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.alibaba</groupId> <groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId> <artifactId>easyexcel</artifactId>
<version>2.2.7</version> <version>3.0.0-beta1</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>easyexcel</name> <name>easyexcel</name>
@ -16,7 +16,7 @@
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jdk.version>1.6</jdk.version> <jdk.version>1.8</jdk.version>
<gpg.skip>true</gpg.skip> <gpg.skip>true</gpg.skip>
<maven.javadoc.skip>true</maven.javadoc.skip> <maven.javadoc.skip>true</maven.javadoc.skip>
</properties> </properties>
@ -60,22 +60,22 @@
<dependency> <dependency>
<groupId>org.apache.poi</groupId> <groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId> <artifactId>poi</artifactId>
<version>3.17</version> <version>4.1.2</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.poi</groupId> <groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId> <artifactId>poi-ooxml</artifactId>
<version>3.17</version> <version>4.1.2</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.poi</groupId> <groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId> <artifactId>poi-ooxml-schemas</artifactId>
<version>3.17</version> <version>4.1.2</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>cglib</groupId> <groupId>cglib</groupId>
<artifactId>cglib</artifactId> <artifactId>cglib</artifactId>
<version>3.1</version> <version>3.3.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.slf4j</groupId> <groupId>org.slf4j</groupId>
@ -85,8 +85,15 @@
<dependency> <dependency>
<groupId>org.ehcache</groupId> <groupId>org.ehcache</groupId>
<artifactId>ehcache</artifactId> <artifactId>ehcache</artifactId>
<version>3.4.0</version> <version>3.8.1</version>
</dependency> </dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
<scope>provided</scope>
</dependency>
<!--test--> <!--test-->
<dependency> <dependency>
<groupId>ch.qos.logback</groupId> <groupId>ch.qos.logback</groupId>
@ -100,12 +107,6 @@
<version>1.2.71</version> <version>1.2.71</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId> <artifactId>spring-boot</artifactId>
@ -121,7 +122,7 @@
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<version>4.12</version> <version>4.13.1</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>
@ -187,8 +188,8 @@
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<configuration> <configuration>
<source>1.6</source> <source>1.8</source>
<target>1.6</target> <target>1.8</target>
</configuration> </configuration>
</plugin> </plugin>
<plugin> <plugin>
@ -232,6 +233,19 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<plugin>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-maven-plugin</artifactId>
<version>1.18.20.0</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>delombok</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins> </plugins>
</build> </build>
</project> </project>

18
src/main/java/com/alibaba/excel/ExcelWriter.java

@ -3,6 +3,8 @@ package com.alibaba.excel;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List; import java.util.List;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -142,7 +144,7 @@ public class ExcelWriter {
* Write to this sheet * Write to this sheet
* @return this current writer * @return this current writer
*/ */
public ExcelWriter write(List data, WriteSheet writeSheet) { public ExcelWriter write(Collection<?> data, WriteSheet writeSheet) {
return write(data, writeSheet, null); return write(data, writeSheet, null);
} }
@ -157,7 +159,7 @@ public class ExcelWriter {
* Write to this table * Write to this table
* @return this * @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); excelBuilder.addContent(data, writeSheet, writeTable);
return this; return this;
} }
@ -194,7 +196,7 @@ public class ExcelWriter {
* @param sheet * @param sheet
* Write to this sheet * Write to this sheet
* @return this current writer * @return this current writer
* @deprecated please use {@link ExcelWriter#write(List, WriteSheet)} * @deprecated please use {@link ExcelWriter#write(Collection, WriteSheet)}
*/ */
@Deprecated @Deprecated
public ExcelWriter write(List data, Sheet sheet) { public ExcelWriter write(List data, Sheet sheet) {
@ -211,7 +213,7 @@ public class ExcelWriter {
* @param table * @param table
* Write to this table * Write to this table
* @return this * @return this
* @deprecated * @deprecated please use {@link ExcelWriter#write(List, WriteSheet,WriteTable)} * @deprecated * @deprecated please use {@link ExcelWriter#write(Collection, WriteSheet,WriteTable)}
*/ */
@Deprecated @Deprecated
public ExcelWriter write(List data, Sheet sheet, Table table) { public ExcelWriter write(List data, Sheet sheet, Table table) {
@ -246,7 +248,7 @@ public class ExcelWriter {
* @param sheet * @param sheet
* Write to this sheet * Write to this sheet
* @return this current writer * @return this current writer
* @deprecated please use {@link ExcelWriter#write(List, WriteSheet)} * @deprecated please use {@link ExcelWriter#write(Collection, WriteSheet)}
*/ */
@Deprecated @Deprecated
public ExcelWriter write0(List data, Sheet sheet) { public ExcelWriter write0(List data, Sheet sheet) {
@ -263,7 +265,7 @@ public class ExcelWriter {
* @param table * @param table
* Write to this table * Write to this table
* @return this * @return this
* @deprecated * @deprecated please use {@link ExcelWriter#write(List, WriteSheet,WriteTable)} * @deprecated * @deprecated please use {@link ExcelWriter#write(Collection, WriteSheet,WriteTable)}
*/ */
@Deprecated @Deprecated
public ExcelWriter write0(List data, Sheet sheet, Table table) { public ExcelWriter write0(List data, Sheet sheet, Table table) {
@ -278,7 +280,7 @@ public class ExcelWriter {
* @param sheet * @param sheet
* Write to this sheet * Write to this sheet
* @return this current writer * @return this current writer
* @deprecated please use {@link ExcelWriter#write(List, WriteSheet)} * @deprecated please use {@link ExcelWriter#write(Collection, WriteSheet)}
*/ */
@Deprecated @Deprecated
public ExcelWriter write1(List data, Sheet sheet) { public ExcelWriter write1(List data, Sheet sheet) {
@ -295,7 +297,7 @@ public class ExcelWriter {
* @param table * @param table
* Write to this table * Write to this table
* @return this * @return this
* @deprecated * @deprecated please use {@link ExcelWriter#write(List, WriteSheet,WriteTable)} * @deprecated * @deprecated please use {@link ExcelWriter#write(Collection, WriteSheet,WriteTable)}
*/ */
@Deprecated @Deprecated
public ExcelWriter write1(List data, Sheet sheet, Table table) { public ExcelWriter write1(List data, Sheet sheet, Table table) {

2
src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java

@ -3,6 +3,7 @@ package com.alibaba.excel.analysis;
import java.io.InputStream; import java.io.InputStream;
import java.util.List; import java.util.List;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey; import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
import org.apache.poi.poifs.crypt.Decryptor; import org.apache.poi.poifs.crypt.Decryptor;
import org.apache.poi.poifs.filesystem.DocumentFactoryHelper; 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.xls.XlsReadWorkbookHolder;
import com.alibaba.excel.read.metadata.holder.xlsx.XlsxReadWorkbookHolder; import com.alibaba.excel.read.metadata.holder.xlsx.XlsxReadWorkbookHolder;
import com.alibaba.excel.support.ExcelTypeEnum; import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.excel.util.DateUtils; import com.alibaba.excel.util.DateUtils;
import com.alibaba.excel.util.FileUtils; import com.alibaba.excel.util.FileUtils;
import com.alibaba.excel.util.NumberDataFormatterUtils; import com.alibaba.excel.util.NumberDataFormatterUtils;

22
src/main/java/com/alibaba/excel/analysis/v03/handlers/FormulaRecordHandler.java

@ -3,14 +3,6 @@ package com.alibaba.excel.analysis.v03.handlers;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.Map; import java.util.Map;
import com.alibaba.excel.enums.RowTypeEnum;
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.analysis.v03.IgnorableXlsRecordHandler;
import com.alibaba.excel.constant.BuiltinFormats; import com.alibaba.excel.constant.BuiltinFormats;
import com.alibaba.excel.context.xls.XlsReadContext; import com.alibaba.excel.context.xls.XlsReadContext;
@ -19,6 +11,13 @@ import com.alibaba.excel.enums.RowTypeEnum;
import com.alibaba.excel.metadata.Cell; import com.alibaba.excel.metadata.Cell;
import com.alibaba.excel.metadata.CellData; 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 * Record handler
* *
@ -32,7 +31,7 @@ public class FormulaRecordHandler extends AbstractXlsRecordHandler implements Ig
public void processRecord(XlsReadContext xlsReadContext, Record record) { public void processRecord(XlsReadContext xlsReadContext, Record record) {
FormulaRecord frec = (FormulaRecord)record; FormulaRecord frec = (FormulaRecord)record;
Map<Integer, Cell> cellMap = xlsReadContext.xlsReadSheetHolder().getCellMap(); Map<Integer, Cell> cellMap = xlsReadContext.xlsReadSheetHolder().getCellMap();
CellData tempCellData = new CellData(); CellData<?> tempCellData = new CellData<>();
tempCellData.setRowIndex(frec.getRow()); tempCellData.setRowIndex(frec.getRow());
tempCellData.setColumnIndex((int)frec.getColumn()); tempCellData.setColumnIndex((int)frec.getColumn());
CellType cellType = CellType.forInt(frec.getCachedResultType()); CellType cellType = CellType.forInt(frec.getCachedResultType());
@ -58,8 +57,9 @@ public class FormulaRecordHandler extends AbstractXlsRecordHandler implements Ig
tempCellData.setNumberValue(BigDecimal.valueOf(frec.getValue())); tempCellData.setNumberValue(BigDecimal.valueOf(frec.getValue()));
Integer dataFormat = Integer dataFormat =
xlsReadContext.xlsReadWorkbookHolder().getFormatTrackingHSSFListener().getFormatIndex(frec); xlsReadContext.xlsReadWorkbookHolder().getFormatTrackingHSSFListener().getFormatIndex(frec);
tempCellData.setDataFormat(dataFormat); Short dataFormatShort = dataFormat.shortValue();
tempCellData.setDataFormatString(BuiltinFormats.getBuiltinFormat(dataFormat, tempCellData.setDataFormat(dataFormatShort);
tempCellData.setDataFormatString(BuiltinFormats.getBuiltinFormat(dataFormatShort,
xlsReadContext.xlsReadWorkbookHolder().getFormatTrackingHSSFListener().getFormatString(frec), xlsReadContext.xlsReadWorkbookHolder().getFormatTrackingHSSFListener().getFormatString(frec),
xlsReadContext.readSheetHolder().getGlobalConfiguration().getLocale())); xlsReadContext.readSheetHolder().getGlobalConfiguration().getLocale()));
cellMap.put((int)frec.getColumn(), tempCellData); cellMap.put((int)frec.getColumn(), tempCellData);

11
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 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.analysis.v03.IgnorableXlsRecordHandler;
import com.alibaba.excel.constant.BuiltinFormats; import com.alibaba.excel.constant.BuiltinFormats;
import com.alibaba.excel.context.xls.XlsReadContext; import com.alibaba.excel.context.xls.XlsReadContext;
import com.alibaba.excel.enums.RowTypeEnum; import com.alibaba.excel.enums.RowTypeEnum;
import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.CellData;
import org.apache.poi.hssf.record.NumberRecord;
import org.apache.poi.hssf.record.Record;
/** /**
* Record handler * Record handler
* *
@ -21,8 +21,9 @@ public class NumberRecordHandler extends AbstractXlsRecordHandler implements Ign
@Override @Override
public void processRecord(XlsReadContext xlsReadContext, Record record) { public void processRecord(XlsReadContext xlsReadContext, Record record) {
NumberRecord nr = (NumberRecord)record; NumberRecord nr = (NumberRecord)record;
CellData cellData = CellData.newInstance(BigDecimal.valueOf(nr.getValue()), nr.getRow(), (int)nr.getColumn()); CellData<?>cellData = CellData.newInstance(BigDecimal.valueOf(nr.getValue()), nr.getRow(), (int)nr.getColumn());
Integer dataFormat = xlsReadContext.xlsReadWorkbookHolder().getFormatTrackingHSSFListener().getFormatIndex(nr); short dataFormat = (short)xlsReadContext.xlsReadWorkbookHolder().getFormatTrackingHSSFListener().getFormatIndex(
nr);
cellData.setDataFormat(dataFormat); cellData.setDataFormat(dataFormat);
cellData.setDataFormatString(BuiltinFormats.getBuiltinFormat(dataFormat, cellData.setDataFormatString(BuiltinFormats.getBuiltinFormat(dataFormat,
xlsReadContext.xlsReadWorkbookHolder().getFormatTrackingHSSFListener().getFormatString(nr), xlsReadContext.xlsReadWorkbookHolder().getFormatTrackingHSSFListener().getFormatString(nr),

2
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 // String for formula
StringRecord srec = (StringRecord)record; StringRecord srec = (StringRecord)record;
XlsReadSheetHolder xlsReadSheetHolder = xlsReadContext.xlsReadSheetHolder(); XlsReadSheetHolder xlsReadSheetHolder = xlsReadContext.xlsReadSheetHolder();
CellData tempCellData = xlsReadSheetHolder.getTempCellData(); CellData<?>tempCellData = xlsReadSheetHolder.getTempCellData();
if (tempCellData == null) { if (tempCellData == null) {
LOGGER.warn("String type formula but no value found."); LOGGER.warn("String type formula but no value found.");
return; return;

58
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.Map;
import java.util.UUID; import java.util.UUID;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory; 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.OPCPackage;
import org.apache.poi.openxml4j.opc.PackageAccess; import org.apache.poi.openxml4j.opc.PackageAccess;
import org.apache.poi.openxml4j.opc.PackagePart; 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.openxmlformats.schemas.spreadsheetml.x2006.main.WorkbookDocument;
import org.xml.sax.ContentHandler; import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource; import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader; 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 * @author jipengfei
*/ */
@Slf4j
public class XlsxSaxAnalyser implements ExcelReadExecutor { public class XlsxSaxAnalyser implements ExcelReadExecutor {
private XlsxReadContext xlsxReadContext; private XlsxReadContext xlsxReadContext;
@ -78,7 +82,9 @@ public class XlsxSaxAnalyser implements ExcelReadExecutor {
XSSFReader xssfReader = new XSSFReader(pkg); XSSFReader xssfReader = new XSSFReader(pkg);
analysisUse1904WindowDate(xssfReader, xlsxReadWorkbookHolder); analysisUse1904WindowDate(xssfReader, xlsxReadWorkbookHolder);
xlsxReadWorkbookHolder.setStylesTable(xssfReader.getStylesTable()); // set style table
setStylesTable(xlsxReadWorkbookHolder, xssfReader);
sheetList = new ArrayList<ReadSheet>(); sheetList = new ArrayList<ReadSheet>();
sheetMap = new HashMap<Integer, InputStream>(); sheetMap = new HashMap<Integer, InputStream>();
commentsTableMap = new HashMap<Integer, CommentsTable>(); commentsTableMap = new HashMap<Integer, CommentsTable>();
@ -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, private void defaultReadCache(XlsxReadWorkbookHolder xlsxReadWorkbookHolder,
PackagePart sharedStringsTablePackagePart) { PackagePart sharedStringsTablePackagePart) {
ReadCache readCache = xlsxReadWorkbookHolder.getReadCacheSelector().readCache(sharedStringsTablePackagePart); ReadCache readCache = xlsxReadWorkbookHolder.getReadCacheSelector().readCache(sharedStringsTablePackagePart);
@ -147,9 +164,10 @@ public class XlsxSaxAnalyser implements ExcelReadExecutor {
xlsxReadWorkbookHolder.setTempFile(readTempFile); xlsxReadWorkbookHolder.setTempFile(readTempFile);
File tempFile = new File(readTempFile.getPath(), UUID.randomUUID().toString() + ".xlsx"); File tempFile = new File(readTempFile.getPath(), UUID.randomUUID().toString() + ".xlsx");
if (decryptedStream != null) { if (decryptedStream != null) {
FileUtils.writeToFile(tempFile, decryptedStream); FileUtils.writeToFile(tempFile, decryptedStream, false);
} else { } else {
FileUtils.writeToFile(tempFile, xlsxReadWorkbookHolder.getInputStream()); FileUtils.writeToFile(tempFile, xlsxReadWorkbookHolder.getInputStream(),
xlsxReadWorkbookHolder.getAutoCloseStream());
} }
return OPCPackage.open(tempFile, PackageAccess.READ); return OPCPackage.open(tempFile, PackageAccess.READ);
} }
@ -177,9 +195,7 @@ public class XlsxSaxAnalyser implements ExcelReadExecutor {
xmlReader.setContentHandler(handler); xmlReader.setContentHandler(handler);
xmlReader.parse(inputSource); xmlReader.parse(inputSource);
inputStream.close(); inputStream.close();
} catch (ExcelAnalysisException e) { } catch (IOException | ParserConfigurationException | SAXException e) {
throw e;
} catch (Exception e) {
throw new ExcelAnalysisException(e); throw new ExcelAnalysisException(e);
} finally { } finally {
if (inputStream != null) { if (inputStream != null) {

12
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.metadata.CellData;
import com.alibaba.excel.read.metadata.holder.xlsx.XlsxReadSheetHolder; import com.alibaba.excel.read.metadata.holder.xlsx.XlsxReadSheetHolder;
import com.alibaba.excel.util.BooleanUtils; import com.alibaba.excel.util.BooleanUtils;
import com.alibaba.excel.util.StringUtils;
/** /**
* Cell Value Handler * Cell Value Handler
@ -20,6 +21,7 @@ public abstract class AbstractCellValueTagHandler extends AbstractXlsxTagHandler
XlsxReadSheetHolder xlsxReadSheetHolder = xlsxReadContext.xlsxReadSheetHolder(); XlsxReadSheetHolder xlsxReadSheetHolder = xlsxReadContext.xlsxReadSheetHolder();
CellData tempCellData = xlsxReadSheetHolder.getTempCellData(); CellData tempCellData = xlsxReadSheetHolder.getTempCellData();
StringBuilder tempData = xlsxReadSheetHolder.getTempData(); StringBuilder tempData = xlsxReadSheetHolder.getTempData();
String tempDataString = tempData.toString();
CellDataTypeEnum oldType = tempCellData.getType(); CellDataTypeEnum oldType = tempCellData.getType();
switch (oldType) { switch (oldType) {
case DIRECT_STRING: case DIRECT_STRING:
@ -28,10 +30,18 @@ public abstract class AbstractCellValueTagHandler extends AbstractXlsxTagHandler
tempCellData.setStringValue(tempData.toString()); tempCellData.setStringValue(tempData.toString());
break; break;
case BOOLEAN: case BOOLEAN:
if(StringUtils.isEmpty(tempDataString)){
tempCellData.setType(CellDataTypeEnum.EMPTY);
break;
}
tempCellData.setBooleanValue(BooleanUtils.valueOf(tempData.toString())); tempCellData.setBooleanValue(BooleanUtils.valueOf(tempData.toString()));
break; break;
case NUMBER: case NUMBER:
case EMPTY: case EMPTY:
if(StringUtils.isEmpty(tempDataString)){
tempCellData.setType(CellDataTypeEnum.EMPTY);
break;
}
tempCellData.setType(CellDataTypeEnum.NUMBER); tempCellData.setType(CellDataTypeEnum.NUMBER);
tempCellData.setNumberValue(new BigDecimal(tempData.toString())); tempCellData.setNumberValue(new BigDecimal(tempData.toString()));
break; break;
@ -44,7 +54,7 @@ public abstract class AbstractCellValueTagHandler extends AbstractXlsxTagHandler
if (tempCellData.getStringValue() != null if (tempCellData.getStringValue() != null
&& xlsxReadContext.currentReadHolder().globalConfiguration().getAutoTrim()) { && xlsxReadContext.currentReadHolder().globalConfiguration().getAutoTrim()) {
tempCellData.setStringValue(tempCellData.getStringValue()); tempCellData.setStringValue(tempCellData.getStringValue().trim());
} }
tempCellData.checkEmpty(); tempCellData.checkEmpty();

2
src/main/java/com/alibaba/excel/analysis/v07/handlers/CellInlineStringValueTagHandler.java

@ -15,7 +15,7 @@ public class CellInlineStringValueTagHandler extends AbstractCellValueTagHandler
@Override @Override
protected void setStringValue(XlsxReadContext xlsxReadContext) { protected void setStringValue(XlsxReadContext xlsxReadContext) {
// This is a special form of string // This is a special form of string
CellData tempCellData = xlsxReadContext.xlsxReadSheetHolder().getTempCellData(); CellData<?> tempCellData = xlsxReadContext.xlsxReadSheetHolder().getTempCellData();
XSSFRichTextString richTextString = new XSSFRichTextString(tempCellData.getStringValue()); XSSFRichTextString richTextString = new XSSFRichTextString(tempCellData.getStringValue());
tempCellData.setStringValue(richTextString.toString()); tempCellData.setStringValue(richTextString.toString());
} }

16
src/main/java/com/alibaba/excel/analysis/v07/handlers/CellTagHandler.java

@ -1,8 +1,5 @@
package com.alibaba.excel.analysis.v07.handlers; 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.BuiltinFormats;
import com.alibaba.excel.constant.ExcelXmlConstants; import com.alibaba.excel.constant.ExcelXmlConstants;
import com.alibaba.excel.context.xlsx.XlsxReadContext; 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.PositionUtils;
import com.alibaba.excel.util.StringUtils; 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 * Cell Handler
* *
@ -46,9 +47,12 @@ public class CellTagHandler extends AbstractXlsxTagHandler {
} else { } else {
dateFormatIndexInteger = Integer.parseInt(dateFormatIndex); dateFormatIndexInteger = Integer.parseInt(dateFormatIndex);
} }
XSSFCellStyle xssfCellStyle = StylesTable stylesTable = xlsxReadContext.xlsxReadWorkbookHolder().getStylesTable();
xlsxReadContext.xlsxReadWorkbookHolder().getStylesTable().getStyleAt(dateFormatIndexInteger); if (stylesTable == null) {
int dataFormat = xssfCellStyle.getDataFormat(); return;
}
XSSFCellStyle xssfCellStyle = stylesTable.getStyleAt(dateFormatIndexInteger);
short dataFormat = xssfCellStyle.getDataFormat();
xlsxReadSheetHolder.getTempCellData().setDataFormat(dataFormat); xlsxReadSheetHolder.getTempCellData().setDataFormat(dataFormat);
xlsxReadSheetHolder.getTempCellData().setDataFormatString(BuiltinFormats.getBuiltinFormat(dataFormat, xlsxReadSheetHolder.getTempCellData().setDataFormatString(BuiltinFormats.getBuiltinFormat(dataFormat,
xssfCellStyle.getDataFormatString(), xlsxReadSheetHolder.getGlobalConfiguration().getLocale())); xssfCellStyle.getDataFormatString(), xlsxReadSheetHolder.getGlobalConfiguration().getLocale()));

5
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.context.xlsx.XlsxReadContext;
import com.alibaba.excel.enums.CellDataTypeEnum; import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.util.StringUtils;
/** /**
* Cell Value Handler * Cell Value Handler
@ -17,6 +18,10 @@ public class CellValueTagHandler extends AbstractCellValueTagHandler {
CellData tempCellData = xlsxReadContext.xlsxReadSheetHolder().getTempCellData(); CellData tempCellData = xlsxReadContext.xlsxReadSheetHolder().getTempCellData();
switch (tempCellData.getType()) { switch (tempCellData.getType()) {
case STRING: 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() String stringValue = xlsxReadContext.readWorkbookHolder().getReadCache()
.get(Integer.valueOf(tempCellData.getStringValue())); .get(Integer.valueOf(tempCellData.getStringValue()));
if (stringValue != null && xlsxReadContext.currentReadHolder().globalConfiguration().getAutoTrim()) { if (stringValue != null && xlsxReadContext.currentReadHolder().globalConfiguration().getAutoTrim()) {

11
src/main/java/com/alibaba/excel/analysis/v07/handlers/RowTagHandler.java

@ -2,17 +2,17 @@ package com.alibaba.excel.analysis.v07.handlers;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import org.xml.sax.Attributes;
import com.alibaba.excel.constant.ExcelXmlConstants; import com.alibaba.excel.constant.ExcelXmlConstants;
import com.alibaba.excel.context.xlsx.XlsxReadContext; import com.alibaba.excel.context.xlsx.XlsxReadContext;
import com.alibaba.excel.enums.RowTypeEnum; import com.alibaba.excel.enums.RowTypeEnum;
import com.alibaba.excel.metadata.Cell; import com.alibaba.excel.metadata.Cell;
import com.alibaba.excel.read.metadata.holder.ReadRowHolder; import com.alibaba.excel.read.metadata.holder.ReadRowHolder;
import com.alibaba.excel.read.metadata.holder.xlsx.XlsxReadSheetHolder; import com.alibaba.excel.read.metadata.holder.xlsx.XlsxReadSheetHolder;
import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.excel.util.PositionUtils; import com.alibaba.excel.util.PositionUtils;
import org.apache.commons.collections4.MapUtils;
import org.xml.sax.Attributes;
/** /**
* Cell Handler * Cell Handler
* *
@ -40,13 +40,12 @@ public class RowTagHandler extends AbstractXlsxTagHandler {
@Override @Override
public void endElement(XlsxReadContext xlsxReadContext, String name) { public void endElement(XlsxReadContext xlsxReadContext, String name) {
XlsxReadSheetHolder xlsxReadSheetHolder = xlsxReadContext.xlsxReadSheetHolder(); XlsxReadSheetHolder xlsxReadSheetHolder = xlsxReadContext.xlsxReadSheetHolder();
RowTypeEnum rowType = RowTypeEnum rowType = MapUtils.isEmpty(xlsxReadSheetHolder.getCellMap()) ? RowTypeEnum.EMPTY : RowTypeEnum.DATA;
CollectionUtils.isEmpty(xlsxReadSheetHolder.getCellMap()) ? RowTypeEnum.EMPTY : RowTypeEnum.DATA;
xlsxReadContext.readRowHolder(new ReadRowHolder(xlsxReadSheetHolder.getRowIndex(), rowType, xlsxReadContext.readRowHolder(new ReadRowHolder(xlsxReadSheetHolder.getRowIndex(), rowType,
xlsxReadSheetHolder.getGlobalConfiguration(), xlsxReadSheetHolder.getCellMap())); xlsxReadSheetHolder.getGlobalConfiguration(), xlsxReadSheetHolder.getCellMap()));
xlsxReadContext.analysisEventProcessor().endRow(xlsxReadContext); xlsxReadContext.analysisEventProcessor().endRow(xlsxReadContext);
xlsxReadSheetHolder.setColumnIndex(null); xlsxReadSheetHolder.setColumnIndex(null);
xlsxReadSheetHolder.setCellMap(new LinkedHashMap<Integer, Cell>()); xlsxReadSheetHolder.setCellMap(new LinkedHashMap<>());
} }
} }

2
src/main/java/com/alibaba/excel/annotation/ExcelProperty.java

@ -23,7 +23,7 @@ public @interface ExcelProperty {
* <p> * <p>
* write: It automatically merges when you have more than one head * write: It automatically merges when you have more than one head
* <p> * <p>
* 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 * @return The name of the sheet header
*/ */

92
src/main/java/com/alibaba/excel/cache/Ehcache.java vendored

@ -1,50 +1,49 @@
package com.alibaba.excel.cache; package com.alibaba.excel.cache;
import java.io.File; import java.io.File;
import java.util.HashMap; import java.util.ArrayList;
import java.util.UUID; 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.CacheManager;
import org.ehcache.config.CacheConfiguration; import org.ehcache.config.CacheConfiguration;
import org.ehcache.config.builders.CacheConfigurationBuilder; import org.ehcache.config.builders.CacheConfigurationBuilder;
import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.CacheManagerBuilder;
import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder;
import org.ehcache.config.units.MemoryUnit; 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 * Default cache
* *
* @author Jiaju Zhuang * @author Jiaju Zhuang
*/ */
@Slf4j
public class Ehcache implements ReadCache { public class Ehcache implements ReadCache {
public static final int BATCH_COUNT = 1000;
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;
/** /**
* Key index * Key index
*/ */
private int index = 0; private int activeIndex = 0;
private HashMap<Integer, String> dataMap = new HashMap<Integer, String>(BATCH_COUNT * 4 / 3 + 1); public static final int DEBUG_CACHE_MISS_SIZE = 1000;
private static CacheManager fileCacheManager; public static final int DEBUG_WRITE_SIZE = 100 * 10000;
private static CacheConfiguration<Integer, HashMap> fileCacheConfiguration; private ArrayList<String> dataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
private static CacheManager activeCacheManager; private static final CacheManager FILE_CACHE_MANAGER;
private CacheConfiguration<Integer, HashMap> activeCacheConfiguration; private static final CacheConfiguration<Integer, ArrayList> FILE_CACHE_CONFIGURATION;
private static final CacheManager ACTIVE_CACHE_MANAGER;
private final CacheConfiguration<Integer, ArrayList> activeCacheConfiguration;
/** /**
* Bulk storage data * Bulk storage data
*/ */
private org.ehcache.Cache<Integer, HashMap> fileCache; private org.ehcache.Cache<Integer, ArrayList> fileCache;
/** /**
* Currently active cache * Currently active cache
*/ */
private org.ehcache.Cache<Integer, HashMap> activeCache; private org.ehcache.Cache<Integer, ArrayList> activeCache;
private String cacheAlias; private String cacheAlias;
/** /**
* Count the number of cache misses * Count the number of cache misses
@ -53,7 +52,7 @@ public class Ehcache implements ReadCache {
public Ehcache(int maxCacheActivateSize) { public Ehcache(int maxCacheActivateSize) {
activeCacheConfiguration = CacheConfigurationBuilder activeCacheConfiguration = CacheConfigurationBuilder
.newCacheConfigurationBuilder(Integer.class, HashMap.class, .newCacheConfigurationBuilder(Integer.class, ArrayList.class,
ResourcePoolsBuilder.newResourcePoolsBuilder().heap(maxCacheActivateSize, MemoryUnit.MB)) ResourcePoolsBuilder.newResourcePoolsBuilder().heap(maxCacheActivateSize, MemoryUnit.MB))
.withSizeOfMaxObjectGraph(1000 * 1000L).withSizeOfMaxObjectSize(maxCacheActivateSize, MemoryUnit.MB) .withSizeOfMaxObjectGraph(1000 * 1000L).withSizeOfMaxObjectSize(maxCacheActivateSize, MemoryUnit.MB)
.build(); .build();
@ -61,11 +60,11 @@ public class Ehcache implements ReadCache {
static { static {
File cacheFile = FileUtils.createCacheTmpFile(); File cacheFile = FileUtils.createCacheTmpFile();
fileCacheManager = FILE_CACHE_MANAGER =
CacheManagerBuilder.newCacheManagerBuilder().with(CacheManagerBuilder.persistence(cacheFile)).build(true); CacheManagerBuilder.newCacheManagerBuilder().with(CacheManagerBuilder.persistence(cacheFile)).build(true);
activeCacheManager = CacheManagerBuilder.newCacheManagerBuilder().build(true); ACTIVE_CACHE_MANAGER = CacheManagerBuilder.newCacheManagerBuilder().build(true);
fileCacheConfiguration = CacheConfigurationBuilder FILE_CACHE_CONFIGURATION = CacheConfigurationBuilder
.newCacheConfigurationBuilder(Integer.class, HashMap.class, .newCacheConfigurationBuilder(Integer.class, ArrayList.class,
ResourcePoolsBuilder.newResourcePoolsBuilder().disk(10, MemoryUnit.GB)) ResourcePoolsBuilder.newResourcePoolsBuilder().disk(10, MemoryUnit.GB))
.withSizeOfMaxObjectGraph(1000 * 1000L).withSizeOfMaxObjectSize(10, MemoryUnit.GB).build(); .withSizeOfMaxObjectGraph(1000 * 1000L).withSizeOfMaxObjectSize(10, MemoryUnit.GB).build();
} }
@ -73,21 +72,22 @@ public class Ehcache implements ReadCache {
@Override @Override
public void init(AnalysisContext analysisContext) { public void init(AnalysisContext analysisContext) {
cacheAlias = UUID.randomUUID().toString(); cacheAlias = UUID.randomUUID().toString();
fileCache = fileCacheManager.createCache(cacheAlias, fileCacheConfiguration); fileCache = FILE_CACHE_MANAGER.createCache(cacheAlias, FILE_CACHE_CONFIGURATION);
activeCache = activeCacheManager.createCache(cacheAlias, activeCacheConfiguration); activeCache = ACTIVE_CACHE_MANAGER.createCache(cacheAlias, activeCacheConfiguration);
} }
@Override @Override
public void put(String value) { public void put(String value) {
dataMap.put(index, value); dataList.add(value);
if ((index + 1) % BATCH_COUNT == 0) { if (dataList.size() >= BATCH_COUNT) {
fileCache.put(index / BATCH_COUNT, dataMap); fileCache.put(activeIndex, dataList);
dataMap = new HashMap<Integer, String>(BATCH_COUNT * 4 / 3 + 1); activeIndex++;
dataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
} }
index++; if (log.isDebugEnabled()) {
if (LOGGER.isDebugEnabled()) { int alreadyPut = activeIndex * BATCH_COUNT + dataList.size();
if (index % DEBUG_WRITE_SIZE == 0) { if (alreadyPut % DEBUG_WRITE_SIZE == 0) {
LOGGER.debug("Already put :{}", index); log.debug("Already put :{}", alreadyPut);
} }
} }
} }
@ -98,31 +98,31 @@ public class Ehcache implements ReadCache {
return null; return null;
} }
int route = key / BATCH_COUNT; int route = key / BATCH_COUNT;
HashMap<Integer, String> dataMap = activeCache.get(route); ArrayList<String> dataList = activeCache.get(route);
if (dataMap == null) { if (dataList == null) {
dataMap = fileCache.get(route); dataList = fileCache.get(route);
activeCache.put(route, dataMap); activeCache.put(route, dataList);
if (LOGGER.isDebugEnabled()) { if (log.isDebugEnabled()) {
if (cacheMiss++ % DEBUG_CACHE_MISS_SIZE == 0) { 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 @Override
public void putFinished() { public void putFinished() {
if (CollectionUtils.isEmpty(dataMap)) { if (CollectionUtils.isEmpty(dataList)) {
return; return;
} }
fileCache.put(index / BATCH_COUNT, dataMap); fileCache.put(activeIndex, dataList);
} }
@Override @Override
public void destroy() { public void destroy() {
fileCacheManager.removeCache(cacheAlias); FILE_CACHE_MANAGER.removeCache(cacheAlias);
activeCacheManager.removeCache(cacheAlias); ACTIVE_CACHE_MANAGER.removeCache(cacheAlias);
} }
} }

10
src/main/java/com/alibaba/excel/cache/MapCache.java vendored

@ -1,26 +1,24 @@
package com.alibaba.excel.cache; package com.alibaba.excel.cache;
import java.util.HashMap; import java.util.ArrayList;
import java.util.Map; import java.util.List;
import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.context.AnalysisContext;
/** /**
*
* Putting temporary data directly into a map is a little more efficient but very memory intensive * Putting temporary data directly into a map is a little more efficient but very memory intensive
* *
* @author Jiaju Zhuang * @author Jiaju Zhuang
*/ */
public class MapCache implements ReadCache { public class MapCache implements ReadCache {
private Map<Integer, String> cache = new HashMap<Integer, String>(); private List<String> cache = new ArrayList<>();
private int index = 0;
@Override @Override
public void init(AnalysisContext analysisContext) {} public void init(AnalysisContext analysisContext) {}
@Override @Override
public void put(String value) { public void put(String value) {
cache.put(index++, value); cache.add(value);
} }
@Override @Override

8
src/main/java/com/alibaba/excel/constant/BuiltinFormats.java

@ -17,7 +17,9 @@ import java.util.Locale;
**/ **/
public class BuiltinFormats { public class BuiltinFormats {
private static final String[] BUILTIN_FORMATS_CN = { public static short GENERAL = 0;
public static final String[] BUILTIN_FORMATS_CN = {
// 0 // 0
"General", "General",
// 1 // 1
@ -189,7 +191,7 @@ public class BuiltinFormats {
// end // end
}; };
private static final String[] BUILTIN_FORMATS_US = { public static final String[] BUILTIN_FORMATS_US = {
// 0 // 0
"General", "General",
// 1 // 1
@ -361,7 +363,7 @@ public class BuiltinFormats {
// end // 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); String[] builtinFormat = switchBuiltinFormats(locale);
if (index == null || index < 0 || index >= builtinFormat.length) { if (index == null || index < 0 || index >= builtinFormat.length) {
return defaultFormat; return defaultFormat;

13
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;
}

41
src/main/java/com/alibaba/excel/context/WriteContextImpl.java

@ -6,22 +6,6 @@ import java.io.OutputStream;
import java.util.Map; import java.util.Map;
import java.util.UUID; 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.enums.WriteTypeEnum;
import com.alibaba.excel.exception.ExcelGenerateException; import com.alibaba.excel.exception.ExcelGenerateException;
import com.alibaba.excel.metadata.CellData; 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.metadata.holder.WriteWorkbookHolder;
import com.alibaba.excel.write.property.ExcelWriteHeadProperty; 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. * 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 { public class WriteContextImpl implements WriteContext {
private static final Logger LOGGER = LoggerFactory.getLogger(WriteContextImpl.class); private static final Logger LOGGER = LoggerFactory.getLogger(WriteContextImpl.class);
private static final String NO_SHEETS="no sheets";
/** /**
* The Workbook currently written * The Workbook currently written
@ -178,8 +179,12 @@ public class WriteContextImpl implements WriteContext {
writeSheetHolder writeSheetHolder
.setCachedSheet(writeWorkbookHolder.getCachedWorkbook().getSheet(writeSheetHolder.getSheetName())); .setCachedSheet(writeWorkbookHolder.getCachedWorkbook().getSheet(writeSheetHolder.getSheetName()));
} }
} catch (Exception e) { } catch (IllegalArgumentException e) {
currentSheet = createSheet(); if (e.getMessage() != null && e.getMessage().contains(NO_SHEETS)) {
currentSheet = createSheet();
} else {
throw e;
}
} }
if (currentSheet == null) { if (currentSheet == null) {
currentSheet = createSheet(); currentSheet = createSheet();

8
src/main/java/com/alibaba/excel/converters/AutoConverter.java

@ -10,10 +10,10 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty;
* *
* @author Jiaju Zhuang * @author Jiaju Zhuang
*/ */
public class AutoConverter implements Converter { public class AutoConverter implements Converter<Object> {
@Override @Override
public Class supportJavaTypeKey() { public Class<?> supportJavaTypeKey() {
return null; return null;
} }
@ -23,13 +23,13 @@ public class AutoConverter implements Converter {
} }
@Override @Override
public Object convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, public Object convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
return null; return null;
} }
@Override @Override
public CellData convertToExcelData(Object value, ExcelContentProperty contentProperty, public CellData<?> convertToExcelData(Object value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
return null; return null;
} }

78
src/main/java/com/alibaba/excel/converters/Converter.java

@ -4,12 +4,16 @@ import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.GlobalConfiguration; import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.property.ExcelContentProperty; import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.alibaba.excel.read.metadata.holder.ReadSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteHolder;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
/** /**
* Convert between Java objects and excel objects * Convert between Java objects and excel objects
* *
* @author Dan Zheng
* @param <T> * @param <T>
* @author Dan Zheng
*/ */
public interface Converter<T> { public interface Converter<T> {
@ -18,44 +22,72 @@ public interface Converter<T> {
* *
* @return Support for Java class * @return Support for Java class
*/ */
Class supportJavaTypeKey(); default Class<?> supportJavaTypeKey() {
throw new UnsupportedOperationException("The current operation is not supported by the current converter.");
}
/** /**
* Back to object enum in excel * Back to object enum in excel
* *
* @return Support for {@link CellDataTypeEnum} * @return Support for {@link CellDataTypeEnum}
*/ */
CellDataTypeEnum supportExcelTypeKey(); default CellDataTypeEnum supportExcelTypeKey() {
throw new UnsupportedOperationException("The current operation is not supported by the current converter.");
}
/**
* Convert excel objects to Java objects
*
* @param cellData Excel cell data.NotNull.
* @param contentProperty Content property.Nullable.
* @param globalConfiguration Global configuration.NotNull.
* @return Data to put into a Java object
* @throws Exception Exception.
*/
default T convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) throws Exception {
throw new UnsupportedOperationException("The current operation is not supported by the current converter.");
}
/** /**
* Convert excel objects to Java objects * Convert excel objects to Java objects
* *
* @param cellData * @param cellData Excel cell data.NotNull.
* Excel cell data.NotNull. * @param contentProperty Content property.Nullable.
* @param contentProperty * @param readSheetHolder .NotNull.
* Content property.Nullable.
* @param globalConfiguration
* Global configuration.NotNull.
* @return Data to put into a Java object * @return Data to put into a Java object
* @throws Exception * @throws Exception Exception.
* Exception. */
default T convertToJavaData(CellData<?> cellData,
ExcelContentProperty contentProperty, ReadSheetHolder readSheetHolder) throws Exception {
return convertToJavaData(cellData, contentProperty, readSheetHolder.globalConfiguration());
}
/**
* Convert Java objects to excel objects
*
* @param value Java Data.NotNull.
* @param contentProperty Content property.Nullable.
* @param globalConfiguration Global configuration.NotNull.
* @return Data to put into a Excel
* @throws Exception Exception.
*/ */
T convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, default CellData<?> convertToExcelData(T value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) throws Exception; GlobalConfiguration globalConfiguration) throws Exception {
throw new UnsupportedOperationException("The current operation is not supported by the current converter.");
}
/** /**
* Convert Java objects to excel objects * Convert Java objects to excel objects
* *
* @param value * @param value Java Data.NotNull.
* Java Data.NotNull. * @param contentProperty Content property.Nullable.
* @param contentProperty * @param currentWriteHolder He would be {@link WriteSheetHolder} or {@link WriteTableHolder}.NotNull.
* Content property.Nullable.
* @param globalConfiguration
* Global configuration.NotNull.
* @return Data to put into a Excel * @return Data to put into a Excel
* @throws Exception * @throws Exception Exception.
* Exception.
*/ */
CellData convertToExcelData(T value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) default CellData<?> convertToExcelData(T value, ExcelContentProperty contentProperty,
throws Exception; WriteHolder currentWriteHolder) throws Exception {
return convertToExcelData(value, contentProperty, currentWriteHolder.globalConfiguration());
}
} }

14
src/main/java/com/alibaba/excel/converters/ConverterKeyBuild.java

@ -1,9 +1,9 @@
package com.alibaba.excel.converters; package com.alibaba.excel.converters;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import com.alibaba.excel.enums.CellDataTypeEnum; import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.util.MapUtils;
/** /**
* Converter unique key.Consider that you can just use class as the key. * Converter unique key.Consider that you can just use class as the key.
@ -12,7 +12,7 @@ import com.alibaba.excel.enums.CellDataTypeEnum;
*/ */
public class ConverterKeyBuild { public class ConverterKeyBuild {
private static final Map<String, String> BOXING_MAP = new HashMap<String, String>(16); private static final Map<String, String> BOXING_MAP = MapUtils.newHashMap();
static { static {
BOXING_MAP.put(int.class.getName(), Integer.class.getName()); BOXING_MAP.put(int.class.getName(), Integer.class.getName());
@ -25,7 +25,7 @@ public class ConverterKeyBuild {
BOXING_MAP.put(boolean.class.getName(), Boolean.class.getName()); BOXING_MAP.put(boolean.class.getName(), Boolean.class.getName());
} }
public static String buildKey(Class clazz) { public static String buildKey(Class<?> clazz) {
String className = clazz.getName(); String className = clazz.getName();
String boxingClassName = BOXING_MAP.get(clazz.getName()); String boxingClassName = BOXING_MAP.get(clazz.getName());
if (boxingClassName == null) { if (boxingClassName == null) {
@ -34,7 +34,11 @@ public class ConverterKeyBuild {
return boxingClassName; return boxingClassName;
} }
public static String buildKey(Class clazz, CellDataTypeEnum cellDataTypeEnum) { public static String buildKey(Class<?> clazz, CellDataTypeEnum cellDataTypeEnum) {
return buildKey(clazz) + "-" + cellDataTypeEnum.toString(); String key = buildKey(clazz);
if (cellDataTypeEnum == null) {
return key;
}
return key + "-" + cellDataTypeEnum.toString();
} }
} }

40
src/main/java/com/alibaba/excel/converters/DefaultConverterLoader.java

@ -1,6 +1,5 @@
package com.alibaba.excel.converters; package com.alibaba.excel.converters;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import com.alibaba.excel.converters.bigdecimal.BigDecimalBooleanConverter; import com.alibaba.excel.converters.bigdecimal.BigDecimalBooleanConverter;
@ -14,6 +13,7 @@ import com.alibaba.excel.converters.bytearray.ByteArrayImageConverter;
import com.alibaba.excel.converters.byteconverter.ByteBooleanConverter; import com.alibaba.excel.converters.byteconverter.ByteBooleanConverter;
import com.alibaba.excel.converters.byteconverter.ByteNumberConverter; import com.alibaba.excel.converters.byteconverter.ByteNumberConverter;
import com.alibaba.excel.converters.byteconverter.ByteStringConverter; import com.alibaba.excel.converters.byteconverter.ByteStringConverter;
import com.alibaba.excel.converters.date.DateDateConverter;
import com.alibaba.excel.converters.date.DateNumberConverter; import com.alibaba.excel.converters.date.DateNumberConverter;
import com.alibaba.excel.converters.date.DateStringConverter; import com.alibaba.excel.converters.date.DateStringConverter;
import com.alibaba.excel.converters.doubleconverter.DoubleBooleanConverter; import com.alibaba.excel.converters.doubleconverter.DoubleBooleanConverter;
@ -38,6 +38,7 @@ import com.alibaba.excel.converters.string.StringErrorConverter;
import com.alibaba.excel.converters.string.StringNumberConverter; import com.alibaba.excel.converters.string.StringNumberConverter;
import com.alibaba.excel.converters.string.StringStringConverter; import com.alibaba.excel.converters.string.StringStringConverter;
import com.alibaba.excel.converters.url.UrlImageConverter; import com.alibaba.excel.converters.url.UrlImageConverter;
import com.alibaba.excel.util.MapUtils;
/** /**
* Load default handler * Load default handler
@ -45,8 +46,8 @@ import com.alibaba.excel.converters.url.UrlImageConverter;
* @author Jiaju Zhuang * @author Jiaju Zhuang
*/ */
public class DefaultConverterLoader { public class DefaultConverterLoader {
private static Map<String, Converter> defaultWriteConverter; private static Map<String, Converter<?>> defaultWriteConverter;
private static Map<String, Converter> allConverter; private static Map<String, Converter<?>> allConverter;
static { static {
initDefaultWriteConverter(); initDefaultWriteConverter();
@ -54,7 +55,7 @@ public class DefaultConverterLoader {
} }
private static void initAllConverter() { private static void initAllConverter() {
allConverter = new HashMap<String, Converter>(64); allConverter = MapUtils.newHashMapWithExpectedSize(40);
putAllConverter(new BigDecimalBooleanConverter()); putAllConverter(new BigDecimalBooleanConverter());
putAllConverter(new BigDecimalNumberConverter()); putAllConverter(new BigDecimalNumberConverter());
putAllConverter(new BigDecimalStringConverter()); putAllConverter(new BigDecimalStringConverter());
@ -97,11 +98,11 @@ public class DefaultConverterLoader {
} }
private static void initDefaultWriteConverter() { private static void initDefaultWriteConverter() {
defaultWriteConverter = new HashMap<String, Converter>(32); defaultWriteConverter = MapUtils.newHashMapWithExpectedSize(40);
putWriteConverter(new BigDecimalNumberConverter()); putWriteConverter(new BigDecimalNumberConverter());
putWriteConverter(new BooleanBooleanConverter()); putWriteConverter(new BooleanBooleanConverter());
putWriteConverter(new ByteNumberConverter()); putWriteConverter(new ByteNumberConverter());
putWriteConverter(new DateStringConverter()); putWriteConverter(new DateDateConverter());
putWriteConverter(new DoubleNumberConverter()); putWriteConverter(new DoubleNumberConverter());
putWriteConverter(new FloatNumberConverter()); putWriteConverter(new FloatNumberConverter());
putWriteConverter(new IntegerNumberConverter()); putWriteConverter(new IntegerNumberConverter());
@ -113,6 +114,18 @@ public class DefaultConverterLoader {
putWriteConverter(new ByteArrayImageConverter()); putWriteConverter(new ByteArrayImageConverter());
putWriteConverter(new BoxingByteArrayImageConverter()); putWriteConverter(new BoxingByteArrayImageConverter());
putWriteConverter(new UrlImageConverter()); putWriteConverter(new UrlImageConverter());
// In some cases, it must be converted to string
putWriteStringConverter(new BigDecimalStringConverter());
putWriteStringConverter(new BooleanStringConverter());
putWriteStringConverter(new ByteStringConverter());
putWriteStringConverter(new DateStringConverter());
putWriteStringConverter(new DoubleStringConverter());
putWriteStringConverter(new FloatStringConverter());
putWriteStringConverter(new IntegerStringConverter());
putWriteStringConverter(new LongStringConverter());
putWriteStringConverter(new ShortStringConverter());
putWriteStringConverter(new StringStringConverter());
} }
/** /**
@ -120,20 +133,25 @@ public class DefaultConverterLoader {
* *
* @return * @return
*/ */
public static Map<String, Converter> loadDefaultWriteConverter() { public static Map<String, Converter<?>> loadDefaultWriteConverter() {
return defaultWriteConverter; return defaultWriteConverter;
} }
private static void putWriteConverter(Converter converter) { private static void putWriteConverter(Converter<?> converter) {
defaultWriteConverter.put(ConverterKeyBuild.buildKey(converter.supportJavaTypeKey()), converter); defaultWriteConverter.put(ConverterKeyBuild.buildKey(converter.supportJavaTypeKey()), converter);
} }
private static void putWriteStringConverter(Converter<?> converter) {
defaultWriteConverter.put(
ConverterKeyBuild.buildKey(converter.supportJavaTypeKey(), converter.supportExcelTypeKey()), converter);
}
/** /**
* Load default read converter * Load default read converter
* *
* @return * @return
*/ */
public static Map<String, Converter> loadDefaultReadConverter() { public static Map<String, Converter<?>> loadDefaultReadConverter() {
return loadAllConverter(); return loadAllConverter();
} }
@ -142,11 +160,11 @@ public class DefaultConverterLoader {
* *
* @return * @return
*/ */
public static Map<String, Converter> loadAllConverter() { public static Map<String, Converter<?>> loadAllConverter() {
return allConverter; return allConverter;
} }
private static void putAllConverter(Converter converter) { private static void putAllConverter(Converter<?> converter) {
allConverter.put(ConverterKeyBuild.buildKey(converter.supportJavaTypeKey(), converter.supportExcelTypeKey()), allConverter.put(ConverterKeyBuild.buildKey(converter.supportJavaTypeKey(), converter.supportExcelTypeKey()),
converter); converter);
} }

10
src/main/java/com/alibaba/excel/converters/bigdecimal/BigDecimalBooleanConverter.java

@ -16,7 +16,7 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty;
public class BigDecimalBooleanConverter implements Converter<BigDecimal> { public class BigDecimalBooleanConverter implements Converter<BigDecimal> {
@Override @Override
public Class supportJavaTypeKey() { public Class<BigDecimal> supportJavaTypeKey() {
return BigDecimal.class; return BigDecimal.class;
} }
@ -26,7 +26,7 @@ public class BigDecimalBooleanConverter implements Converter<BigDecimal> {
} }
@Override @Override
public BigDecimal convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, public BigDecimal convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
if (cellData.getBooleanValue()) { if (cellData.getBooleanValue()) {
return BigDecimal.ONE; return BigDecimal.ONE;
@ -35,12 +35,12 @@ public class BigDecimalBooleanConverter implements Converter<BigDecimal> {
} }
@Override @Override
public CellData convertToExcelData(BigDecimal value, ExcelContentProperty contentProperty, public CellData<?> convertToExcelData(BigDecimal value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
if (BigDecimal.ONE.equals(value)) { if (BigDecimal.ONE.equals(value)) {
return new CellData(Boolean.TRUE); return new CellData<>(Boolean.TRUE);
} }
return new CellData(Boolean.FALSE); return new CellData<>(Boolean.FALSE);
} }
} }

12
src/main/java/com/alibaba/excel/converters/bigdecimal/BigDecimalNumberConverter.java

@ -7,6 +7,8 @@ import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.GlobalConfiguration; import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.property.ExcelContentProperty; import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.alibaba.excel.util.NumberUtils;
import com.alibaba.excel.write.metadata.holder.WriteHolder;
/** /**
* BigDecimal and number converter * BigDecimal and number converter
@ -16,7 +18,7 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty;
public class BigDecimalNumberConverter implements Converter<BigDecimal> { public class BigDecimalNumberConverter implements Converter<BigDecimal> {
@Override @Override
public Class supportJavaTypeKey() { public Class<BigDecimal> supportJavaTypeKey() {
return BigDecimal.class; return BigDecimal.class;
} }
@ -26,14 +28,14 @@ public class BigDecimalNumberConverter implements Converter<BigDecimal> {
} }
@Override @Override
public BigDecimal convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, public BigDecimal convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
return cellData.getNumberValue(); return cellData.getNumberValue();
} }
@Override @Override
public CellData convertToExcelData(BigDecimal value, ExcelContentProperty contentProperty, public CellData<?> convertToExcelData(BigDecimal value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { WriteHolder currentWriteHolder) {
return new CellData(value); return NumberUtils.formatToCellData(value, contentProperty, currentWriteHolder);
} }
} }

8
src/main/java/com/alibaba/excel/converters/bigdecimal/BigDecimalStringConverter.java

@ -18,7 +18,7 @@ import com.alibaba.excel.util.NumberUtils;
public class BigDecimalStringConverter implements Converter<BigDecimal> { public class BigDecimalStringConverter implements Converter<BigDecimal> {
@Override @Override
public Class supportJavaTypeKey() { public Class<BigDecimal> supportJavaTypeKey() {
return BigDecimal.class; return BigDecimal.class;
} }
@ -28,14 +28,14 @@ public class BigDecimalStringConverter implements Converter<BigDecimal> {
} }
@Override @Override
public BigDecimal convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, public BigDecimal convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) throws ParseException { GlobalConfiguration globalConfiguration) throws ParseException {
return NumberUtils.parseBigDecimal(cellData.getStringValue(), contentProperty); return NumberUtils.parseBigDecimal(cellData.getStringValue(), contentProperty);
} }
@Override @Override
public CellData convertToExcelData(BigDecimal value, ExcelContentProperty contentProperty, public CellData<?> convertToExcelData(BigDecimal value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
return NumberUtils.formatToCellData(value, contentProperty); return NumberUtils.formatToCellDataString(value, contentProperty);
} }
} }

8
src/main/java/com/alibaba/excel/converters/booleanconverter/BooleanBooleanConverter.java

@ -14,7 +14,7 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty;
public class BooleanBooleanConverter implements Converter<Boolean> { public class BooleanBooleanConverter implements Converter<Boolean> {
@Override @Override
public Class supportJavaTypeKey() { public Class<?> supportJavaTypeKey() {
return Boolean.class; return Boolean.class;
} }
@ -24,15 +24,15 @@ public class BooleanBooleanConverter implements Converter<Boolean> {
} }
@Override @Override
public Boolean convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, public Boolean convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
return cellData.getBooleanValue(); return cellData.getBooleanValue();
} }
@Override @Override
public CellData convertToExcelData(Boolean value, ExcelContentProperty contentProperty, public CellData<?> convertToExcelData(Boolean value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
return new CellData(value); return new CellData<>(value);
} }
} }

10
src/main/java/com/alibaba/excel/converters/booleanconverter/BooleanNumberConverter.java

@ -15,7 +15,7 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty;
*/ */
public class BooleanNumberConverter implements Converter<Boolean> { public class BooleanNumberConverter implements Converter<Boolean> {
@Override @Override
public Class supportJavaTypeKey() { public Class<?> supportJavaTypeKey() {
return Boolean.class; return Boolean.class;
} }
@ -25,7 +25,7 @@ public class BooleanNumberConverter implements Converter<Boolean> {
} }
@Override @Override
public Boolean convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, public Boolean convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
if (BigDecimal.ONE.compareTo(cellData.getNumberValue()) == 0) { if (BigDecimal.ONE.compareTo(cellData.getNumberValue()) == 0) {
return Boolean.TRUE; return Boolean.TRUE;
@ -34,12 +34,12 @@ public class BooleanNumberConverter implements Converter<Boolean> {
} }
@Override @Override
public CellData convertToExcelData(Boolean value, ExcelContentProperty contentProperty, public CellData<?> convertToExcelData(Boolean value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
if (value) { if (value) {
return new CellData(BigDecimal.ONE); return new CellData<>(BigDecimal.ONE);
} }
return new CellData(BigDecimal.ZERO); return new CellData<>(BigDecimal.ZERO);
} }
} }

8
src/main/java/com/alibaba/excel/converters/booleanconverter/BooleanStringConverter.java

@ -14,7 +14,7 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty;
public class BooleanStringConverter implements Converter<Boolean> { public class BooleanStringConverter implements Converter<Boolean> {
@Override @Override
public Class supportJavaTypeKey() { public Class<?> supportJavaTypeKey() {
return Boolean.class; return Boolean.class;
} }
@ -24,15 +24,15 @@ public class BooleanStringConverter implements Converter<Boolean> {
} }
@Override @Override
public Boolean convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, public Boolean convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
return Boolean.valueOf(cellData.getStringValue()); return Boolean.valueOf(cellData.getStringValue());
} }
@Override @Override
public CellData convertToExcelData(Boolean value, ExcelContentProperty contentProperty, public CellData<?> convertToExcelData(Boolean value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
return new CellData(value.toString()); return new CellData<>(value.toString());
} }
} }

8
src/main/java/com/alibaba/excel/converters/bytearray/BoxingByteArrayImageConverter.java

@ -13,7 +13,7 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty;
*/ */
public class BoxingByteArrayImageConverter implements Converter<Byte[]> { public class BoxingByteArrayImageConverter implements Converter<Byte[]> {
@Override @Override
public Class supportJavaTypeKey() { public Class<?> supportJavaTypeKey() {
return Byte[].class; return Byte[].class;
} }
@ -23,19 +23,19 @@ public class BoxingByteArrayImageConverter implements Converter<Byte[]> {
} }
@Override @Override
public Byte[] convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, public Byte[] convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
throw new UnsupportedOperationException("Cannot convert images to byte arrays"); throw new UnsupportedOperationException("Cannot convert images to byte arrays");
} }
@Override @Override
public CellData convertToExcelData(Byte[] value, ExcelContentProperty contentProperty, public CellData<?> convertToExcelData(Byte[] value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
byte[] byteValue = new byte[value.length]; byte[] byteValue = new byte[value.length];
for (int i = 0; i < value.length; i++) { for (int i = 0; i < value.length; i++) {
byteValue[i] = value[i]; byteValue[i] = value[i];
} }
return new CellData(byteValue); return new CellData<>(byteValue);
} }
} }

8
src/main/java/com/alibaba/excel/converters/bytearray/ByteArrayImageConverter.java

@ -13,7 +13,7 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty;
*/ */
public class ByteArrayImageConverter implements Converter<byte[]> { public class ByteArrayImageConverter implements Converter<byte[]> {
@Override @Override
public Class supportJavaTypeKey() { public Class<byte[]> supportJavaTypeKey() {
return byte[].class; return byte[].class;
} }
@ -23,15 +23,15 @@ public class ByteArrayImageConverter implements Converter<byte[]> {
} }
@Override @Override
public byte[] convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, public byte[] convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
throw new UnsupportedOperationException("Cannot convert images to byte arrays"); throw new UnsupportedOperationException("Cannot convert images to byte arrays");
} }
@Override @Override
public CellData convertToExcelData(byte[] value, ExcelContentProperty contentProperty, public CellData<?> convertToExcelData(byte[] value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
return new CellData(value); return new CellData<>(value);
} }
} }

10
src/main/java/com/alibaba/excel/converters/byteconverter/ByteBooleanConverter.java

@ -16,7 +16,7 @@ public class ByteBooleanConverter implements Converter<Byte> {
private static final Byte ZERO = (byte)0; private static final Byte ZERO = (byte)0;
@Override @Override
public Class supportJavaTypeKey() { public Class<?> supportJavaTypeKey() {
return Byte.class; return Byte.class;
} }
@ -26,7 +26,7 @@ public class ByteBooleanConverter implements Converter<Byte> {
} }
@Override @Override
public Byte convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, public Byte convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
if (cellData.getBooleanValue()) { if (cellData.getBooleanValue()) {
return ONE; return ONE;
@ -35,12 +35,12 @@ public class ByteBooleanConverter implements Converter<Byte> {
} }
@Override @Override
public CellData convertToExcelData(Byte value, ExcelContentProperty contentProperty, public CellData<?> convertToExcelData(Byte value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
if (ONE.equals(value)) { if (ONE.equals(value)) {
return new CellData(Boolean.TRUE); return new CellData<>(Boolean.TRUE);
} }
return new CellData(Boolean.FALSE); return new CellData<>(Boolean.FALSE);
} }
} }

12
src/main/java/com/alibaba/excel/converters/byteconverter/ByteNumberConverter.java

@ -7,6 +7,8 @@ import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.GlobalConfiguration; import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.property.ExcelContentProperty; import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.alibaba.excel.util.NumberUtils;
import com.alibaba.excel.write.metadata.holder.WriteHolder;
/** /**
* Byte and number converter * Byte and number converter
@ -16,7 +18,7 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty;
public class ByteNumberConverter implements Converter<Byte> { public class ByteNumberConverter implements Converter<Byte> {
@Override @Override
public Class supportJavaTypeKey() { public Class<?> supportJavaTypeKey() {
return Byte.class; return Byte.class;
} }
@ -26,15 +28,15 @@ public class ByteNumberConverter implements Converter<Byte> {
} }
@Override @Override
public Byte convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, public Byte convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
return cellData.getNumberValue().byteValue(); return cellData.getNumberValue().byteValue();
} }
@Override @Override
public CellData convertToExcelData(Byte value, ExcelContentProperty contentProperty, public CellData<?> convertToExcelData(Byte value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { WriteHolder currentWriteHolder) {
return new CellData(new BigDecimal(Byte.toString(value))); return NumberUtils.formatToCellData(value, contentProperty, currentWriteHolder);
} }
} }

8
src/main/java/com/alibaba/excel/converters/byteconverter/ByteStringConverter.java

@ -17,7 +17,7 @@ import com.alibaba.excel.util.NumberUtils;
public class ByteStringConverter implements Converter<Byte> { public class ByteStringConverter implements Converter<Byte> {
@Override @Override
public Class supportJavaTypeKey() { public Class<?> supportJavaTypeKey() {
return Byte.class; return Byte.class;
} }
@ -27,15 +27,15 @@ public class ByteStringConverter implements Converter<Byte> {
} }
@Override @Override
public Byte convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, public Byte convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) throws ParseException { GlobalConfiguration globalConfiguration) throws ParseException {
return NumberUtils.parseByte(cellData.getStringValue(), contentProperty); return NumberUtils.parseByte(cellData.getStringValue(), contentProperty);
} }
@Override @Override
public CellData convertToExcelData(Byte value, ExcelContentProperty contentProperty, public CellData<?> convertToExcelData(Byte value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
return NumberUtils.formatToCellData(value, contentProperty); return NumberUtils.formatToCellDataString(value, contentProperty);
} }
} }

47
src/main/java/com/alibaba/excel/converters/date/DateDateConverter.java

@ -0,0 +1,47 @@
package com.alibaba.excel.converters.date;
import java.util.Date;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.alibaba.excel.util.WorkBookUtil;
import com.alibaba.excel.write.metadata.holder.WriteHolder;
/**
* Date and date converter
*
* @author Jiaju Zhuang
*/
public class DateDateConverter implements Converter<Date> {
@Override
public Class<Date> supportJavaTypeKey() {
return Date.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.DATE;
}
@Override
public Date convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
return cellData.getDateValue();
}
@Override
public CellData<?> convertToExcelData(Date value, ExcelContentProperty contentProperty,
WriteHolder currentWriteHolder) throws Exception {
CellData<?> cellData = new CellData<>(value);
if (contentProperty == null || contentProperty.getDateTimeFormatProperty() == null
|| contentProperty.getDateTimeFormatProperty().getFormat() == null) {
return cellData;
}
WorkBookUtil.fillDataFormat(cellData, currentWriteHolder,
contentProperty.getDateTimeFormatProperty().getFormat());
return cellData;
}
}

10
src/main/java/com/alibaba/excel/converters/date/DateNumberConverter.java

@ -19,7 +19,7 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty;
public class DateNumberConverter implements Converter<Date> { public class DateNumberConverter implements Converter<Date> {
@Override @Override
public Class supportJavaTypeKey() { public Class<?> supportJavaTypeKey() {
return Date.class; return Date.class;
} }
@ -29,7 +29,7 @@ public class DateNumberConverter implements Converter<Date> {
} }
@Override @Override
public Date convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, public Date convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
if (contentProperty == null || contentProperty.getDateTimeFormatProperty() == null) { if (contentProperty == null || contentProperty.getDateTimeFormatProperty() == null) {
return DateUtil.getJavaDate(cellData.getNumberValue().doubleValue(), return DateUtil.getJavaDate(cellData.getNumberValue().doubleValue(),
@ -41,13 +41,13 @@ public class DateNumberConverter implements Converter<Date> {
} }
@Override @Override
public CellData convertToExcelData(Date value, ExcelContentProperty contentProperty, public CellData<?> convertToExcelData(Date value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
if (contentProperty == null || contentProperty.getDateTimeFormatProperty() == null) { if (contentProperty == null || contentProperty.getDateTimeFormatProperty() == null) {
return new CellData( return new CellData<>(
BigDecimal.valueOf(DateUtil.getExcelDate(value, globalConfiguration.getUse1904windowing()))); BigDecimal.valueOf(DateUtil.getExcelDate(value, globalConfiguration.getUse1904windowing())));
} else { } else {
return new CellData(BigDecimal.valueOf( return new CellData<>(BigDecimal.valueOf(
DateUtil.getExcelDate(value, contentProperty.getDateTimeFormatProperty().getUse1904windowing()))); DateUtil.getExcelDate(value, contentProperty.getDateTimeFormatProperty().getUse1904windowing())));
} }
} }

10
src/main/java/com/alibaba/excel/converters/date/DateStringConverter.java

@ -17,7 +17,7 @@ import com.alibaba.excel.util.DateUtils;
*/ */
public class DateStringConverter implements Converter<Date> { public class DateStringConverter implements Converter<Date> {
@Override @Override
public Class supportJavaTypeKey() { public Class<?> supportJavaTypeKey() {
return Date.class; return Date.class;
} }
@ -27,7 +27,7 @@ public class DateStringConverter implements Converter<Date> {
} }
@Override @Override
public Date convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, public Date convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) throws ParseException { GlobalConfiguration globalConfiguration) throws ParseException {
if (contentProperty == null || contentProperty.getDateTimeFormatProperty() == null) { if (contentProperty == null || contentProperty.getDateTimeFormatProperty() == null) {
return DateUtils.parseDate(cellData.getStringValue(), null); return DateUtils.parseDate(cellData.getStringValue(), null);
@ -38,12 +38,12 @@ public class DateStringConverter implements Converter<Date> {
} }
@Override @Override
public CellData convertToExcelData(Date value, ExcelContentProperty contentProperty, public CellData<?> convertToExcelData(Date value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
if (contentProperty == null || contentProperty.getDateTimeFormatProperty() == null) { if (contentProperty == null || contentProperty.getDateTimeFormatProperty() == null) {
return new CellData(DateUtils.format(value, null)); return new CellData<>(DateUtils.format(value, null));
} else { } else {
return new CellData(DateUtils.format(value, contentProperty.getDateTimeFormatProperty().getFormat())); return new CellData<>(DateUtils.format(value, contentProperty.getDateTimeFormatProperty().getFormat()));
} }
} }
} }

10
src/main/java/com/alibaba/excel/converters/doubleconverter/DoubleBooleanConverter.java

@ -16,7 +16,7 @@ public class DoubleBooleanConverter implements Converter<Double> {
private static final Double ZERO = 0.0; private static final Double ZERO = 0.0;
@Override @Override
public Class supportJavaTypeKey() { public Class<?> supportJavaTypeKey() {
return Double.class; return Double.class;
} }
@ -26,7 +26,7 @@ public class DoubleBooleanConverter implements Converter<Double> {
} }
@Override @Override
public Double convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, public Double convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
if (cellData.getBooleanValue()) { if (cellData.getBooleanValue()) {
return ONE; return ONE;
@ -35,12 +35,12 @@ public class DoubleBooleanConverter implements Converter<Double> {
} }
@Override @Override
public CellData convertToExcelData(Double value, ExcelContentProperty contentProperty, public CellData<?> convertToExcelData(Double value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
if (ONE.equals(value)) { if (ONE.equals(value)) {
return new CellData(Boolean.TRUE); return new CellData<>(Boolean.TRUE);
} }
return new CellData(Boolean.FALSE); return new CellData<>(Boolean.FALSE);
} }
} }

13
src/main/java/com/alibaba/excel/converters/doubleconverter/DoubleNumberConverter.java

@ -7,6 +7,8 @@ import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.GlobalConfiguration; import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.property.ExcelContentProperty; import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.alibaba.excel.util.NumberUtils;
import com.alibaba.excel.write.metadata.holder.WriteHolder;
/** /**
* Double and number converter * Double and number converter
@ -16,7 +18,7 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty;
public class DoubleNumberConverter implements Converter<Double> { public class DoubleNumberConverter implements Converter<Double> {
@Override @Override
public Class supportJavaTypeKey() { public Class<?> supportJavaTypeKey() {
return Double.class; return Double.class;
} }
@ -26,15 +28,14 @@ public class DoubleNumberConverter implements Converter<Double> {
} }
@Override @Override
public Double convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, public Double convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
return cellData.getNumberValue().doubleValue(); return cellData.getNumberValue().doubleValue();
} }
@Override @Override
public CellData convertToExcelData(Double value, ExcelContentProperty contentProperty, public CellData<?> convertToExcelData(Double value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { WriteHolder currentWriteHolder) {
return new CellData(BigDecimal.valueOf(value)); return NumberUtils.formatToCellData(value, contentProperty, currentWriteHolder);
} }
} }

8
src/main/java/com/alibaba/excel/converters/doubleconverter/DoubleStringConverter.java

@ -17,7 +17,7 @@ import com.alibaba.excel.util.NumberUtils;
public class DoubleStringConverter implements Converter<Double> { public class DoubleStringConverter implements Converter<Double> {
@Override @Override
public Class supportJavaTypeKey() { public Class<?> supportJavaTypeKey() {
return Double.class; return Double.class;
} }
@ -27,14 +27,14 @@ public class DoubleStringConverter implements Converter<Double> {
} }
@Override @Override
public Double convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, public Double convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) throws ParseException { GlobalConfiguration globalConfiguration) throws ParseException {
return NumberUtils.parseDouble(cellData.getStringValue(), contentProperty); return NumberUtils.parseDouble(cellData.getStringValue(), contentProperty);
} }
@Override @Override
public CellData convertToExcelData(Double value, ExcelContentProperty contentProperty, public CellData<?> convertToExcelData(Double value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
return NumberUtils.formatToCellData(value, contentProperty); return NumberUtils.formatToCellDataString(value, contentProperty);
} }
} }

8
src/main/java/com/alibaba/excel/converters/file/FileImageConverter.java

@ -17,7 +17,7 @@ import com.alibaba.excel.util.FileUtils;
*/ */
public class FileImageConverter implements Converter<File> { public class FileImageConverter implements Converter<File> {
@Override @Override
public Class supportJavaTypeKey() { public Class<?> supportJavaTypeKey() {
return File.class; return File.class;
} }
@ -27,15 +27,15 @@ public class FileImageConverter implements Converter<File> {
} }
@Override @Override
public File convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, public File convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
throw new UnsupportedOperationException("Cannot convert images to file"); throw new UnsupportedOperationException("Cannot convert images to file");
} }
@Override @Override
public CellData convertToExcelData(File value, ExcelContentProperty contentProperty, public CellData<?> convertToExcelData(File value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) throws IOException { GlobalConfiguration globalConfiguration) throws IOException {
return new CellData(FileUtils.readFileToByteArray(value)); return new CellData<>(FileUtils.readFileToByteArray(value));
} }
} }

10
src/main/java/com/alibaba/excel/converters/floatconverter/FloatBooleanConverter.java

@ -16,7 +16,7 @@ public class FloatBooleanConverter implements Converter<Float> {
private static final Float ZERO = (float)0.0; private static final Float ZERO = (float)0.0;
@Override @Override
public Class supportJavaTypeKey() { public Class<?> supportJavaTypeKey() {
return Float.class; return Float.class;
} }
@ -26,7 +26,7 @@ public class FloatBooleanConverter implements Converter<Float> {
} }
@Override @Override
public Float convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, public Float convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
if (cellData.getBooleanValue()) { if (cellData.getBooleanValue()) {
return ONE; return ONE;
@ -35,12 +35,12 @@ public class FloatBooleanConverter implements Converter<Float> {
} }
@Override @Override
public CellData convertToExcelData(Float value, ExcelContentProperty contentProperty, public CellData<?> convertToExcelData(Float value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
if (ONE.equals(value)) { if (ONE.equals(value)) {
return new CellData(Boolean.TRUE); return new CellData<>(Boolean.TRUE);
} }
return new CellData(Boolean.FALSE); return new CellData<>(Boolean.FALSE);
} }
} }

15
src/main/java/com/alibaba/excel/converters/floatconverter/FloatNumberConverter.java

@ -1,12 +1,12 @@
package com.alibaba.excel.converters.floatconverter; package com.alibaba.excel.converters.floatconverter;
import java.math.BigDecimal;
import com.alibaba.excel.converters.Converter; import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum; import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.GlobalConfiguration; import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.property.ExcelContentProperty; import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.alibaba.excel.util.NumberUtils;
import com.alibaba.excel.write.metadata.holder.WriteHolder;
/** /**
* Float and number converter * Float and number converter
@ -16,7 +16,7 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty;
public class FloatNumberConverter implements Converter<Float> { public class FloatNumberConverter implements Converter<Float> {
@Override @Override
public Class supportJavaTypeKey() { public Class<?> supportJavaTypeKey() {
return Float.class; return Float.class;
} }
@ -26,15 +26,14 @@ public class FloatNumberConverter implements Converter<Float> {
} }
@Override @Override
public Float convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, public Float convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
return cellData.getNumberValue().floatValue(); return cellData.getNumberValue().floatValue();
} }
@Override @Override
public CellData convertToExcelData(Float value, ExcelContentProperty contentProperty, public CellData<?> convertToExcelData(Float value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { WriteHolder currentWriteHolder) {
return new CellData(new BigDecimal(Float.toString(value))); return NumberUtils.formatToCellData(value, contentProperty, currentWriteHolder);
} }
} }

8
src/main/java/com/alibaba/excel/converters/floatconverter/FloatStringConverter.java

@ -17,7 +17,7 @@ import com.alibaba.excel.util.NumberUtils;
public class FloatStringConverter implements Converter<Float> { public class FloatStringConverter implements Converter<Float> {
@Override @Override
public Class supportJavaTypeKey() { public Class<?> supportJavaTypeKey() {
return Float.class; return Float.class;
} }
@ -27,14 +27,14 @@ public class FloatStringConverter implements Converter<Float> {
} }
@Override @Override
public Float convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, public Float convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) throws ParseException { GlobalConfiguration globalConfiguration) throws ParseException {
return NumberUtils.parseFloat(cellData.getStringValue(), contentProperty); return NumberUtils.parseFloat(cellData.getStringValue(), contentProperty);
} }
@Override @Override
public CellData convertToExcelData(Float value, ExcelContentProperty contentProperty, public CellData<?> convertToExcelData(Float value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
return NumberUtils.formatToCellData(value, contentProperty); return NumberUtils.formatToCellDataString(value, contentProperty);
} }
} }

8
src/main/java/com/alibaba/excel/converters/inputstream/InputStreamImageConverter.java

@ -17,7 +17,7 @@ import com.alibaba.excel.util.IoUtils;
*/ */
public class InputStreamImageConverter implements Converter<InputStream> { public class InputStreamImageConverter implements Converter<InputStream> {
@Override @Override
public Class supportJavaTypeKey() { public Class<?> supportJavaTypeKey() {
return InputStream.class; return InputStream.class;
} }
@ -27,15 +27,15 @@ public class InputStreamImageConverter implements Converter<InputStream> {
} }
@Override @Override
public InputStream convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, public InputStream convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
throw new UnsupportedOperationException("Cannot convert images to input stream"); throw new UnsupportedOperationException("Cannot convert images to input stream");
} }
@Override @Override
public CellData convertToExcelData(InputStream value, ExcelContentProperty contentProperty, public CellData<?> convertToExcelData(InputStream value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) throws IOException { GlobalConfiguration globalConfiguration) throws IOException {
return new CellData(IoUtils.toByteArray(value)); return new CellData<>(IoUtils.toByteArray(value));
} }
} }

10
src/main/java/com/alibaba/excel/converters/integer/IntegerBooleanConverter.java

@ -16,7 +16,7 @@ public class IntegerBooleanConverter implements Converter<Integer> {
private static final Integer ZERO = 0; private static final Integer ZERO = 0;
@Override @Override
public Class supportJavaTypeKey() { public Class<?> supportJavaTypeKey() {
return Integer.class; return Integer.class;
} }
@ -26,7 +26,7 @@ public class IntegerBooleanConverter implements Converter<Integer> {
} }
@Override @Override
public Integer convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, public Integer convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
if (cellData.getBooleanValue()) { if (cellData.getBooleanValue()) {
return ONE; return ONE;
@ -35,12 +35,12 @@ public class IntegerBooleanConverter implements Converter<Integer> {
} }
@Override @Override
public CellData convertToExcelData(Integer value, ExcelContentProperty contentProperty, public CellData<?> convertToExcelData(Integer value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
if (ONE.equals(value)) { if (ONE.equals(value)) {
return new CellData(Boolean.TRUE); return new CellData<>(Boolean.TRUE);
} }
return new CellData(Boolean.FALSE); return new CellData<>(Boolean.FALSE);
} }
} }

14
src/main/java/com/alibaba/excel/converters/integer/IntegerNumberConverter.java

@ -1,12 +1,12 @@
package com.alibaba.excel.converters.integer; package com.alibaba.excel.converters.integer;
import java.math.BigDecimal;
import com.alibaba.excel.converters.Converter; import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum; import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.GlobalConfiguration; import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.property.ExcelContentProperty; import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.alibaba.excel.util.NumberUtils;
import com.alibaba.excel.write.metadata.holder.WriteHolder;
/** /**
* Integer and number converter * Integer and number converter
@ -16,7 +16,7 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty;
public class IntegerNumberConverter implements Converter<Integer> { public class IntegerNumberConverter implements Converter<Integer> {
@Override @Override
public Class supportJavaTypeKey() { public Class<?> supportJavaTypeKey() {
return Integer.class; return Integer.class;
} }
@ -26,15 +26,15 @@ public class IntegerNumberConverter implements Converter<Integer> {
} }
@Override @Override
public Integer convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, public Integer convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
return cellData.getNumberValue().intValue(); return cellData.getNumberValue().intValue();
} }
@Override @Override
public CellData convertToExcelData(Integer value, ExcelContentProperty contentProperty, public CellData<?> convertToExcelData(Integer value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { WriteHolder currentWriteHolder) {
return new CellData(new BigDecimal(Integer.toString(value))); return NumberUtils.formatToCellData(value, contentProperty, currentWriteHolder);
} }
} }

8
src/main/java/com/alibaba/excel/converters/integer/IntegerStringConverter.java

@ -17,7 +17,7 @@ import com.alibaba.excel.util.NumberUtils;
public class IntegerStringConverter implements Converter<Integer> { public class IntegerStringConverter implements Converter<Integer> {
@Override @Override
public Class supportJavaTypeKey() { public Class<?> supportJavaTypeKey() {
return Integer.class; return Integer.class;
} }
@ -27,14 +27,14 @@ public class IntegerStringConverter implements Converter<Integer> {
} }
@Override @Override
public Integer convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, public Integer convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) throws ParseException { GlobalConfiguration globalConfiguration) throws ParseException {
return NumberUtils.parseInteger(cellData.getStringValue(), contentProperty); return NumberUtils.parseInteger(cellData.getStringValue(), contentProperty);
} }
@Override @Override
public CellData convertToExcelData(Integer value, ExcelContentProperty contentProperty, public CellData<?> convertToExcelData(Integer value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
return NumberUtils.formatToCellData(value, contentProperty); return NumberUtils.formatToCellDataString(value, contentProperty);
} }
} }

10
src/main/java/com/alibaba/excel/converters/longconverter/LongBooleanConverter.java

@ -16,7 +16,7 @@ public class LongBooleanConverter implements Converter<Long> {
private static final Long ZERO = 0L; private static final Long ZERO = 0L;
@Override @Override
public Class supportJavaTypeKey() { public Class<Long> supportJavaTypeKey() {
return Long.class; return Long.class;
} }
@ -26,7 +26,7 @@ public class LongBooleanConverter implements Converter<Long> {
} }
@Override @Override
public Long convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, public Long convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
if (cellData.getBooleanValue()) { if (cellData.getBooleanValue()) {
return ONE; return ONE;
@ -35,12 +35,12 @@ public class LongBooleanConverter implements Converter<Long> {
} }
@Override @Override
public CellData convertToExcelData(Long value, ExcelContentProperty contentProperty, public CellData<?> convertToExcelData(Long value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
if (ONE.equals(value)) { if (ONE.equals(value)) {
return new CellData(Boolean.TRUE); return new CellData<>(Boolean.TRUE);
} }
return new CellData(Boolean.FALSE); return new CellData<>(Boolean.FALSE);
} }
} }

14
src/main/java/com/alibaba/excel/converters/longconverter/LongNumberConverter.java

@ -1,12 +1,12 @@
package com.alibaba.excel.converters.longconverter; package com.alibaba.excel.converters.longconverter;
import java.math.BigDecimal;
import com.alibaba.excel.converters.Converter; import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum; import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.GlobalConfiguration; import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.property.ExcelContentProperty; import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.alibaba.excel.util.NumberUtils;
import com.alibaba.excel.write.metadata.holder.WriteHolder;
/** /**
* Long and number converter * Long and number converter
@ -16,7 +16,7 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty;
public class LongNumberConverter implements Converter<Long> { public class LongNumberConverter implements Converter<Long> {
@Override @Override
public Class supportJavaTypeKey() { public Class<Long> supportJavaTypeKey() {
return Long.class; return Long.class;
} }
@ -26,15 +26,15 @@ public class LongNumberConverter implements Converter<Long> {
} }
@Override @Override
public Long convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, public Long convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
return cellData.getNumberValue().longValue(); return cellData.getNumberValue().longValue();
} }
@Override @Override
public CellData convertToExcelData(Long value, ExcelContentProperty contentProperty, public CellData<?> convertToExcelData(Long value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { WriteHolder currentWriteHolder) {
return new CellData(BigDecimal.valueOf(value)); return NumberUtils.formatToCellData(value, contentProperty, currentWriteHolder);
} }
} }

8
src/main/java/com/alibaba/excel/converters/longconverter/LongStringConverter.java

@ -17,7 +17,7 @@ import com.alibaba.excel.util.NumberUtils;
public class LongStringConverter implements Converter<Long> { public class LongStringConverter implements Converter<Long> {
@Override @Override
public Class supportJavaTypeKey() { public Class<Long> supportJavaTypeKey() {
return Long.class; return Long.class;
} }
@ -27,14 +27,14 @@ public class LongStringConverter implements Converter<Long> {
} }
@Override @Override
public Long convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, public Long convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) throws ParseException { GlobalConfiguration globalConfiguration) throws ParseException {
return NumberUtils.parseLong(cellData.getStringValue(), contentProperty); return NumberUtils.parseLong(cellData.getStringValue(), contentProperty);
} }
@Override @Override
public CellData convertToExcelData(Long value, ExcelContentProperty contentProperty, public CellData<?> convertToExcelData(Long value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
return NumberUtils.formatToCellData(value, contentProperty); return NumberUtils.formatToCellDataString(value, contentProperty);
} }
} }

10
src/main/java/com/alibaba/excel/converters/shortconverter/ShortBooleanConverter.java

@ -16,7 +16,7 @@ public class ShortBooleanConverter implements Converter<Short> {
private static final Short ZERO = 0; private static final Short ZERO = 0;
@Override @Override
public Class supportJavaTypeKey() { public Class<Short> supportJavaTypeKey() {
return Short.class; return Short.class;
} }
@ -26,7 +26,7 @@ public class ShortBooleanConverter implements Converter<Short> {
} }
@Override @Override
public Short convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, public Short convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
if (cellData.getBooleanValue()) { if (cellData.getBooleanValue()) {
return ONE; return ONE;
@ -35,12 +35,12 @@ public class ShortBooleanConverter implements Converter<Short> {
} }
@Override @Override
public CellData convertToExcelData(Short value, ExcelContentProperty contentProperty, public CellData<?> convertToExcelData(Short value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
if (ONE.equals(value)) { if (ONE.equals(value)) {
return new CellData(Boolean.TRUE); return new CellData<>(Boolean.TRUE);
} }
return new CellData(Boolean.FALSE); return new CellData<>(Boolean.FALSE);
} }
} }

13
src/main/java/com/alibaba/excel/converters/shortconverter/ShortNumberConverter.java

@ -7,6 +7,8 @@ import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.GlobalConfiguration; import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.property.ExcelContentProperty; import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.alibaba.excel.util.NumberUtils;
import com.alibaba.excel.write.metadata.holder.WriteHolder;
/** /**
* Short and number converter * Short and number converter
@ -16,7 +18,7 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty;
public class ShortNumberConverter implements Converter<Short> { public class ShortNumberConverter implements Converter<Short> {
@Override @Override
public Class supportJavaTypeKey() { public Class<Short> supportJavaTypeKey() {
return Short.class; return Short.class;
} }
@ -26,15 +28,14 @@ public class ShortNumberConverter implements Converter<Short> {
} }
@Override @Override
public Short convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, public Short convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
return cellData.getNumberValue().shortValue(); return cellData.getNumberValue().shortValue();
} }
@Override @Override
public CellData convertToExcelData(Short value, ExcelContentProperty contentProperty, public CellData<?> convertToExcelData(Short value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { WriteHolder currentWriteHolder) {
return new CellData(new BigDecimal(Short.toString(value))); return NumberUtils.formatToCellData(value, contentProperty, currentWriteHolder);
} }
} }

8
src/main/java/com/alibaba/excel/converters/shortconverter/ShortStringConverter.java

@ -17,7 +17,7 @@ import com.alibaba.excel.util.NumberUtils;
public class ShortStringConverter implements Converter<Short> { public class ShortStringConverter implements Converter<Short> {
@Override @Override
public Class supportJavaTypeKey() { public Class<?> supportJavaTypeKey() {
return Short.class; return Short.class;
} }
@ -27,14 +27,14 @@ public class ShortStringConverter implements Converter<Short> {
} }
@Override @Override
public Short convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, public Short convertToJavaData(CellData<?>cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) throws ParseException { GlobalConfiguration globalConfiguration) throws ParseException {
return NumberUtils.parseShort(cellData.getStringValue(), contentProperty); return NumberUtils.parseShort(cellData.getStringValue(), contentProperty);
} }
@Override @Override
public CellData convertToExcelData(Short value, ExcelContentProperty contentProperty, public CellData<?>convertToExcelData(Short value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
return NumberUtils.formatToCellData(value, contentProperty); return NumberUtils.formatToCellDataString(value, contentProperty);
} }
} }

8
src/main/java/com/alibaba/excel/converters/string/StringBooleanConverter.java

@ -14,7 +14,7 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty;
public class StringBooleanConverter implements Converter<String> { public class StringBooleanConverter implements Converter<String> {
@Override @Override
public Class supportJavaTypeKey() { public Class<?> supportJavaTypeKey() {
return String.class; return String.class;
} }
@ -24,15 +24,15 @@ public class StringBooleanConverter implements Converter<String> {
} }
@Override @Override
public String convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, public String convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
return cellData.getBooleanValue().toString(); return cellData.getBooleanValue().toString();
} }
@Override @Override
public CellData convertToExcelData(String value, ExcelContentProperty contentProperty, public CellData<?> convertToExcelData(String value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
return new CellData(Boolean.valueOf(value)); return new CellData<>(Boolean.valueOf(value));
} }
} }

8
src/main/java/com/alibaba/excel/converters/string/StringErrorConverter.java

@ -13,7 +13,7 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty;
*/ */
public class StringErrorConverter implements Converter<String> { public class StringErrorConverter implements Converter<String> {
@Override @Override
public Class supportJavaTypeKey() { public Class<String> supportJavaTypeKey() {
return String.class; return String.class;
} }
@ -23,15 +23,15 @@ public class StringErrorConverter implements Converter<String> {
} }
@Override @Override
public String convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, public String convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
return cellData.getStringValue(); return cellData.getStringValue();
} }
@Override @Override
public CellData convertToExcelData(String value, ExcelContentProperty contentProperty, public CellData<?> convertToExcelData(String value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
return new CellData(CellDataTypeEnum.ERROR, value); return new CellData<>(CellDataTypeEnum.ERROR, value);
} }
} }

8
src/main/java/com/alibaba/excel/converters/string/StringImageConverter.java

@ -17,7 +17,7 @@ import com.alibaba.excel.util.FileUtils;
*/ */
public class StringImageConverter implements Converter<String> { public class StringImageConverter implements Converter<String> {
@Override @Override
public Class supportJavaTypeKey() { public Class<?> supportJavaTypeKey() {
return String.class; return String.class;
} }
@ -27,15 +27,15 @@ public class StringImageConverter implements Converter<String> {
} }
@Override @Override
public String convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, public String convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
throw new UnsupportedOperationException("Cannot convert images to string"); throw new UnsupportedOperationException("Cannot convert images to string");
} }
@Override @Override
public CellData convertToExcelData(String value, ExcelContentProperty contentProperty, public CellData<?> convertToExcelData(String value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) throws IOException { GlobalConfiguration globalConfiguration) throws IOException {
return new CellData(FileUtils.readFileToByteArray(new File(value))); return new CellData<>(FileUtils.readFileToByteArray(new File(value)));
} }
} }

8
src/main/java/com/alibaba/excel/converters/string/StringNumberConverter.java

@ -22,7 +22,7 @@ import com.alibaba.excel.util.StringUtils;
public class StringNumberConverter implements Converter<String> { public class StringNumberConverter implements Converter<String> {
@Override @Override
public Class supportJavaTypeKey() { public Class<?> supportJavaTypeKey() {
return String.class; return String.class;
} }
@ -32,7 +32,7 @@ public class StringNumberConverter implements Converter<String> {
} }
@Override @Override
public String convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, public String convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
// If there are "DateTimeFormat", read as date // If there are "DateTimeFormat", read as date
if (contentProperty != null && contentProperty.getDateTimeFormatProperty() != null) { if (contentProperty != null && contentProperty.getDateTimeFormatProperty() != null) {
@ -55,8 +55,8 @@ public class StringNumberConverter implements Converter<String> {
} }
@Override @Override
public CellData convertToExcelData(String value, ExcelContentProperty contentProperty, public CellData<?> convertToExcelData(String value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
return new CellData(new BigDecimal(value)); return new CellData<>(new BigDecimal(value));
} }
} }

8
src/main/java/com/alibaba/excel/converters/string/StringStringConverter.java

@ -13,7 +13,7 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty;
*/ */
public class StringStringConverter implements Converter<String> { public class StringStringConverter implements Converter<String> {
@Override @Override
public Class supportJavaTypeKey() { public Class<?> supportJavaTypeKey() {
return String.class; return String.class;
} }
@ -23,15 +23,15 @@ public class StringStringConverter implements Converter<String> {
} }
@Override @Override
public String convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, public String convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
return cellData.getStringValue(); return cellData.getStringValue();
} }
@Override @Override
public CellData convertToExcelData(String value, ExcelContentProperty contentProperty, public CellData<?> convertToExcelData(String value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
return new CellData(value); return new CellData<>(value);
} }
} }

8
src/main/java/com/alibaba/excel/converters/url/UrlImageConverter.java

@ -19,7 +19,7 @@ import com.alibaba.excel.util.IoUtils;
*/ */
public class UrlImageConverter implements Converter<URL> { public class UrlImageConverter implements Converter<URL> {
@Override @Override
public Class supportJavaTypeKey() { public Class<?> supportJavaTypeKey() {
return URL.class; return URL.class;
} }
@ -29,19 +29,19 @@ public class UrlImageConverter implements Converter<URL> {
} }
@Override @Override
public URL convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, public URL convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
throw new UnsupportedOperationException("Cannot convert images to url."); throw new UnsupportedOperationException("Cannot convert images to url.");
} }
@Override @Override
public CellData convertToExcelData(URL value, ExcelContentProperty contentProperty, public CellData<?> convertToExcelData(URL value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) throws IOException { GlobalConfiguration globalConfiguration) throws IOException {
InputStream inputStream = null; InputStream inputStream = null;
try { try {
inputStream = value.openStream(); inputStream = value.openStream();
byte[] bytes = IoUtils.toByteArray(inputStream); byte[] bytes = IoUtils.toByteArray(inputStream);
return new CellData(bytes); return new CellData<>(bytes);
} finally { } finally {
if (inputStream != null) { if (inputStream != null) {
inputStream.close(); inputStream.close();

8
src/main/java/com/alibaba/excel/enums/CellDataTypeEnum.java

@ -39,9 +39,15 @@ public enum CellDataTypeEnum {
/** /**
* Images are currently supported only when writing * Images are currently supported only when writing
*/ */
IMAGE; IMAGE,
/**
* date.Support only when writing.
*/
DATE,
;
private static final Map<String, CellDataTypeEnum> TYPE_ROUTING_MAP = new HashMap<String, CellDataTypeEnum>(16); private static final Map<String, CellDataTypeEnum> TYPE_ROUTING_MAP = new HashMap<String, CellDataTypeEnum>(16);
static { static {
TYPE_ROUTING_MAP.put("s", STRING); TYPE_ROUTING_MAP.put("s", STRING);
TYPE_ROUTING_MAP.put("str", DIRECT_STRING); TYPE_ROUTING_MAP.put("str", DIRECT_STRING);

2
src/main/java/com/alibaba/excel/event/AnalysisEventListener.java

@ -16,7 +16,7 @@ import com.alibaba.excel.util.ConverterUtils;
public abstract class AnalysisEventListener<T> implements ReadListener<T> { public abstract class AnalysisEventListener<T> implements ReadListener<T> {
@Override @Override
public void invokeHead(Map<Integer, CellData> headMap, AnalysisContext context) { public void invokeHead(Map<Integer, CellData<?>> headMap, AnalysisContext context) {
invokeHeadMap(ConverterUtils.convertToStringMap(headMap, context), context); invokeHeadMap(ConverterUtils.convertToStringMap(headMap, context), context);
} }

38
src/main/java/com/alibaba/excel/exception/ExcelDataConvertException.java

@ -4,11 +4,16 @@ import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty; import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.alibaba.excel.write.builder.ExcelWriterBuilder; import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import lombok.Getter;
import lombok.Setter;
/** /**
* Data convert exception * Data convert exception
* *
* @author Jiaju Zhuang * @author Jiaju Zhuang
*/ */
@Getter
@Setter
public class ExcelDataConvertException extends RuntimeException { public class ExcelDataConvertException extends RuntimeException {
/** /**
* NotNull. * NotNull.
@ -21,7 +26,7 @@ public class ExcelDataConvertException extends RuntimeException {
/** /**
* NotNull. * NotNull.
*/ */
private CellData cellData; private CellData<?> cellData;
/** /**
* Nullable.Only when the header is configured and when the class header is used is not null. * Nullable.Only when the header is configured and when the class header is used is not null.
* *
@ -47,35 +52,4 @@ public class ExcelDataConvertException extends RuntimeException {
this.excelContentProperty = excelContentProperty; this.excelContentProperty = excelContentProperty;
} }
public Integer getRowIndex() {
return rowIndex;
}
public void setRowIndex(Integer rowIndex) {
this.rowIndex = rowIndex;
}
public Integer getColumnIndex() {
return columnIndex;
}
public void setColumnIndex(Integer columnIndex) {
this.columnIndex = columnIndex;
}
public ExcelContentProperty getExcelContentProperty() {
return excelContentProperty;
}
public void setExcelContentProperty(ExcelContentProperty excelContentProperty) {
this.excelContentProperty = excelContentProperty;
}
public CellData getCellData() {
return cellData;
}
public void setCellData(CellData cellData) {
this.cellData = cellData;
}
} }

8
src/main/java/com/alibaba/excel/metadata/AbstractHolder.java

@ -34,7 +34,7 @@ public abstract class AbstractHolder implements ConfigurationHolder {
* <p> * <p>
* Write key: * Write key:
*/ */
private Map<String, Converter> converterMap; private Map<String, Converter<?>> converterMap;
public AbstractHolder(BasicParameter basicParameter, AbstractHolder prentAbstractHolder) { public AbstractHolder(BasicParameter basicParameter, AbstractHolder prentAbstractHolder) {
this.newInitialization = Boolean.TRUE; this.newInitialization = Boolean.TRUE;
@ -103,16 +103,16 @@ public abstract class AbstractHolder implements ConfigurationHolder {
this.globalConfiguration = globalConfiguration; this.globalConfiguration = globalConfiguration;
} }
public Map<String, Converter> getConverterMap() { public Map<String, Converter<?>> getConverterMap() {
return converterMap; return converterMap;
} }
public void setConverterMap(Map<String, Converter> converterMap) { public void setConverterMap(Map<String, Converter<?>> converterMap) {
this.converterMap = converterMap; this.converterMap = converterMap;
} }
@Override @Override
public Map<String, Converter> converterMap() { public Map<String, Converter<?>> converterMap() {
return getConverterMap(); return getConverterMap();
} }

142
src/main/java/com/alibaba/excel/metadata/CellData.java

@ -1,10 +1,14 @@
package com.alibaba.excel.metadata; package com.alibaba.excel.metadata;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.Date;
import com.alibaba.excel.enums.CellDataTypeEnum; import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.util.StringUtils; import com.alibaba.excel.util.StringUtils;
import lombok.Getter;
import lombok.Setter;
/** /**
* Excel internal cell data. * Excel internal cell data.
* *
@ -12,6 +16,8 @@ import com.alibaba.excel.util.StringUtils;
* *
* @author Jiaju Zhuang * @author Jiaju Zhuang
*/ */
@Getter
@Setter
public class CellData<T> extends AbstractCell { public class CellData<T> extends AbstractCell {
private CellDataTypeEnum type; private CellDataTypeEnum type;
/** /**
@ -30,11 +36,15 @@ public class CellData<T> extends AbstractCell {
private String formulaValue; private String formulaValue;
private byte[] imageValue; private byte[] imageValue;
/** /**
* The number formatting.Currently only supported when reading * Support only when writing.
*/
private Date dateValue;
/**
* The number formatting.
*/ */
private Integer dataFormat; private Short dataFormat;
/** /**
* The string of number formatting.Currently only supported when reading * The string of number formatting.
*/ */
private String dataFormatString; private String dataFormatString;
/** /**
@ -53,6 +63,8 @@ public class CellData<T> extends AbstractCell {
this.dataFormat = other.dataFormat; this.dataFormat = other.dataFormat;
this.dataFormatString = other.dataFormatString; this.dataFormatString = other.dataFormatString;
this.data = other.data; this.data = other.data;
setRowIndex(other.getRowIndex());
setColumnIndex(other.getColumnIndex());
} }
public CellData() {} public CellData() {}
@ -110,92 +122,22 @@ public class CellData<T> extends AbstractCell {
this.formula = Boolean.FALSE; this.formula = Boolean.FALSE;
} }
public CellData(CellDataTypeEnum type) { public CellData(Date dateValue) {
if (type == null) { if (dateValue == null) {
throw new IllegalArgumentException("Type can not be null"); throw new IllegalArgumentException("DateValue can not be null");
} }
this.type = type; this.type = CellDataTypeEnum.DATE;
this.dateValue = dateValue;
this.formula = Boolean.FALSE; this.formula = Boolean.FALSE;
} }
public CellDataTypeEnum getType() {
return type;
}
public void setType(CellDataTypeEnum type) { public CellData(CellDataTypeEnum type) {
if (type == null) {
throw new IllegalArgumentException("Type can not be null");
}
this.type = type; this.type = type;
} this.formula = Boolean.FALSE;
public BigDecimal getNumberValue() {
return numberValue;
}
public void setNumberValue(BigDecimal numberValue) {
this.numberValue = numberValue;
}
public String getStringValue() {
return stringValue;
}
public void setStringValue(String stringValue) {
this.stringValue = stringValue;
}
public Boolean getBooleanValue() {
return booleanValue;
}
public void setBooleanValue(Boolean booleanValue) {
this.booleanValue = booleanValue;
}
public Boolean getFormula() {
return formula;
}
public void setFormula(Boolean formula) {
this.formula = formula;
}
public String getFormulaValue() {
return formulaValue;
}
public void setFormulaValue(String formulaValue) {
this.formulaValue = formulaValue;
}
public byte[] getImageValue() {
return imageValue;
}
public void setImageValue(byte[] imageValue) {
this.imageValue = imageValue;
}
public Integer getDataFormat() {
return dataFormat;
}
public void setDataFormat(Integer dataFormat) {
this.dataFormat = dataFormat;
}
public String getDataFormatString() {
return dataFormatString;
}
public void setDataFormatString(String dataFormatString) {
this.dataFormatString = dataFormatString;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
} }
/** /**
@ -226,37 +168,37 @@ public class CellData<T> extends AbstractCell {
} }
} }
public static CellData newEmptyInstance() { public static CellData<?> newEmptyInstance() {
return newEmptyInstance(null, null); return newEmptyInstance(null, null);
} }
public static CellData newEmptyInstance(Integer rowIndex, Integer columnIndex) { public static CellData<?> newEmptyInstance(Integer rowIndex, Integer columnIndex) {
CellData cellData = new CellData(CellDataTypeEnum.EMPTY); CellData<?> cellData = new CellData<>(CellDataTypeEnum.EMPTY);
cellData.setRowIndex(rowIndex); cellData.setRowIndex(rowIndex);
cellData.setColumnIndex(columnIndex); cellData.setColumnIndex(columnIndex);
return cellData; return cellData;
} }
public static CellData newInstance(Boolean booleanValue) { public static CellData<?> newInstance(Boolean booleanValue) {
return newInstance(booleanValue, null, null); return newInstance(booleanValue, null, null);
} }
public static CellData newInstance(Boolean booleanValue, Integer rowIndex, Integer columnIndex) { public static CellData<?> newInstance(Boolean booleanValue, Integer rowIndex, Integer columnIndex) {
CellData cellData = new CellData(booleanValue); CellData<?> cellData = new CellData<>(booleanValue);
cellData.setRowIndex(rowIndex); cellData.setRowIndex(rowIndex);
cellData.setColumnIndex(columnIndex); cellData.setColumnIndex(columnIndex);
return cellData; return cellData;
} }
public static CellData newInstance(String stringValue, Integer rowIndex, Integer columnIndex) { public static CellData<?> newInstance(String stringValue, Integer rowIndex, Integer columnIndex) {
CellData cellData = new CellData(stringValue); CellData<?> cellData = new CellData<>(stringValue);
cellData.setRowIndex(rowIndex); cellData.setRowIndex(rowIndex);
cellData.setColumnIndex(columnIndex); cellData.setColumnIndex(columnIndex);
return cellData; return cellData;
} }
public static CellData newInstance(BigDecimal numberValue, Integer rowIndex, Integer columnIndex) { public static CellData<?> newInstance(BigDecimal numberValue, Integer rowIndex, Integer columnIndex) {
CellData cellData = new CellData(numberValue); CellData<?> cellData = new CellData<>(numberValue);
cellData.setRowIndex(rowIndex); cellData.setRowIndex(rowIndex);
cellData.setColumnIndex(columnIndex); cellData.setColumnIndex(columnIndex);
return cellData; return cellData;
@ -269,14 +211,28 @@ public class CellData<T> extends AbstractCell {
} }
switch (type) { switch (type) {
case NUMBER: case NUMBER:
if (numberValue == null) {
return StringUtils.EMPTY;
}
return numberValue.toString(); return numberValue.toString();
case BOOLEAN: case BOOLEAN:
if (booleanValue == null) {
return StringUtils.EMPTY;
}
return booleanValue.toString(); return booleanValue.toString();
case DIRECT_STRING: case DIRECT_STRING:
case STRING: case STRING:
case ERROR: case ERROR:
return stringValue; return stringValue;
case DATE:
if (dateValue == null) {
return StringUtils.EMPTY;
}
return dateValue.toString();
case IMAGE: case IMAGE:
if (imageValue == null) {
return StringUtils.EMPTY;
}
return "image[" + imageValue.length + "]"; return "image[" + imageValue.length + "]";
default: default:
return StringUtils.EMPTY; return StringUtils.EMPTY;

2
src/main/java/com/alibaba/excel/metadata/ConfigurationHolder.java

@ -32,5 +32,5 @@ public interface ConfigurationHolder extends Holder {
* *
* @return Converter * @return Converter
*/ */
Map<String, Converter> converterMap(); Map<String, Converter<?>> converterMap();
} }

10
src/main/java/com/alibaba/excel/metadata/format/DataFormatter.java

@ -170,7 +170,7 @@ public class DataFormatter {
this.decimalSymbols = DecimalFormatSymbols.getInstance(this.locale); this.decimalSymbols = DecimalFormatSymbols.getInstance(this.locale);
} }
private Format getFormat(Double data,Integer dataFormat, String dataFormatString) { private Format getFormat(Double data,Short dataFormat, String dataFormatString) {
// Might be better to separate out the n p and z formats, falling back to p when n and z are not set. // Might be better to separate out the n p and z formats, falling back to p when n and z are not set.
// That however would require other code to be re factored. // That however would require other code to be re factored.
@ -225,7 +225,7 @@ public class DataFormatter {
return format; return format;
} }
private Format createFormat(Integer dataFormat, String dataFormatString) { private Format createFormat(Short dataFormat, String dataFormatString) {
String formatStr = dataFormatString; String formatStr = dataFormatString;
Format format = checkSpecialConverter(formatStr); Format format = checkSpecialConverter(formatStr);
@ -607,7 +607,7 @@ public class DataFormatter {
* @param dataFormatString * @param dataFormatString
* @return Formatted value * @return Formatted value
*/ */
private String getFormattedDateString(Double data, Integer dataFormat, String dataFormatString) { private String getFormattedDateString(Double data, Short dataFormat, String dataFormatString) {
Format dateFormat = getFormat(data, dataFormat, dataFormatString); Format dateFormat = getFormat(data, dataFormat, dataFormatString);
if (dateFormat instanceof ExcelStyleDateFormatter) { if (dateFormat instanceof ExcelStyleDateFormatter) {
// Hint about the raw excel value // Hint about the raw excel value
@ -630,7 +630,7 @@ public class DataFormatter {
* @param dataFormatString * @param dataFormatString
* @return a formatted number string * @return a formatted number string
*/ */
private String getFormattedNumberString(Double data, Integer dataFormat, String dataFormatString) { private String getFormattedNumberString(Double data, Short dataFormat, String dataFormatString) {
Format numberFormat = getFormat(data, dataFormat, dataFormatString); Format numberFormat = getFormat(data, dataFormat, dataFormatString);
String formatted = numberFormat.format(data); String formatted = numberFormat.format(data);
return formatted.replaceFirst("E(\\d)", "E+$1"); // to match Excel's E-notation return formatted.replaceFirst("E(\\d)", "E+$1"); // to match Excel's E-notation
@ -644,7 +644,7 @@ public class DataFormatter {
* @param dataFormatString * @param dataFormatString
* @return * @return
*/ */
public String format(Double data, Integer dataFormat, String dataFormatString) { public String format(Double data, Short dataFormat, String dataFormatString) {
if (DateUtils.isADateFormat(dataFormat, dataFormatString)) { if (DateUtils.isADateFormat(dataFormat, dataFormatString)) {
return getFormattedDateString(data, dataFormat, dataFormatString); return getFormattedDateString(data, dataFormat, dataFormatString);
} }

2
src/main/java/com/alibaba/excel/metadata/property/ExcelHeadProperty.java

@ -8,6 +8,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.TreeMap; import java.util.TreeMap;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -21,7 +22,6 @@ import com.alibaba.excel.exception.ExcelCommonException;
import com.alibaba.excel.metadata.Head; import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.Holder; import com.alibaba.excel.metadata.Holder;
import com.alibaba.excel.util.ClassUtils; import com.alibaba.excel.util.ClassUtils;
import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.excel.util.StringUtils; import com.alibaba.excel.util.StringUtils;
import com.alibaba.excel.write.metadata.holder.AbstractWriteHolder; import com.alibaba.excel.write.metadata.holder.AbstractWriteHolder;

51
src/main/java/com/alibaba/excel/read/listener/ModelBuildEventListener.java

@ -14,9 +14,10 @@ import com.alibaba.excel.exception.ExcelDataConvertException;
import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head; import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.property.ExcelContentProperty; import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.alibaba.excel.read.metadata.holder.ReadHolder; import com.alibaba.excel.read.metadata.holder.ReadSheetHolder;
import com.alibaba.excel.read.metadata.property.ExcelReadHeadProperty; import com.alibaba.excel.read.metadata.property.ExcelReadHeadProperty;
import com.alibaba.excel.util.ConverterUtils; import com.alibaba.excel.util.ConverterUtils;
import com.alibaba.excel.util.FieldUtils;
import net.sf.cglib.beans.BeanMap; import net.sf.cglib.beans.BeanMap;
@ -25,28 +26,28 @@ import net.sf.cglib.beans.BeanMap;
* *
* @author jipengfei * @author jipengfei
*/ */
public class ModelBuildEventListener extends AbstractIgnoreExceptionReadListener<Map<Integer, CellData>> { public class ModelBuildEventListener extends AbstractIgnoreExceptionReadListener<Map<Integer, CellData<?>>> {
@Override @Override
public void invokeHead(Map<Integer, CellData> cellDataMap, AnalysisContext context) {} public void invokeHead(Map<Integer, CellData<?>> cellDataMap, AnalysisContext context) {}
@Override @Override
public void invoke(Map<Integer, CellData> cellDataMap, AnalysisContext context) { public void invoke(Map<Integer, CellData<?>> cellDataMap, AnalysisContext context) {
ReadHolder currentReadHolder = context.currentReadHolder(); ReadSheetHolder readSheetHolder = context.readSheetHolder();
if (HeadKindEnum.CLASS.equals(currentReadHolder.excelReadHeadProperty().getHeadKind())) { if (HeadKindEnum.CLASS.equals(readSheetHolder.excelReadHeadProperty().getHeadKind())) {
context.readRowHolder() context.readRowHolder()
.setCurrentRowAnalysisResult(buildUserModel(cellDataMap, currentReadHolder, context)); .setCurrentRowAnalysisResult(buildUserModel(cellDataMap, readSheetHolder, context));
return; return;
} }
context.readRowHolder().setCurrentRowAnalysisResult(buildStringList(cellDataMap, currentReadHolder, context)); context.readRowHolder().setCurrentRowAnalysisResult(buildStringList(cellDataMap, readSheetHolder, context));
} }
private Object buildStringList(Map<Integer, CellData> cellDataMap, ReadHolder currentReadHolder, private Object buildStringList(Map<Integer, CellData<?>> cellDataMap, ReadSheetHolder readSheetHolder,
AnalysisContext context) { AnalysisContext context) {
int index = 0; int index = 0;
if (context.readWorkbookHolder().getDefaultReturnMap()) { if (context.readWorkbookHolder().getDefaultReturnMap()) {
Map<Integer, String> map = new LinkedHashMap<Integer, String>(cellDataMap.size() * 4 / 3 + 1); Map<Integer, String> map = new LinkedHashMap<Integer, String>(cellDataMap.size() * 4 / 3 + 1);
for (Map.Entry<Integer, CellData> entry : cellDataMap.entrySet()) { for (Map.Entry<Integer, CellData<?>> entry : cellDataMap.entrySet()) {
Integer key = entry.getKey(); Integer key = entry.getKey();
CellData cellData = entry.getValue(); CellData cellData = entry.getValue();
while (index < key) { while (index < key) {
@ -59,10 +60,10 @@ public class ModelBuildEventListener extends AbstractIgnoreExceptionReadListener
continue; continue;
} }
map.put(key, map.put(key,
(String)ConverterUtils.convertToJavaObject(cellData, null, null, currentReadHolder.converterMap(), (String)ConverterUtils.convertToJavaObject(cellData, null, null, readSheetHolder.converterMap(),
currentReadHolder.globalConfiguration(), context.readRowHolder().getRowIndex(), key)); readSheetHolder, context.readRowHolder().getRowIndex(), key));
} }
int headSize = currentReadHolder.excelReadHeadProperty().getHeadMap().size(); int headSize = readSheetHolder.excelReadHeadProperty().getHeadMap().size();
while (index < headSize) { while (index < headSize) {
map.put(index, null); map.put(index, null);
index++; index++;
@ -70,10 +71,10 @@ public class ModelBuildEventListener extends AbstractIgnoreExceptionReadListener
return map; return map;
} else { } else {
// Compatible with the old code the old code returns a list // Compatible with the old code the old code returns a list
List<String> list = new ArrayList<String>(); List<String> list = new ArrayList<>();
for (Map.Entry<Integer, CellData> entry : cellDataMap.entrySet()) { for (Map.Entry<Integer, CellData<?>> entry : cellDataMap.entrySet()) {
Integer key = entry.getKey(); Integer key = entry.getKey();
CellData cellData = entry.getValue(); CellData<?> cellData = entry.getValue();
while (index < key) { while (index < key) {
list.add(null); list.add(null);
index++; index++;
@ -84,10 +85,10 @@ public class ModelBuildEventListener extends AbstractIgnoreExceptionReadListener
continue; continue;
} }
list.add( list.add(
(String)ConverterUtils.convertToJavaObject(cellData, null, null, currentReadHolder.converterMap(), (String)ConverterUtils.convertToJavaObject(cellData, null, null, readSheetHolder.converterMap(),
currentReadHolder.globalConfiguration(), context.readRowHolder().getRowIndex(), key)); readSheetHolder, context.readRowHolder().getRowIndex(), key));
} }
int headSize = currentReadHolder.excelReadHeadProperty().getHeadMap().size(); int headSize = readSheetHolder.excelReadHeadProperty().getHeadMap().size();
while (index < headSize) { while (index < headSize) {
list.add(null); list.add(null);
index++; index++;
@ -96,15 +97,15 @@ public class ModelBuildEventListener extends AbstractIgnoreExceptionReadListener
} }
} }
private Object buildUserModel(Map<Integer, CellData> cellDataMap, ReadHolder currentReadHolder, private Object buildUserModel(Map<Integer, CellData<?>> cellDataMap, ReadSheetHolder readSheetHolder,
AnalysisContext context) { AnalysisContext context) {
ExcelReadHeadProperty excelReadHeadProperty = currentReadHolder.excelReadHeadProperty(); ExcelReadHeadProperty excelReadHeadProperty = readSheetHolder.excelReadHeadProperty();
Object resultModel; Object resultModel;
try { try {
resultModel = excelReadHeadProperty.getHeadClazz().newInstance(); resultModel = excelReadHeadProperty.getHeadClazz().newInstance();
} catch (Exception e) { } catch (Exception e) {
throw new ExcelDataConvertException(context.readRowHolder().getRowIndex(), 0, throw new ExcelDataConvertException(context.readRowHolder().getRowIndex(), 0,
new CellData(CellDataTypeEnum.EMPTY), null, new CellData<>(CellDataTypeEnum.EMPTY), null,
"Can not instance class: " + excelReadHeadProperty.getHeadClazz().getName(), e); "Can not instance class: " + excelReadHeadProperty.getHeadClazz().getName(), e);
} }
Map<Integer, Head> headMap = excelReadHeadProperty.getHeadMap(); Map<Integer, Head> headMap = excelReadHeadProperty.getHeadMap();
@ -115,16 +116,16 @@ public class ModelBuildEventListener extends AbstractIgnoreExceptionReadListener
if (!cellDataMap.containsKey(index)) { if (!cellDataMap.containsKey(index)) {
continue; continue;
} }
CellData cellData = cellDataMap.get(index); CellData<?> cellData = cellDataMap.get(index);
if (cellData.getType() == CellDataTypeEnum.EMPTY) { if (cellData.getType() == CellDataTypeEnum.EMPTY) {
continue; continue;
} }
ExcelContentProperty excelContentProperty = contentPropertyMap.get(index); ExcelContentProperty excelContentProperty = contentPropertyMap.get(index);
Object value = ConverterUtils.convertToJavaObject(cellData, excelContentProperty.getField(), Object value = ConverterUtils.convertToJavaObject(cellData, excelContentProperty.getField(),
excelContentProperty, currentReadHolder.converterMap(), currentReadHolder.globalConfiguration(), excelContentProperty, readSheetHolder.converterMap(), readSheetHolder,
context.readRowHolder().getRowIndex(), index); context.readRowHolder().getRowIndex(), index);
if (value != null) { if (value != null) {
map.put(excelContentProperty.getField().getName(), value); map.put(FieldUtils.resolveCglibFieldName(excelContentProperty.getField()), value);
} }
} }
BeanMap.create(resultModel).putAll(map); BeanMap.create(resultModel).putAll(map);

2
src/main/java/com/alibaba/excel/read/listener/ReadListener.java

@ -29,7 +29,7 @@ public interface ReadListener<T> extends Listener {
* @param headMap * @param headMap
* @param context * @param context
*/ */
void invokeHead(Map<Integer, CellData> headMap, AnalysisContext context); void invokeHead(Map<Integer, CellData<?>> headMap, AnalysisContext context);
/** /**
* When analysis one row trigger invoke function. * When analysis one row trigger invoke function.

18
src/main/java/com/alibaba/excel/read/metadata/holder/AbstractReadHolder.java

@ -1,12 +1,8 @@
package com.alibaba.excel.read.metadata.holder; package com.alibaba.excel.read.metadata.holder;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.excel.converters.Converter; import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.converters.ConverterKeyBuild; import com.alibaba.excel.converters.ConverterKeyBuild;
import com.alibaba.excel.converters.DefaultConverterLoader; import com.alibaba.excel.converters.DefaultConverterLoader;
@ -17,6 +13,10 @@ import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.read.metadata.ReadBasicParameter; import com.alibaba.excel.read.metadata.ReadBasicParameter;
import com.alibaba.excel.read.metadata.ReadWorkbook; import com.alibaba.excel.read.metadata.ReadWorkbook;
import com.alibaba.excel.read.metadata.property.ExcelReadHeadProperty; import com.alibaba.excel.read.metadata.property.ExcelReadHeadProperty;
import com.alibaba.excel.util.ListUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** /**
* Read Holder * Read Holder
@ -24,8 +24,6 @@ import com.alibaba.excel.read.metadata.property.ExcelReadHeadProperty;
* @author Jiaju Zhuang * @author Jiaju Zhuang
*/ */
public abstract class AbstractReadHolder extends AbstractHolder implements ReadHolder { public abstract class AbstractReadHolder extends AbstractHolder implements ReadHolder {
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractReadHolder.class);
/** /**
* Count the number of added heads when read sheet. * Count the number of added heads when read sheet.
* *
@ -84,9 +82,9 @@ public abstract class AbstractReadHolder extends AbstractHolder implements ReadH
} }
if (parentAbstractReadHolder == null) { if (parentAbstractReadHolder == null) {
this.readListenerList = new ArrayList<ReadListener>(); this.readListenerList = ListUtils.newArrayList();
} else { } else {
this.readListenerList = new ArrayList<ReadListener>(parentAbstractReadHolder.getReadListenerList()); this.readListenerList = ListUtils.newArrayList(parentAbstractReadHolder.getReadListenerList());
} }
if (HolderEnum.WORKBOOK.equals(holderType())) { if (HolderEnum.WORKBOOK.equals(holderType())) {
Boolean useDefaultListener = ((ReadWorkbook)readBasicParameter).getUseDefaultListener(); Boolean useDefaultListener = ((ReadWorkbook)readBasicParameter).getUseDefaultListener();
@ -102,11 +100,11 @@ public abstract class AbstractReadHolder extends AbstractHolder implements ReadH
if (parentAbstractReadHolder == null) { if (parentAbstractReadHolder == null) {
setConverterMap(DefaultConverterLoader.loadDefaultReadConverter()); setConverterMap(DefaultConverterLoader.loadDefaultReadConverter());
} else { } else {
setConverterMap(new HashMap<String, Converter>(parentAbstractReadHolder.getConverterMap())); setConverterMap(new HashMap<>(parentAbstractReadHolder.getConverterMap()));
} }
if (readBasicParameter.getCustomConverterList() != null if (readBasicParameter.getCustomConverterList() != null
&& !readBasicParameter.getCustomConverterList().isEmpty()) { && !readBasicParameter.getCustomConverterList().isEmpty()) {
for (Converter converter : readBasicParameter.getCustomConverterList()) { for (Converter<?> converter : readBasicParameter.getCustomConverterList()) {
getConverterMap().put( getConverterMap().put(
ConverterKeyBuild.buildKey(converter.supportJavaTypeKey(), converter.supportExcelTypeKey()), ConverterKeyBuild.buildKey(converter.supportJavaTypeKey(), converter.supportExcelTypeKey()),
converter); converter);

6
src/main/java/com/alibaba/excel/read/metadata/holder/ReadSheetHolder.java

@ -51,7 +51,7 @@ public class ReadSheetHolder extends AbstractReadHolder {
/** /**
* Current CellData * Current CellData
*/ */
private CellData tempCellData; private CellData<?> tempCellData;
public ReadSheetHolder(ReadSheet readSheet, ReadWorkbookHolder readWorkbookHolder) { public ReadSheetHolder(ReadSheet readSheet, ReadWorkbookHolder readWorkbookHolder) {
super(readSheet, readWorkbookHolder, readWorkbookHolder.getReadWorkbook().getConvertAllFiled()); super(readSheet, readWorkbookHolder, readWorkbookHolder.getReadWorkbook().getConvertAllFiled());
@ -135,11 +135,11 @@ public class ReadSheetHolder extends AbstractReadHolder {
this.rowIndex = rowIndex; this.rowIndex = rowIndex;
} }
public CellData getTempCellData() { public CellData<?> getTempCellData() {
return tempCellData; return tempCellData;
} }
public void setTempCellData(CellData tempCellData) { public void setTempCellData(CellData<?> tempCellData) {
this.tempCellData = tempCellData; this.tempCellData = tempCellData;
} }

4
src/main/java/com/alibaba/excel/read/processor/DefaultAnalysisEventProcessor.java

@ -82,7 +82,7 @@ public class DefaultAnalysisEventProcessor implements AnalysisEventProcessor {
private void dealData(AnalysisContext analysisContext) { private void dealData(AnalysisContext analysisContext) {
ReadRowHolder readRowHolder = analysisContext.readRowHolder(); ReadRowHolder readRowHolder = analysisContext.readRowHolder();
Map<Integer, CellData> cellDataMap = (Map)readRowHolder.getCellMap(); Map<Integer, CellData<?>> cellDataMap = (Map)readRowHolder.getCellMap();
readRowHolder.setCurrentRowAnalysisResult(cellDataMap); readRowHolder.setCurrentRowAnalysisResult(cellDataMap);
int rowIndex = readRowHolder.getRowIndex(); int rowIndex = readRowHolder.getRowIndex();
int currentHeadRowNumber = analysisContext.readSheetHolder().getHeadRowNumber(); int currentHeadRowNumber = analysisContext.readSheetHolder().getHeadRowNumber();
@ -111,7 +111,7 @@ public class DefaultAnalysisEventProcessor implements AnalysisEventProcessor {
} }
} }
private void buildHead(AnalysisContext analysisContext, Map<Integer, CellData> cellDataMap) { private void buildHead(AnalysisContext analysisContext, Map<Integer, CellData<?>> cellDataMap) {
if (!HeadKindEnum.CLASS.equals(analysisContext.currentReadHolder().excelReadHeadProperty().getHeadKind())) { if (!HeadKindEnum.CLASS.equals(analysisContext.currentReadHolder().excelReadHeadProperty().getHeadKind())) {
return; return;
} }

75
src/main/java/com/alibaba/excel/util/BooleanUtils.java

@ -25,4 +25,79 @@ public class BooleanUtils {
} }
} }
// boolean Boolean methods
//-----------------------------------------------------------------------
/**
* <p>Checks if a {@code Boolean} value is {@code true},
* handling {@code null} by returning {@code false}.</p>
*
* <pre>
* BooleanUtils.isTrue(Boolean.TRUE) = true
* BooleanUtils.isTrue(Boolean.FALSE) = false
* BooleanUtils.isTrue(null) = false
* </pre>
*
* @param bool the boolean to check, null returns {@code false}
* @return {@code true} only if the input is non-null and true
* @since 2.1
*/
public static boolean isTrue(final Boolean bool) {
return Boolean.TRUE.equals(bool);
}
/**
* <p>Checks if a {@code Boolean} value is <i>not</i> {@code true},
* handling {@code null} by returning {@code true}.</p>
*
* <pre>
* BooleanUtils.isNotTrue(Boolean.TRUE) = false
* BooleanUtils.isNotTrue(Boolean.FALSE) = true
* BooleanUtils.isNotTrue(null) = true
* </pre>
*
* @param bool the boolean to check, null returns {@code true}
* @return {@code true} if the input is null or false
* @since 2.3
*/
public static boolean isNotTrue(final Boolean bool) {
return !isTrue(bool);
}
/**
* <p>Checks if a {@code Boolean} value is {@code false},
* handling {@code null} by returning {@code false}.</p>
*
* <pre>
* BooleanUtils.isFalse(Boolean.TRUE) = false
* BooleanUtils.isFalse(Boolean.FALSE) = true
* BooleanUtils.isFalse(null) = false
* </pre>
*
* @param bool the boolean to check, null returns {@code false}
* @return {@code true} only if the input is non-null and false
* @since 2.1
*/
public static boolean isFalse(final Boolean bool) {
return Boolean.FALSE.equals(bool);
}
/**
* <p>Checks if a {@code Boolean} value is <i>not</i> {@code false},
* handling {@code null} by returning {@code true}.</p>
*
* <pre>
* BooleanUtils.isNotFalse(Boolean.TRUE) = true
* BooleanUtils.isNotFalse(Boolean.FALSE) = false
* BooleanUtils.isNotFalse(null) = true
* </pre>
*
* @param bool the boolean to check, null returns {@code true}
* @return {@code true} if the input is null or true
* @since 2.3
*/
public static boolean isNotFalse(final Boolean bool) {
return !isFalse(bool);
}
} }

49
src/main/java/com/alibaba/excel/util/ClassUtils.java

@ -6,6 +6,8 @@ import java.lang.reflect.Modifier;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.TreeMap; import java.util.TreeMap;
@ -208,4 +210,51 @@ public class ClassUtils {
return ignoreMap; return ignoreMap;
} }
} }
/**
* <p>Gets a {@code List} of all interfaces implemented by the given
* class and its superclasses.</p>
*
* <p>The order is determined by looking through each interface in turn as
* declared in the source file and following its hierarchy up. Then each
* superclass is considered in the same way. Later duplicates are ignored,
* so the order is maintained.</p>
*
* @param cls the class to look up, may be {@code null}
* @return the {@code List} of interfaces in order,
* {@code null} if null input
*/
public static List<Class<?>> getAllInterfaces(final Class<?> cls) {
if (cls == null) {
return null;
}
final LinkedHashSet<Class<?>> interfacesFound = new LinkedHashSet<>();
getAllInterfaces(cls, interfacesFound);
return new ArrayList<>(interfacesFound);
}
/**
* Gets the interfaces for the specified class.
*
* @param cls the class to look up, may be {@code null}
* @param interfacesFound the {@code Set} of interfaces for the class
*/
private static void getAllInterfaces(Class<?> cls, final HashSet<Class<?>> interfacesFound) {
while (cls != null) {
final Class<?>[] interfaces = cls.getInterfaces();
for (final Class<?> i : interfaces) {
if (interfacesFound.add(i)) {
getAllInterfaces(i, interfacesFound);
}
}
cls = cls.getSuperclass();
}
}
} }

22
src/main/java/com/alibaba/excel/util/CollectionUtils.java

@ -1,22 +0,0 @@
package com.alibaba.excel.util;
import java.util.Collection;
import java.util.Map;
/**
* Collection utils
*
* @author jipengfei
*/
public class CollectionUtils {
private CollectionUtils() {}
public static boolean isEmpty(Collection<?> collection) {
return (collection == null || collection.isEmpty());
}
public static boolean isEmpty(Map<?, ?> map) {
return (map == null || map.isEmpty());
}
}

49
src/main/java/com/alibaba/excel/util/ConverterUtils.java

@ -3,7 +3,6 @@ package com.alibaba.excel.util;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType; import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.context.AnalysisContext;
@ -12,9 +11,9 @@ import com.alibaba.excel.converters.ConverterKeyBuild;
import com.alibaba.excel.enums.CellDataTypeEnum; import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.exception.ExcelDataConvertException; import com.alibaba.excel.exception.ExcelDataConvertException;
import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.property.ExcelContentProperty; import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.alibaba.excel.read.metadata.holder.ReadHolder; import com.alibaba.excel.read.metadata.holder.ReadHolder;
import com.alibaba.excel.read.metadata.holder.ReadSheetHolder;
/** /**
* Converting objects * Converting objects
@ -32,13 +31,13 @@ public class ConverterUtils {
* @param context * @param context
* @return * @return
*/ */
public static Map<Integer, String> convertToStringMap(Map<Integer, CellData> cellDataMap, AnalysisContext context) { public static Map<Integer, String> convertToStringMap(Map<Integer, CellData<?>> cellDataMap, AnalysisContext context) {
Map<Integer, String> stringMap = new HashMap<Integer, String>(cellDataMap.size() * 4 / 3 + 1); Map<Integer, String> stringMap = MapUtils.newHashMapWithExpectedSize(cellDataMap.size());
ReadHolder currentReadHolder = context.currentReadHolder(); ReadSheetHolder readSheetHolder = context.readSheetHolder();
int index = 0; int index = 0;
for (Map.Entry<Integer, CellData> entry : cellDataMap.entrySet()) { for (Map.Entry<Integer, CellData<?>> entry : cellDataMap.entrySet()) {
Integer key = entry.getKey(); Integer key = entry.getKey();
CellData cellData = entry.getValue(); CellData<?> cellData = entry.getValue();
while (index < key) { while (index < key) {
stringMap.put(index, null); stringMap.put(index, null);
index++; index++;
@ -48,15 +47,15 @@ public class ConverterUtils {
stringMap.put(key, null); stringMap.put(key, null);
continue; continue;
} }
Converter converter = Converter<?> converter =
currentReadHolder.converterMap().get(ConverterKeyBuild.buildKey(String.class, cellData.getType())); readSheetHolder.converterMap().get(ConverterKeyBuild.buildKey(String.class, cellData.getType()));
if (converter == null) { if (converter == null) {
throw new ExcelDataConvertException(context.readRowHolder().getRowIndex(), key, cellData, null, throw new ExcelDataConvertException(context.readRowHolder().getRowIndex(), key, cellData, null,
"Converter not found, convert " + cellData.getType() + " to String"); "Converter not found, convert " + cellData.getType() + " to String");
} }
try { try {
stringMap.put(key, stringMap.put(key,
(String)(converter.convertToJavaData(cellData, null, currentReadHolder.globalConfiguration()))); (String)(converter.convertToJavaData(cellData, null, readSheetHolder)));
} catch (Exception e) { } catch (Exception e) {
throw new ExcelDataConvertException(context.readRowHolder().getRowIndex(), key, cellData, null, throw new ExcelDataConvertException(context.readRowHolder().getRowIndex(), key, cellData, null,
"Convert data " + cellData + " to String error ", e); "Convert data " + cellData + " to String error ", e);
@ -72,15 +71,15 @@ public class ConverterUtils {
* @param field * @param field
* @param contentProperty * @param contentProperty
* @param converterMap * @param converterMap
* @param globalConfiguration * @param readSheetHolder
* @param rowIndex * @param rowIndex
* @param columnIndex * @param columnIndex
* @return * @return
*/ */
public static Object convertToJavaObject(CellData cellData, Field field, ExcelContentProperty contentProperty, public static Object convertToJavaObject(CellData<?> cellData, Field field, ExcelContentProperty contentProperty,
Map<String, Converter> converterMap, GlobalConfiguration globalConfiguration, Integer rowIndex, Map<String, Converter<?>> converterMap, ReadSheetHolder readSheetHolder, Integer rowIndex,
Integer columnIndex) { Integer columnIndex) {
Class clazz; Class<?> clazz;
if (field == null) { if (field == null) {
clazz = String.class; clazz = String.class;
} else { } else {
@ -88,37 +87,37 @@ public class ConverterUtils {
} }
if (clazz == CellData.class) { if (clazz == CellData.class) {
Type type = field.getGenericType(); Type type = field.getGenericType();
Class classGeneric; Class<?> classGeneric;
if (type instanceof ParameterizedType) { if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType)type; ParameterizedType parameterizedType = (ParameterizedType)type;
classGeneric = (Class)parameterizedType.getActualTypeArguments()[0]; classGeneric = (Class<?>)parameterizedType.getActualTypeArguments()[0];
} else { } else {
classGeneric = String.class; classGeneric = String.class;
} }
CellData cellDataReturn = new CellData(cellData); CellData<Object> cellDataReturn = new CellData<Object>(cellData);
cellDataReturn.setData(doConvertToJavaObject(cellData, classGeneric, contentProperty, converterMap, cellDataReturn.setData(doConvertToJavaObject(cellData, classGeneric, contentProperty, converterMap,
globalConfiguration, rowIndex, columnIndex)); readSheetHolder, rowIndex, columnIndex));
return cellDataReturn; return cellDataReturn;
} }
return doConvertToJavaObject(cellData, clazz, contentProperty, converterMap, globalConfiguration, rowIndex, return doConvertToJavaObject(cellData, clazz, contentProperty, converterMap, readSheetHolder, rowIndex,
columnIndex); columnIndex);
} }
/** /**
*
* @param cellData * @param cellData
* @param clazz * @param clazz
* @param contentProperty * @param contentProperty
* @param converterMap * @param converterMap
* @param globalConfiguration * @param readSheetHolder
* @param rowIndex * @param rowIndex
* @param columnIndex * @param columnIndex
* @return * @return
*/ */
private static Object doConvertToJavaObject(CellData cellData, Class clazz, ExcelContentProperty contentProperty, private static Object doConvertToJavaObject(CellData<?> cellData, Class<?> clazz,
Map<String, Converter> converterMap, GlobalConfiguration globalConfiguration, Integer rowIndex, ExcelContentProperty contentProperty,
Map<String, Converter<?>> converterMap, ReadSheetHolder readSheetHolder, Integer rowIndex,
Integer columnIndex) { Integer columnIndex) {
Converter converter = null; Converter<?> converter = null;
if (contentProperty != null) { if (contentProperty != null) {
converter = contentProperty.getConverter(); converter = contentProperty.getConverter();
} }
@ -130,7 +129,7 @@ public class ConverterUtils {
"Converter not found, convert " + cellData.getType() + " to " + clazz.getName()); "Converter not found, convert " + cellData.getType() + " to " + clazz.getName());
} }
try { try {
return converter.convertToJavaData(cellData, contentProperty, globalConfiguration); return converter.convertToJavaData(cellData, contentProperty, readSheetHolder);
} catch (Exception e) { } catch (Exception e) {
throw new ExcelDataConvertException(rowIndex, columnIndex, cellData, contentProperty, throw new ExcelDataConvertException(rowIndex, columnIndex, cellData, contentProperty,
"Convert data " + cellData + " to " + clazz + " error ", e); "Convert data " + cellData + " to " + clazz + " error ", e);

32
src/main/java/com/alibaba/excel/util/DateUtils.java

@ -17,16 +17,16 @@ public class DateUtils {
/** /**
* Is a cache of dates * Is a cache of dates
*/ */
private static final ThreadLocal<Map<Integer, Boolean>> DATE_THREAD_LOCAL = private static final ThreadLocal<Map<Short, Boolean>> DATE_THREAD_LOCAL =
new ThreadLocal<Map<Integer, Boolean>>(); new ThreadLocal<>();
/** /**
* Is a cache of dates * Is a cache of dates
*/ */
private static final ThreadLocal<Map<String, SimpleDateFormat>> DATE_FORMAT_THREAD_LOCAL = private static final ThreadLocal<Map<String, SimpleDateFormat>> DATE_FORMAT_THREAD_LOCAL =
new ThreadLocal<Map<String, SimpleDateFormat>>(); new ThreadLocal<>();
/** /**
* The following patterns are used in {@link #isADateFormat(Integer, String)} * The following patterns are used in {@link #isADateFormat(Short, String)}
*/ */
private static final Pattern date_ptrn1 = Pattern.compile("^\\[\\$\\-.*?\\]"); private static final Pattern date_ptrn1 = Pattern.compile("^\\[\\$\\-.*?\\]");
private static final Pattern date_ptrn2 = Pattern.compile("^\\[[a-zA-Z]+\\]"); private static final Pattern date_ptrn2 = Pattern.compile("^\\[[a-zA-Z]+\\]");
@ -43,11 +43,15 @@ public class DateUtils {
public static final String DATE_FORMAT_10 = "yyyy-MM-dd"; public static final String DATE_FORMAT_10 = "yyyy-MM-dd";
public static final String DATE_FORMAT_14 = "yyyyMMddHHmmss"; public static final String DATE_FORMAT_14 = "yyyyMMddHHmmss";
public static final String DATE_FORMAT_16 = "yyyy-MM-dd HH:mm";
public static final String DATE_FORMAT_16_FORWARD_SLASH = "yyyy/MM/dd HH:mm";
public static final String DATE_FORMAT_17 = "yyyyMMdd HH:mm:ss"; public static final String DATE_FORMAT_17 = "yyyyMMdd HH:mm:ss";
public static final String DATE_FORMAT_19 = "yyyy-MM-dd HH:mm:ss"; public static final String DATE_FORMAT_19 = "yyyy-MM-dd HH:mm:ss";
public static final String DATE_FORMAT_19_FORWARD_SLASH = "yyyy/MM/dd HH:mm:ss"; public static final String DATE_FORMAT_19_FORWARD_SLASH = "yyyy/MM/dd HH:mm:ss";
private static final String MINUS = "-"; private static final String MINUS = "-";
public static String defaultDateFormat = DATE_FORMAT_19;
private DateUtils() {} private DateUtils() {}
/** /**
@ -91,6 +95,12 @@ public class DateUtils {
} else { } else {
return DATE_FORMAT_19_FORWARD_SLASH; return DATE_FORMAT_19_FORWARD_SLASH;
} }
case 16:
if (dateString.contains(MINUS)) {
return DATE_FORMAT_16;
} else {
return DATE_FORMAT_16_FORWARD_SLASH;
}
case 17: case 17:
return DATE_FORMAT_17; return DATE_FORMAT_17;
case 14: case 14:
@ -126,7 +136,7 @@ public class DateUtils {
return ""; return "";
} }
if (StringUtils.isEmpty(dateFormat)) { if (StringUtils.isEmpty(dateFormat)) {
dateFormat = DATE_FORMAT_19; dateFormat = defaultDateFormat;
} }
return getCacheDateFormat(dateFormat).format(date); return getCacheDateFormat(dateFormat).format(date);
} }
@ -154,13 +164,13 @@ public class DateUtils {
* @param formatString * @param formatString
* @return * @return
*/ */
public static boolean isADateFormat(Integer formatIndex, String formatString) { public static boolean isADateFormat(Short formatIndex, String formatString) {
if (formatIndex == null) { if (formatIndex == null) {
return false; return false;
} }
Map<Integer, Boolean> isDateCache = DATE_THREAD_LOCAL.get(); Map<Short, Boolean> isDateCache = DATE_THREAD_LOCAL.get();
if (isDateCache == null) { if (isDateCache == null) {
isDateCache = new HashMap<Integer, Boolean>(); isDateCache = MapUtils.newHashMap();
DATE_THREAD_LOCAL.set(isDateCache); DATE_THREAD_LOCAL.set(isDateCache);
} else { } else {
Boolean isDateCachedData = isDateCache.get(formatIndex); Boolean isDateCachedData = isDateCache.get(formatIndex);
@ -180,7 +190,7 @@ public class DateUtils {
* @param formatString * @param formatString
* @return * @return
*/ */
public static boolean isADateFormatUncached(Integer formatIndex, String formatString) { public static boolean isADateFormatUncached(Short formatIndex, String formatString) {
// First up, is this an internal date format? // First up, is this an internal date format?
if (isInternalDateFormat(formatIndex)) { if (isInternalDateFormat(formatIndex)) {
return true; return true;
@ -256,9 +266,9 @@ public class DateUtils {
/** /**
* Given a format ID this will check whether the format represents an internal excel date format or not. * Given a format ID this will check whether the format represents an internal excel date format or not.
* *
* @see #isADateFormat(Integer, String) * @see #isADateFormat(Short, String)
*/ */
public static boolean isInternalDateFormat(int format) { public static boolean isInternalDateFormat(short format) {
switch (format) { switch (format) {
// Internal Date Formats as described on page 427 in // Internal Date Formats as described on page 427 in
// Microsoft Excel Dev's Kit... // Microsoft Excel Dev's Kit...

145
src/main/java/com/alibaba/excel/util/FieldUtils.java

@ -0,0 +1,145 @@
package com.alibaba.excel.util;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
/**
* Field utils
*
* @author Jiaju Zhuang
**/
public class FieldUtils {
private static final int START_RESOLVE_FIELD_LENGTH = 2;
/**
* Parsing the name matching cglib
* <ul>
* <ul>null -> null</ul>
* <ul>string1 -> string1</ul>
* <ul>String2 -> string2</ul>
* <ul>sTring3 -> STring3</ul>
* <ul>STring4 -> STring4</ul>
* <ul>STRING5 -> STRING5</ul>
* <ul>STRing6 -> STRing6</ul>
* </ul>
*
* @param field field
* @return field name.
*/
public static String resolveCglibFieldName(Field field) {
if (field == null) {
return null;
}
String fieldName = field.getName();
if (StringUtils.isBlank(fieldName) || fieldName.length() < START_RESOLVE_FIELD_LENGTH) {
return fieldName;
}
char firstChar = fieldName.charAt(0);
char secondChar = fieldName.charAt(1);
if (Character.isUpperCase(firstChar) == Character.isUpperCase(secondChar)) {
return fieldName;
}
if (Character.isUpperCase(firstChar)) {
return buildFieldName(Character.toLowerCase(firstChar), fieldName);
}
return buildFieldName(Character.toUpperCase(firstChar), fieldName);
}
private static String buildFieldName(char firstChar, String fieldName) {
return firstChar + fieldName.substring(1);
}
/**
* Gets an accessible {@link Field} by name respecting scope. Superclasses/interfaces will be considered.
*
* @param cls
* the {@link Class} to reflect, must not be {@code null}
* @param fieldName
* the field name to obtain
* @return the Field object
* @throws IllegalArgumentException
* if the class is {@code null}, or the field name is blank or empty
*/
public static Field getField(final Class<?> cls, final String fieldName) {
final Field field = getField(cls, fieldName, false);
MemberUtils.setAccessibleWorkaround(field);
return field;
}
/**
* Gets an accessible {@link Field} by name, breaking scope if requested. Superclasses/interfaces will be
* considered.
*
* @param cls
* the {@link Class} to reflect, must not be {@code null}
* @param fieldName
* the field name to obtain
* @param forceAccess
* whether to break scope restrictions using the
* {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} method. {@code false} will only
* match {@code public} fields.
* @return the Field object
* @throws NullPointerException if the class is {@code null}
* @throws IllegalArgumentException if the field name is blank or empty or is matched at multiple places
* in the inheritance hierarchy
*/
public static Field getField(final Class<?> cls, final String fieldName, final boolean forceAccess) {
Validate.isTrue(cls != null, "The class must not be null");
Validate.isTrue(StringUtils.isNotBlank(fieldName), "The field name must not be blank/empty");
// FIXME is this workaround still needed? lang requires Java 6
// Sun Java 1.3 has a bugged implementation of getField hence we write the
// code ourselves
// getField() will return the Field object with the declaring class
// set correctly to the class that declares the field. Thus requesting the
// field on a subclass will return the field from the superclass.
//
// priority order for lookup:
// searchclass private/protected/package/public
// superclass protected/package/public
// private/different package blocks access to further superclasses
// implementedinterface public
// check up the superclass hierarchy
for (Class<?> acls = cls; acls != null; acls = acls.getSuperclass()) {
try {
final Field field = acls.getDeclaredField(fieldName);
// getDeclaredField checks for non-public scopes as well
// and it returns accurate results
if (!Modifier.isPublic(field.getModifiers())) {
if (forceAccess) {
field.setAccessible(true);
} else {
continue;
}
}
return field;
} catch (final NoSuchFieldException ex) { // NOPMD
// ignore
}
}
// check the public interface case. This must be manually searched for
// incase there is a public supersuperclass field hidden by a private/package
// superclass field.
Field match = null;
for (final Class<?> class1 : ClassUtils.getAllInterfaces(cls)) {
try {
final Field test = class1.getField(fieldName);
Validate.isTrue(match == null, "Reference to field %s is ambiguous relative to %s"
+ "; a matching field exists on two or more implemented interfaces.", fieldName, cls);
match = test;
} catch (final NoSuchFieldException ex) { // NOPMD
// ignore
}
}
return match;
}
}

24
src/main/java/com/alibaba/excel/util/FileUtils.java

@ -9,12 +9,12 @@ import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.UUID; import java.util.UUID;
import org.apache.poi.util.DefaultTempFileCreationStrategy;
import org.apache.poi.util.TempFile;
import com.alibaba.excel.exception.ExcelAnalysisException; import com.alibaba.excel.exception.ExcelAnalysisException;
import com.alibaba.excel.exception.ExcelCommonException; import com.alibaba.excel.exception.ExcelCommonException;
import org.apache.poi.util.DefaultTempFileCreationStrategy;
import org.apache.poi.util.TempFile;
/** /**
* *
* @author jipengfei * @author jipengfei
@ -100,10 +100,21 @@ public class FileUtils {
/** /**
* Write inputStream to file * Write inputStream to file
* *
* @param file * @param file file
* @param inputStream * @param inputStream inputStream
*/ */
public static void writeToFile(File file, InputStream inputStream) { public static void writeToFile(File file, InputStream inputStream) {
writeToFile(file, inputStream, true);
}
/**
* Write inputStream to file
*
* @param file file
* @param inputStream inputStream
* @param closeInputStream closeInputStream
*/
public static void writeToFile(File file, InputStream inputStream, boolean closeInputStream) {
OutputStream outputStream = null; OutputStream outputStream = null;
try { try {
outputStream = new FileOutputStream(file); outputStream = new FileOutputStream(file);
@ -122,7 +133,7 @@ public class FileUtils {
throw new ExcelAnalysisException("Can not close 'outputStream'!", e); throw new ExcelAnalysisException("Can not close 'outputStream'!", e);
} }
} }
if (inputStream != null) { if (inputStream != null && closeInputStream) {
try { try {
inputStream.close(); inputStream.close();
} catch (IOException e) { } catch (IOException e) {
@ -132,6 +143,7 @@ public class FileUtils {
} }
} }
public static void createPoiFilesDirectory() { public static void createPoiFilesDirectory() {
File poiFilesPathFile = new File(poiFilesPath); File poiFilesPathFile = new File(poiFilesPath);
createDirectory(poiFilesPathFile); createDirectory(poiFilesPathFile);

39
src/main/java/com/alibaba/excel/util/IntUtils.java

@ -0,0 +1,39 @@
package com.alibaba.excel.util;
import java.util.ArrayList;
import java.util.List;
/**
* Int utils
*
* @author Jiaju Zhuang
**/
public class IntUtils {
private IntUtils() {}
/**
* The largest power of two that can be represented as an {@code int}.
*
* @since 10.0
*/
public static final int MAX_POWER_OF_TWO = 1 << (Integer.SIZE - 2);
/**
* Returns the {@code int} nearest in value to {@code value}.
*
* @param value any {@code long} value
* @return the same value cast to {@code int} if it is in the range of the {@code int} type,
* {@link Integer#MAX_VALUE} if it is too large, or {@link Integer#MIN_VALUE} if it is too
* small
*/
public static int saturatedCast(long value) {
if (value > Integer.MAX_VALUE) {
return Integer.MAX_VALUE;
}
if (value < Integer.MIN_VALUE) {
return Integer.MIN_VALUE;
}
return (int) value;
}
}

121
src/main/java/com/alibaba/excel/util/ListUtils.java

@ -0,0 +1,121 @@
package com.alibaba.excel.util;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import lombok.NonNull;
import org.apache.commons.compress.utils.Iterators;
/**
* List utils
*
* @author Jiaju Zhuang
**/
public class ListUtils {
private ListUtils() {}
/**
* Creates a <i>mutable</i>, empty {@code ArrayList} instance (for Java 6 and earlier).
*
* <p><b>Note for Java 7 and later:</b> this method is now unnecessary and should be treated as
* deprecated. Instead, use the {@code ArrayList} {@linkplain ArrayList#ArrayList() constructor}
* directly, taking advantage of the new <a href="http://goo.gl/iz2Wi">"diamond" syntax</a>.
*/
public static <E> ArrayList<E> newArrayList() {
return new ArrayList<>();
}
/**
* Creates a <i>mutable</i> {@code ArrayList} instance containing the given elements; a very thin
* shortcut for creating an empty list and then calling {@link Iterators#addAll}.
*
*/
public static <E> ArrayList<E> newArrayList(Iterator<? extends E> elements) {
ArrayList<E> list = newArrayList();
Iterators.addAll(list, elements);
return list;
}
/**
* Creates a <i>mutable</i> {@code ArrayList} instance containing the given elements;
*
*
* <p><b>Note for Java 7 and later:</b> if {@code elements} is a {@link Collection}, you don't
* need this method. Use the {@code ArrayList} {@linkplain ArrayList#ArrayList(Collection)
* constructor} directly, taking advantage of the new <a href="http://goo.gl/iz2Wi">"diamond"
* syntax</a>.
*/
public static <E> ArrayList<E> newArrayList(Iterable<? extends E> elements) {
checkNotNull(elements); // for GWT
// Let ArrayList's sizing logic work, if possible
return (elements instanceof Collection)
? new ArrayList<>((Collection<? extends E>)elements)
: newArrayList(elements.iterator());
}
/**
* Creates an {@code ArrayList} instance backed by an array with the specified initial size;
* simply delegates to {@link ArrayList#ArrayList(int)}.
*
* <p><b>Note for Java 7 and later:</b> this method is now unnecessary and should be treated as
* deprecated. Instead, use {@code new }{@link ArrayList#ArrayList(int) ArrayList}{@code <>(int)}
* directly, taking advantage of the new <a href="http://goo.gl/iz2Wi">"diamond" syntax</a>.
* (Unlike here, there is no risk of overload ambiguity, since the {@code ArrayList} constructors
* very wisely did not accept varargs.)
*
* @param initialArraySize the exact size of the initial backing array for the returned array list
* ({@code ArrayList} documentation calls this value the "capacity")
* @return a new, empty {@code ArrayList} which is guaranteed not to resize itself unless its size
* reaches {@code initialArraySize + 1}
* @throws IllegalArgumentException if {@code initialArraySize} is negative
*/
public static <E> ArrayList<E> newArrayListWithCapacity(int initialArraySize) {
checkNonnegative(initialArraySize, "initialArraySize");
return new ArrayList<>(initialArraySize);
}
/**
* Creates an {@code ArrayList} instance to hold {@code estimatedSize} elements, <i>plus</i> an
* unspecified amount of padding; you almost certainly mean to call {@link
* #newArrayListWithCapacity} (see that method for further advice on usage).
*
* <p><b>Note:</b> This method will soon be deprecated. Even in the rare case that you do want
* some amount of padding, it's best if you choose your desired amount explicitly.
*
* @param estimatedSize an estimate of the eventual {@link List#size()} of the new list
* @return a new, empty {@code ArrayList}, sized appropriately to hold the estimated number of
* elements
* @throws IllegalArgumentException if {@code estimatedSize} is negative
*/
public static <E> ArrayList<E> newArrayListWithExpectedSize(int estimatedSize) {
return new ArrayList<>(computeArrayListCapacity(estimatedSize));
}
static int computeArrayListCapacity(int arraySize) {
checkNonnegative(arraySize, "arraySize");
return IntUtils.saturatedCast(5L + arraySize + (arraySize / 10));
}
static int checkNonnegative(int value, String name) {
if (value < 0) {
throw new IllegalArgumentException(name + " cannot be negative but was: " + value);
}
return value;
}
/**
* Ensures that an object reference passed as a parameter to the calling method is not null.
*
* @param reference an object reference
* @return the non-null reference that was validated
* @throws NullPointerException if {@code reference} is null
*/
public static <T extends @NonNull Object> T checkNotNull(T reference) {
if (reference == null) {
throw new NullPointerException();
}
return reference;
}
}

63
src/main/java/com/alibaba/excel/util/MapUtils.java

@ -0,0 +1,63 @@
package com.alibaba.excel.util;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Map utils
*
* @author Jiaju Zhuang
**/
public class MapUtils {
private MapUtils() {}
/**
* Creates a <i>mutable</i>, empty {@code HashMap} instance.
*
* <p><b>Note:</b> if mutability is not required, use {@link ImmutableMap#of()} instead.
*
* <p><b>Note:</b> if {@code K} is an {@code enum} type, use {@link #newEnumMap} instead.
*
* <p><b>Note for Java 7 and later:</b> this method is now unnecessary and should be treated as
* deprecated. Instead, use the {@code HashMap} constructor directly, taking advantage of the new
* <a href="http://goo.gl/iz2Wi">"diamond" syntax</a>.
*
* @return a new, empty {@code HashMap}
*/
public static <K, V> HashMap<K, V> newHashMap() {
return new HashMap<>();
}
/**
* Creates a {@code HashMap} instance, with a high enough "initial capacity" that it <i>should</i>
* hold {@code expectedSize} elements without growth. This behavior cannot be broadly guaranteed,
* but it is observed to be true for OpenJDK 1.7. It also can't be guaranteed that the method
* isn't inadvertently <i>oversizing</i> the returned map.
*
* @param expectedSize the number of entries you expect to add to the returned map
* @return a new, empty {@code HashMap} with enough capacity to hold {@code expectedSize} entries
* without resizing
* @throws IllegalArgumentException if {@code expectedSize} is negative
*/
public static <K, V> HashMap<K, V> newHashMapWithExpectedSize(int expectedSize) {
return new HashMap<>(capacity(expectedSize));
}
/**
* Returns a capacity that is sufficient to keep the map from being resized as long as it grows no
* larger than expectedSize and the load factor is its default (0.75).
*/
static int capacity(int expectedSize) {
if (expectedSize < 3) {
return expectedSize + 1;
}
if (expectedSize < IntUtils.MAX_POWER_OF_TWO) {
// This is the calculation used in JDK8 to resize when a putAll
// happens; it seems to be the most conservative calculation we
// can make. 0.75 is the default load factor.
return (int) ((float) expectedSize / 0.75F + 1.0F);
}
return Integer.MAX_VALUE;
}
}

54
src/main/java/com/alibaba/excel/util/MemberUtils.java

@ -0,0 +1,54 @@
package com.alibaba.excel.util;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Member;
import java.lang.reflect.Modifier;
/**
* Member utils.
*
* @author Jiaju Zhuang
*/
public class MemberUtils {
private static final int ACCESS_TEST = Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE;
/**
* XXX Default access superclass workaround.
*
* When a {@code public} class has a default access superclass with {@code public} members,
* these members are accessible. Calling them from compiled code works fine.
* Unfortunately, on some JVMs, using reflection to invoke these members
* seems to (wrongly) prevent access even when the modifier is {@code public}.
* Calling {@code setAccessible(true)} solves the problem but will only work from
* sufficiently privileged code. Better workarounds would be gratefully
* accepted.
* @param o the AccessibleObject to set as accessible
* @return a boolean indicating whether the accessibility of the object was set to true.
*/
static boolean setAccessibleWorkaround(final AccessibleObject o) {
if (o == null || o.isAccessible()) {
return false;
}
final Member m = (Member) o;
if (!o.isAccessible() && Modifier.isPublic(m.getModifiers()) && isPackageAccess(m.getDeclaringClass().getModifiers())) {
try {
o.setAccessible(true);
return true;
} catch (final SecurityException e) { // NOPMD
// ignore in favor of subsequent IllegalAccessException
}
}
return false;
}
/**
* Returns whether a given set of modifiers implies package access.
* @param modifiers to test
* @return {@code true} unless {@code package}/{@code protected}/{@code private} modifier detected
*/
static boolean isPackageAccess(final int modifiers) {
return (modifiers & ACCESS_TEST) == 0;
}
}

2
src/main/java/com/alibaba/excel/util/NumberDataFormatterUtils.java

@ -24,7 +24,7 @@ public class NumberDataFormatterUtils {
* @param globalConfiguration * @param globalConfiguration
* @return * @return
*/ */
public static String format(Double data, Integer dataFormat, String dataFormatString, public static String format(Double data, Short dataFormat, String dataFormatString,
GlobalConfiguration globalConfiguration) { GlobalConfiguration globalConfiguration) {
DataFormatter dataFormatter = DATA_FORMATTER_THREAD_LOCAL.get(); DataFormatter dataFormatter = DATA_FORMATTER_THREAD_LOCAL.get();
if (dataFormatter == null) { if (dataFormatter == null) {

24
src/main/java/com/alibaba/excel/util/NumberUtils.java

@ -7,6 +7,7 @@ import java.text.ParseException;
import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty; import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.alibaba.excel.write.metadata.holder.WriteHolder;
/** /**
* Number utils * Number utils
@ -46,8 +47,27 @@ public class NumberUtils {
* @param contentProperty * @param contentProperty
* @return * @return
*/ */
public static CellData formatToCellData(Number num, ExcelContentProperty contentProperty) { public static CellData<?> formatToCellDataString(Number num, ExcelContentProperty contentProperty) {
return new CellData(format(num, contentProperty)); return new CellData<>(format(num, contentProperty));
}
/**
* format
*
* @param num
* @param contentProperty
* @param currentWriteHolder
* @return
*/
public static CellData<?> formatToCellData(Number num, ExcelContentProperty contentProperty,
WriteHolder currentWriteHolder) {
CellData<?> cellData = new CellData<>(BigDecimal.valueOf(num.doubleValue()));
if (contentProperty != null && contentProperty.getNumberFormatProperty() != null
&& StringUtils.isNotBlank(contentProperty.getNumberFormatProperty().getFormat())) {
WorkBookUtil.fillDataFormat(cellData, currentWriteHolder,
contentProperty.getNumberFormatProperty().getFormat());
}
return cellData;
} }
/** /**

87
src/main/java/com/alibaba/excel/util/StringUtils.java

@ -6,11 +6,92 @@ package com.alibaba.excel.util;
* @author jipengfei * @author jipengfei
*/ */
public class StringUtils { public class StringUtils {
private StringUtils() {}
/**
* A String for a space character.
*/
public static final String SPACE = " ";
/**
* The empty String {@code ""}.
*/
public static final String EMPTY = ""; public static final String EMPTY = "";
private StringUtils() {} /**
* <p>Checks if a CharSequence is empty ("") or null.</p>
*
* <pre>
* StringUtils.isEmpty(null) = true
* StringUtils.isEmpty("") = true
* StringUtils.isEmpty(" ") = false
* StringUtils.isEmpty("bob") = false
* StringUtils.isEmpty(" bob ") = false
* </pre>
*
* <p>NOTE: This method changed in Lang version 2.0.
* It no longer trims the CharSequence.
* That functionality is available in isBlank().</p>
*
* @param cs the CharSequence to check, may be null
* @return {@code true} if the CharSequence is empty or null
*/
public static boolean isEmpty(final CharSequence cs) {
return cs == null || cs.length() == 0;
}
public static boolean isEmpty(Object str) { /**
return (str == null || EMPTY.equals(str)); * <p>Checks if a CharSequence is empty (""), null or whitespace only.</p>
*
* <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
*
* <pre>
* StringUtils.isBlank(null) = true
* StringUtils.isBlank("") = true
* StringUtils.isBlank(" ") = true
* StringUtils.isBlank("bob") = false
* StringUtils.isBlank(" bob ") = false
* </pre>
*
* @param cs the CharSequence to check, may be null
* @return {@code true} if the CharSequence is null, empty or whitespace only
*/
public static boolean isBlank(final CharSequence cs) {
int strLen;
if (cs == null || (strLen = cs.length()) == 0) {
return true;
}
for (int i = 0; i < strLen; i++) {
if (!Character.isWhitespace(cs.charAt(i))) {
return false;
}
}
return true;
} }
/**
* <p>Checks if a CharSequence is not empty (""), not null and not whitespace only.</p>
*
* <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
*
* <pre>
* StringUtils.isNotBlank(null) = false
* StringUtils.isNotBlank("") = false
* StringUtils.isNotBlank(" ") = false
* StringUtils.isNotBlank("bob") = true
* StringUtils.isNotBlank(" bob ") = true
* </pre>
*
* @param cs the CharSequence to check, may be null
* @return {@code true} if the CharSequence is
* not empty and not null and not whitespace only
* @since 2.0
* @since 3.0 Changed signature from isNotBlank(String) to isNotBlank(CharSequence)
*/
public static boolean isNotBlank(final CharSequence cs) {
return !isBlank(cs);
}
} }

20
src/main/java/com/alibaba/excel/util/StyleUtil.java

@ -1,5 +1,8 @@
package com.alibaba.excel.util; package com.alibaba.excel.util;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import org.apache.poi.ss.usermodel.BorderStyle; import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.FillPatternType; import org.apache.poi.ss.usermodel.FillPatternType;
@ -8,15 +11,17 @@ import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors; import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.VerticalAlignment; import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import com.alibaba.excel.write.metadata.style.WriteCellStyle; import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
/** /**
* @author jipengfei * @author jipengfei
*/ */
public class StyleUtil { public class StyleUtil {
public static short XSSF_DEFAULT_STYLE = 0;
public static short HSSF_DEFAULT_STYLE = 15;
private StyleUtil() {} private StyleUtil() {}
/** /**
@ -183,4 +188,13 @@ public class StyleUtil {
} }
} }
public static boolean isDefaultStyle(CellStyle cellStyle) {
if (cellStyle == null) {
return true;
}
if (cellStyle instanceof XSSFCellStyle) {
return cellStyle.getIndex() == XSSF_DEFAULT_STYLE;
}
return cellStyle.getIndex() == HSSF_DEFAULT_STYLE;
}
} }

151
src/main/java/com/alibaba/excel/util/Validate.java

@ -0,0 +1,151 @@
package com.alibaba.excel.util;
import java.util.Objects;
/**
* Validate
*
* @author Jiaju Zhuang
*/
public class Validate {
private static final String DEFAULT_IS_TRUE_EX_MESSAGE = "The validated expression is false";
private static final String DEFAULT_IS_NULL_EX_MESSAGE = "The validated object is null";
/**
* <p>Validate that the argument condition is {@code true}; otherwise
* throwing an exception with the specified message. This method is useful when
* validating according to an arbitrary boolean expression, such as validating a
* primitive number or using your own custom validation expression.</p>
*
* <pre>Validate.isTrue(i &gt; 0.0, "The value must be greater than zero: &#37;d", i);</pre>
*
* <p>For performance reasons, the long value is passed as a separate parameter and
* appended to the exception message only in the case of an error.</p>
*
* @param expression the boolean expression to check
* @param message the {@link String#format(String, Object...)} exception message if invalid, not null
* @param value the value to append to the message when invalid
* @throws IllegalArgumentException if expression is {@code false}
* @see #isTrue(boolean)
* @see #isTrue(boolean, String, double)
* @see #isTrue(boolean, String, Object...)
*/
public static void isTrue(final boolean expression, final String message, final long value) {
if (!expression) {
throw new IllegalArgumentException(String.format(message, Long.valueOf(value)));
}
}
/**
* <p>Validate that the argument condition is {@code true}; otherwise
* throwing an exception with the specified message. This method is useful when
* validating according to an arbitrary boolean expression, such as validating a
* primitive number or using your own custom validation expression.</p>
*
* <pre>Validate.isTrue(d &gt; 0.0, "The value must be greater than zero: &#37;s", d);</pre>
*
* <p>For performance reasons, the double value is passed as a separate parameter and
* appended to the exception message only in the case of an error.</p>
*
* @param expression the boolean expression to check
* @param message the {@link String#format(String, Object...)} exception message if invalid, not null
* @param value the value to append to the message when invalid
* @throws IllegalArgumentException if expression is {@code false}
* @see #isTrue(boolean)
* @see #isTrue(boolean, String, long)
* @see #isTrue(boolean, String, Object...)
*/
public static void isTrue(final boolean expression, final String message, final double value) {
if (!expression) {
throw new IllegalArgumentException(String.format(message, Double.valueOf(value)));
}
}
/**
* <p>Validate that the argument condition is {@code true}; otherwise
* throwing an exception with the specified message. This method is useful when
* validating according to an arbitrary boolean expression, such as validating a
* primitive number or using your own custom validation expression.</p>
*
* <pre>
* Validate.isTrue(i &gt;= min &amp;&amp; i &lt;= max, "The value must be between &#37;d and &#37;d", min, max);
* Validate.isTrue(myObject.isOk(), "The object is not okay");</pre>
*
* @param expression the boolean expression to check
* @param message the {@link String#format(String, Object...)} exception message if invalid, not null
* @param values the optional values for the formatted exception message, null array not recommended
* @throws IllegalArgumentException if expression is {@code false}
* @see #isTrue(boolean)
* @see #isTrue(boolean, String, long)
* @see #isTrue(boolean, String, double)
*/
public static void isTrue(final boolean expression, final String message, final Object... values) {
if (!expression) {
throw new IllegalArgumentException(String.format(message, values));
}
}
/**
* <p>Validate that the argument condition is {@code true}; otherwise
* throwing an exception. This method is useful when validating according
* to an arbitrary boolean expression, such as validating a
* primitive number or using your own custom validation expression.</p>
*
* <pre>
* Validate.isTrue(i &gt; 0);
* Validate.isTrue(myObject.isOk());</pre>
*
* <p>The message of the exception is &quot;The validated expression is
* false&quot;.</p>
*
* @param expression the boolean expression to check
* @throws IllegalArgumentException if expression is {@code false}
* @see #isTrue(boolean, String, long)
* @see #isTrue(boolean, String, double)
* @see #isTrue(boolean, String, Object...)
*/
public static void isTrue(final boolean expression) {
if (!expression) {
throw new IllegalArgumentException(DEFAULT_IS_TRUE_EX_MESSAGE);
}
}
/**
* <p>Validate that the specified argument is not {@code null};
* otherwise throwing an exception.
*
* <pre>Validate.notNull(myObject, "The object must not be null");</pre>
*
* <p>The message of the exception is &quot;The validated object is
* null&quot;.</p>
*
* @param <T> the object type
* @param object the object to check
* @return the validated object (never {@code null} for method chaining)
* @throws NullPointerException if the object is {@code null}
* @see #notNull(Object, String, Object...)
*/
public static <T> T notNull(final T object) {
return notNull(object, DEFAULT_IS_NULL_EX_MESSAGE);
}
/**
* <p>Validate that the specified argument is not {@code null};
* otherwise throwing an exception with the specified message.
*
* <pre>Validate.notNull(myObject, "The object must not be null");</pre>
*
* @param <T> the object type
* @param object the object to check
* @param message the {@link String#format(String, Object...)} exception message if invalid, not null
* @param values the optional values for the formatted exception message
* @return the validated object (never {@code null} for method chaining)
* @throws NullPointerException if the object is {@code null}
* @see #notNull(Object)
*/
public static <T> T notNull(final T object, final String message, final Object... values) {
return Objects.requireNonNull(object, () -> String.format(message, values));
}
}

25
src/main/java/com/alibaba/excel/util/WorkBookUtil.java

@ -2,6 +2,13 @@ package com.alibaba.excel.util;
import java.io.IOException; import java.io.IOException;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.metadata.holder.WriteHolder;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey; import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.poifs.filesystem.POIFSFileSystem;
@ -13,16 +20,12 @@ import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.streaming.SXSSFWorkbook; import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
/** /**
*
* @author jipengfei * @author jipengfei
*/ */
public class WorkBookUtil { public class WorkBookUtil {
private static final int ROW_ACCESS_WINDOW_SIZE = 500; public static final int ROW_ACCESS_WINDOW_SIZE = 500;
private WorkBookUtil() {} private WorkBookUtil() {}
@ -91,4 +94,16 @@ public class WorkBookUtil {
cell.setCellValue(cellValue); cell.setCellValue(cellValue);
return cell; return cell;
} }
public static void fillDataFormat(CellData<?> cellData, WriteHolder currentWriteHolder, String format) {
WriteWorkbookHolder writeWorkbookHolder;
if (currentWriteHolder instanceof WriteSheetHolder) {
writeWorkbookHolder = ((WriteSheetHolder)currentWriteHolder).getParentWriteWorkbookHolder();
} else {
writeWorkbookHolder = ((WriteTableHolder)currentWriteHolder).getParentWriteSheetHolder()
.getParentWriteWorkbookHolder();
}
cellData.setDataFormat(writeWorkbookHolder.getDataFormat(format));
cellData.setDataFormatString(format);
}
} }

38
src/main/java/com/alibaba/excel/util/WriteHandlerUtils.java

@ -4,9 +4,6 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import com.alibaba.excel.context.WriteContext; import com.alibaba.excel.context.WriteContext;
import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head; import com.alibaba.excel.metadata.Head;
@ -16,6 +13,9 @@ import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.handler.WorkbookWriteHandler; import com.alibaba.excel.write.handler.WorkbookWriteHandler;
import com.alibaba.excel.write.handler.WriteHandler; import com.alibaba.excel.write.handler.WriteHandler;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
/** /**
* Write handler utils * Write handler utils
* *
@ -25,7 +25,6 @@ public class WriteHandlerUtils {
private WriteHandlerUtils() {} private WriteHandlerUtils() {}
public static void beforeWorkbookCreate(WriteContext writeContext) { public static void beforeWorkbookCreate(WriteContext writeContext) {
beforeWorkbookCreate(writeContext, false); beforeWorkbookCreate(writeContext, false);
} }
@ -37,7 +36,7 @@ public class WriteHandlerUtils {
} }
for (WriteHandler writeHandler : handlerList) { for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof WorkbookWriteHandler) { if (writeHandler instanceof WorkbookWriteHandler) {
((WorkbookWriteHandler) writeHandler).beforeWorkbookCreate(); ((WorkbookWriteHandler)writeHandler).beforeWorkbookCreate();
} }
} }
} }
@ -53,7 +52,7 @@ public class WriteHandlerUtils {
} }
for (WriteHandler writeHandler : handlerList) { for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof WorkbookWriteHandler) { if (writeHandler instanceof WorkbookWriteHandler) {
((WorkbookWriteHandler) writeHandler).afterWorkbookCreate(writeContext.writeWorkbookHolder()); ((WorkbookWriteHandler)writeHandler).afterWorkbookCreate(writeContext.writeWorkbookHolder());
} }
} }
} }
@ -66,7 +65,7 @@ public class WriteHandlerUtils {
} }
for (WriteHandler writeHandler : handlerList) { for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof WorkbookWriteHandler) { if (writeHandler instanceof WorkbookWriteHandler) {
((WorkbookWriteHandler) writeHandler).afterWorkbookDispose(writeContext.writeWorkbookHolder()); ((WorkbookWriteHandler)writeHandler).afterWorkbookDispose(writeContext.writeWorkbookHolder());
} }
} }
} }
@ -82,13 +81,12 @@ public class WriteHandlerUtils {
} }
for (WriteHandler writeHandler : handlerList) { for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof SheetWriteHandler) { if (writeHandler instanceof SheetWriteHandler) {
((SheetWriteHandler) writeHandler).beforeSheetCreate(writeContext.writeWorkbookHolder(), ((SheetWriteHandler)writeHandler).beforeSheetCreate(writeContext.writeWorkbookHolder(),
writeContext.writeSheetHolder()); writeContext.writeSheetHolder());
} }
} }
} }
public static void afterSheetCreate(WriteContext writeContext) { public static void afterSheetCreate(WriteContext writeContext) {
afterSheetCreate(writeContext, false); afterSheetCreate(writeContext, false);
} }
@ -100,7 +98,7 @@ public class WriteHandlerUtils {
} }
for (WriteHandler writeHandler : handlerList) { for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof SheetWriteHandler) { if (writeHandler instanceof SheetWriteHandler) {
((SheetWriteHandler) writeHandler).afterSheetCreate(writeContext.writeWorkbookHolder(), ((SheetWriteHandler)writeHandler).afterSheetCreate(writeContext.writeWorkbookHolder(),
writeContext.writeSheetHolder()); writeContext.writeSheetHolder());
} }
} }
@ -119,7 +117,7 @@ public class WriteHandlerUtils {
} }
for (WriteHandler writeHandler : handlerList) { for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof CellWriteHandler) { if (writeHandler instanceof CellWriteHandler) {
((CellWriteHandler) writeHandler).beforeCellCreate(writeContext.writeSheetHolder(), ((CellWriteHandler)writeHandler).beforeCellCreate(writeContext.writeSheetHolder(),
writeContext.writeTableHolder(), row, head, columnIndex, relativeRowIndex, isHead); writeContext.writeTableHolder(), row, head, columnIndex, relativeRowIndex, isHead);
} }
} }
@ -134,7 +132,7 @@ public class WriteHandlerUtils {
} }
for (WriteHandler writeHandler : handlerList) { for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof CellWriteHandler) { if (writeHandler instanceof CellWriteHandler) {
((CellWriteHandler) writeHandler).afterCellCreate(writeContext.writeSheetHolder(), ((CellWriteHandler)writeHandler).afterCellCreate(writeContext.writeSheetHolder(),
writeContext.writeTableHolder(), cell, head, relativeRowIndex, isHead); writeContext.writeTableHolder(), cell, head, relativeRowIndex, isHead);
} }
} }
@ -149,7 +147,7 @@ public class WriteHandlerUtils {
} }
for (WriteHandler writeHandler : handlerList) { for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof CellWriteHandler) { if (writeHandler instanceof CellWriteHandler) {
((CellWriteHandler) writeHandler).afterCellDataConverted(writeContext.writeSheetHolder(), ((CellWriteHandler)writeHandler).afterCellDataConverted(writeContext.writeSheetHolder(),
writeContext.writeTableHolder(), cellData, cell, head, relativeRowIndex, isHead); writeContext.writeTableHolder(), cellData, cell, head, relativeRowIndex, isHead);
} }
} }
@ -157,14 +155,14 @@ public class WriteHandlerUtils {
public static void afterCellDispose(WriteContext writeContext, CellData cellData, Cell cell, Head head, public static void afterCellDispose(WriteContext writeContext, CellData cellData, Cell cell, Head head,
Integer relativeRowIndex, Boolean isHead) { Integer relativeRowIndex, Boolean isHead) {
List<CellData> cellDataList = new ArrayList<CellData>(); List<CellData<?>> cellDataList = new ArrayList<>();
if (cell != null) { if (cellData != null) {
cellDataList.add(cellData); cellDataList.add(cellData);
} }
afterCellDispose(writeContext, cellDataList, cell, head, relativeRowIndex, isHead); afterCellDispose(writeContext, cellDataList, cell, head, relativeRowIndex, isHead);
} }
public static void afterCellDispose(WriteContext writeContext, List<CellData> cellDataList, Cell cell, Head head, public static void afterCellDispose(WriteContext writeContext, List<CellData<?>> cellDataList, Cell cell, Head head,
Integer relativeRowIndex, Boolean isHead) { Integer relativeRowIndex, Boolean isHead) {
List<WriteHandler> handlerList = List<WriteHandler> handlerList =
writeContext.currentWriteHolder().writeHandlerMap().get(CellWriteHandler.class); writeContext.currentWriteHolder().writeHandlerMap().get(CellWriteHandler.class);
@ -173,7 +171,7 @@ public class WriteHandlerUtils {
} }
for (WriteHandler writeHandler : handlerList) { for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof CellWriteHandler) { if (writeHandler instanceof CellWriteHandler) {
((CellWriteHandler) writeHandler).afterCellDispose(writeContext.writeSheetHolder(), ((CellWriteHandler)writeHandler).afterCellDispose(writeContext.writeSheetHolder(),
writeContext.writeTableHolder(), cellDataList, cell, head, relativeRowIndex, isHead); writeContext.writeTableHolder(), cellDataList, cell, head, relativeRowIndex, isHead);
} }
} }
@ -190,7 +188,7 @@ public class WriteHandlerUtils {
} }
for (WriteHandler writeHandler : handlerList) { for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof RowWriteHandler) { if (writeHandler instanceof RowWriteHandler) {
((RowWriteHandler) writeHandler).beforeRowCreate(writeContext.writeSheetHolder(), ((RowWriteHandler)writeHandler).beforeRowCreate(writeContext.writeSheetHolder(),
writeContext.writeTableHolder(), rowIndex, relativeRowIndex, isHead); writeContext.writeTableHolder(), rowIndex, relativeRowIndex, isHead);
} }
} }
@ -203,7 +201,7 @@ public class WriteHandlerUtils {
} }
for (WriteHandler writeHandler : handlerList) { for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof RowWriteHandler) { if (writeHandler instanceof RowWriteHandler) {
((RowWriteHandler) writeHandler).afterRowCreate(writeContext.writeSheetHolder(), ((RowWriteHandler)writeHandler).afterRowCreate(writeContext.writeSheetHolder(),
writeContext.writeTableHolder(), row, relativeRowIndex, isHead); writeContext.writeTableHolder(), row, relativeRowIndex, isHead);
} }
} }
@ -217,7 +215,7 @@ public class WriteHandlerUtils {
} }
for (WriteHandler writeHandler : handlerList) { for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof RowWriteHandler) { if (writeHandler instanceof RowWriteHandler) {
((RowWriteHandler) writeHandler).afterRowDispose(writeContext.writeSheetHolder(), ((RowWriteHandler)writeHandler).afterRowDispose(writeContext.writeSheetHolder(),
writeContext.writeTableHolder(), row, relativeRowIndex, isHead); writeContext.writeTableHolder(), row, relativeRowIndex, isHead);
} }
} }

7
src/main/java/com/alibaba/excel/write/ExcelBuilder.java

@ -1,5 +1,6 @@
package com.alibaba.excel.write; package com.alibaba.excel.write;
import java.util.Collection;
import java.util.List; import java.util.List;
import com.alibaba.excel.context.WriteContext; import com.alibaba.excel.context.WriteContext;
@ -20,10 +21,10 @@ public interface ExcelBuilder {
* java basic type or java model extend BaseModel * java basic type or java model extend BaseModel
* @param writeSheet * @param writeSheet
* Write the sheet * Write the sheet
* @deprecated please use{@link ExcelBuilder#addContent(List, WriteSheet, WriteTable)} * @deprecated please use{@link ExcelBuilder#addContent(Collection, WriteSheet, WriteTable)}
*/ */
@Deprecated @Deprecated
void addContent(List data, WriteSheet writeSheet); void addContent(Collection<?> data, WriteSheet writeSheet);
/** /**
* WorkBook increase value * WorkBook increase value
@ -35,7 +36,7 @@ public interface ExcelBuilder {
* @param writeTable * @param writeTable
* Write the table * Write the table
*/ */
void addContent(List data, WriteSheet writeSheet, WriteTable writeTable); void addContent(Collection<?> data, WriteSheet writeSheet, WriteTable writeTable);
/** /**
* WorkBook fill value * WorkBook fill value

10
src/main/java/com/alibaba/excel/write/ExcelBuilderImpl.java

@ -1,13 +1,19 @@
package com.alibaba.excel.write; package com.alibaba.excel.write;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.List; import java.util.List;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import com.alibaba.excel.context.WriteContext; import com.alibaba.excel.context.WriteContext;
import com.alibaba.excel.context.WriteContextImpl; import com.alibaba.excel.context.WriteContextImpl;
import com.alibaba.excel.enums.WriteTypeEnum; import com.alibaba.excel.enums.WriteTypeEnum;
import com.alibaba.excel.exception.ExcelGenerateException; import com.alibaba.excel.exception.ExcelGenerateException;
import com.alibaba.excel.util.FieldUtils;
import com.alibaba.excel.util.FileUtils; import com.alibaba.excel.util.FileUtils;
import com.alibaba.excel.write.executor.ExcelWriteAddExecutor; import com.alibaba.excel.write.executor.ExcelWriteAddExecutor;
import com.alibaba.excel.write.executor.ExcelWriteFillExecutor; import com.alibaba.excel.write.executor.ExcelWriteFillExecutor;
@ -43,12 +49,12 @@ public class ExcelBuilderImpl implements ExcelBuilder {
} }
@Override @Override
public void addContent(List data, WriteSheet writeSheet) { public void addContent(Collection<?> data, WriteSheet writeSheet) {
addContent(data, writeSheet, null); addContent(data, writeSheet, null);
} }
@Override @Override
public void addContent(List data, WriteSheet writeSheet, WriteTable writeTable) { public void addContent(Collection<?> data, WriteSheet writeSheet, WriteTable writeTable) {
try { try {
context.currentSheet(writeSheet, WriteTypeEnum.ADD); context.currentSheet(writeSheet, WriteTypeEnum.ADD);
context.currentTable(writeTable); context.currentTable(writeTable);

4
src/main/java/com/alibaba/excel/write/builder/ExcelWriterSheetBuilder.java

@ -1,6 +1,6 @@
package com.alibaba.excel.write.builder; package com.alibaba.excel.write.builder;
import java.util.List; import java.util.Collection;
import com.alibaba.excel.ExcelWriter; import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.exception.ExcelGenerateException; import com.alibaba.excel.exception.ExcelGenerateException;
@ -54,7 +54,7 @@ public class ExcelWriterSheetBuilder extends AbstractExcelWriterParameterBuilder
return writeSheet; return writeSheet;
} }
public void doWrite(List data) { public void doWrite(Collection<?> data) {
if (excelWriter == null) { if (excelWriter == null) {
throw new ExcelGenerateException("Must use 'EasyExcelFactory.write().sheet()' to call this method"); throw new ExcelGenerateException("Must use 'EasyExcelFactory.write().sheet()' to call this method");
} }

4
src/main/java/com/alibaba/excel/write/builder/ExcelWriterTableBuilder.java

@ -1,6 +1,6 @@
package com.alibaba.excel.write.builder; package com.alibaba.excel.write.builder;
import java.util.List; import java.util.Collection;
import com.alibaba.excel.ExcelWriter; import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.exception.ExcelGenerateException; import com.alibaba.excel.exception.ExcelGenerateException;
@ -47,7 +47,7 @@ public class ExcelWriterTableBuilder extends AbstractExcelWriterParameterBuilder
return writeTable; return writeTable;
} }
public void doWrite(List data) { public void doWrite(Collection<?> data) {
if (excelWriter == null) { if (excelWriter == null) {
throw new ExcelGenerateException("Must use 'EasyExcelFactory.write().sheet().table()' to call this method"); throw new ExcelGenerateException("Must use 'EasyExcelFactory.write().sheet().table()' to call this method");
} }

59
src/main/java/com/alibaba/excel/write/executor/AbstractExcelWriteExecutor.java

@ -1,12 +1,5 @@
package com.alibaba.excel.write.executor; package com.alibaba.excel.write.executor;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.ss.usermodel.Drawing;
import org.apache.poi.ss.usermodel.Sheet;
import com.alibaba.excel.context.WriteContext; import com.alibaba.excel.context.WriteContext;
import com.alibaba.excel.converters.Converter; import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.converters.ConverterKeyBuild; import com.alibaba.excel.converters.ConverterKeyBuild;
@ -18,6 +11,13 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.alibaba.excel.util.WriteHandlerUtils; import com.alibaba.excel.util.WriteHandlerUtils;
import com.alibaba.excel.write.metadata.holder.WriteHolder; import com.alibaba.excel.write.metadata.holder.WriteHolder;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.ss.usermodel.Drawing;
import org.apache.poi.ss.usermodel.Sheet;
/** /**
* Excel write Executor * Excel write Executor
* *
@ -30,12 +30,13 @@ public abstract class AbstractExcelWriteExecutor implements ExcelWriteExecutor {
this.writeContext = writeContext; this.writeContext = writeContext;
} }
protected CellData converterAndSet(WriteHolder currentWriteHolder, Class clazz, Cell cell, Object value, protected CellData<?> converterAndSet(WriteHolder currentWriteHolder, Class<?> clazz, CellDataTypeEnum targetType,
Cell cell, Object value,
ExcelContentProperty excelContentProperty, Head head, Integer relativeRowIndex) { ExcelContentProperty excelContentProperty, Head head, Integer relativeRowIndex) {
if (value instanceof String && currentWriteHolder.globalConfiguration().getAutoTrim()) { if (value instanceof String && currentWriteHolder.globalConfiguration().getAutoTrim()) {
value = ((String)value).trim(); value = ((String)value).trim();
} }
CellData cellData = convert(currentWriteHolder, clazz, cell, value, excelContentProperty); CellData<?> cellData = convert(currentWriteHolder, clazz, targetType, cell, value, excelContentProperty);
if (cellData.getFormula() != null && cellData.getFormula()) { if (cellData.getFormula() != null && cellData.getFormula()) {
cell.setCellFormula(cellData.getFormulaValue()); cell.setCellFormula(cellData.getFormulaValue());
} }
@ -53,6 +54,9 @@ public abstract class AbstractExcelWriteExecutor implements ExcelWriteExecutor {
case NUMBER: case NUMBER:
cell.setCellValue(cellData.getNumberValue().doubleValue()); cell.setCellValue(cellData.getNumberValue().doubleValue());
return cellData; return cellData;
case DATE:
cell.setCellValue(cellData.getDateValue());
return cellData;
case IMAGE: case IMAGE:
setImageValue(cellData, cell); setImageValue(cellData, cell);
return cellData; return cellData;
@ -61,15 +65,16 @@ public abstract class AbstractExcelWriteExecutor implements ExcelWriteExecutor {
default: default:
throw new ExcelDataConvertException(cell.getRow().getRowNum(), cell.getColumnIndex(), cellData, throw new ExcelDataConvertException(cell.getRow().getRowNum(), cell.getColumnIndex(), cellData,
excelContentProperty, "Not supported data:" + value + " return type:" + cell.getCellType() excelContentProperty, "Not supported data:" + value + " return type:" + cell.getCellType()
+ "at row:" + cell.getRow().getRowNum()); + "at row:" + cell.getRow().getRowNum());
} }
} }
protected CellData convert(WriteHolder currentWriteHolder, Class clazz, Cell cell, Object value, protected CellData<?> convert(WriteHolder currentWriteHolder, Class<?> clazz, CellDataTypeEnum targetType,
ExcelContentProperty excelContentProperty) { Cell cell,
Object value, ExcelContentProperty excelContentProperty) {
// This means that the user has defined the data. // This means that the user has defined the data.
if (value instanceof CellData) { if (value instanceof CellData) {
CellData cellDataValue = (CellData)value; CellData<?> cellDataValue = (CellData<?>)value;
if (cellDataValue.getType() != null) { if (cellDataValue.getType() != null) {
return cellDataValue; return cellDataValue;
} else { } else {
@ -78,8 +83,8 @@ public abstract class AbstractExcelWriteExecutor implements ExcelWriteExecutor {
return cellDataValue; return cellDataValue;
} }
} }
CellData cellDataReturn = doConvert(currentWriteHolder, cellDataValue.getData().getClass(), cell, CellData<?> cellDataReturn = doConvert(currentWriteHolder, cellDataValue.getData().getClass(), targetType,
cellDataValue.getData(), excelContentProperty); cell, cellDataValue.getData(), excelContentProperty);
// The formula information is subject to user input // The formula information is subject to user input
if (cellDataValue.getFormula() != null) { if (cellDataValue.getFormula() != null) {
cellDataReturn.setFormula(cellDataValue.getFormula()); cellDataReturn.setFormula(cellDataValue.getFormula());
@ -87,44 +92,40 @@ public abstract class AbstractExcelWriteExecutor implements ExcelWriteExecutor {
} }
return cellDataReturn; return cellDataReturn;
} }
return doConvert(currentWriteHolder, clazz, cell, value, excelContentProperty); return doConvert(currentWriteHolder, clazz, targetType, cell, value, excelContentProperty);
} }
private CellData doConvert(WriteHolder currentWriteHolder, Class clazz, Cell cell, Object value, private CellData<?> doConvert(WriteHolder currentWriteHolder, Class<?> clazz, CellDataTypeEnum targetType,
ExcelContentProperty excelContentProperty) { Cell cell, Object value, ExcelContentProperty excelContentProperty) {
Converter converter = null; Converter converter = null;
if (excelContentProperty != null) { if (excelContentProperty != null) {
converter = excelContentProperty.getConverter(); converter = excelContentProperty.getConverter();
} }
if (converter == null) { if (converter == null) {
if (value == null || clazz == null) { converter = currentWriteHolder.converterMap().get(ConverterKeyBuild.buildKey(clazz, targetType));
return new CellData(CellDataTypeEnum.EMPTY);
}
converter = currentWriteHolder.converterMap().get(ConverterKeyBuild.buildKey(clazz));
} }
if (converter == null) { if (converter == null) {
throw new ExcelDataConvertException(cell.getRow().getRowNum(), cell.getColumnIndex(), throw new ExcelDataConvertException(cell.getRow().getRowNum(), cell.getColumnIndex(),
new CellData(CellDataTypeEnum.EMPTY), excelContentProperty, new CellData<>(CellDataTypeEnum.EMPTY), excelContentProperty,
"Can not find 'Converter' support class " + clazz.getSimpleName() + "."); "Can not find 'Converter' support class " + clazz.getSimpleName() + ".");
} }
CellData cellData; CellData<?> cellData;
try { try {
cellData = cellData = converter.convertToExcelData(value, excelContentProperty, currentWriteHolder);
converter.convertToExcelData(value, excelContentProperty, currentWriteHolder.globalConfiguration());
} catch (Exception e) { } catch (Exception e) {
throw new ExcelDataConvertException(cell.getRow().getRowNum(), cell.getColumnIndex(), throw new ExcelDataConvertException(cell.getRow().getRowNum(), cell.getColumnIndex(),
new CellData(CellDataTypeEnum.EMPTY), excelContentProperty, new CellData<>(CellDataTypeEnum.EMPTY), excelContentProperty,
"Convert data:" + value + " error,at row:" + cell.getRow().getRowNum(), e); "Convert data:" + value + " error,at row:" + cell.getRow().getRowNum(), e);
} }
if (cellData == null || cellData.getType() == null) { if (cellData == null || cellData.getType() == null) {
throw new ExcelDataConvertException(cell.getRow().getRowNum(), cell.getColumnIndex(), throw new ExcelDataConvertException(cell.getRow().getRowNum(), cell.getColumnIndex(),
new CellData(CellDataTypeEnum.EMPTY), excelContentProperty, new CellData<>(CellDataTypeEnum.EMPTY), excelContentProperty,
"Convert data:" + value + " return null,at row:" + cell.getRow().getRowNum()); "Convert data:" + value + " return null,at row:" + cell.getRow().getRowNum());
} }
return cellData; return cellData;
} }
private void setImageValue(CellData cellData, Cell cell) { private void setImageValue(CellData<?> cellData, Cell cell) {
Sheet sheet = cell.getSheet(); Sheet sheet = cell.getSheet();
int index = sheet.getWorkbook().addPicture(cellData.getImageValue(), HSSFWorkbook.PICTURE_TYPE_PNG); int index = sheet.getWorkbook().addPicture(cellData.getImageValue(), HSSFWorkbook.PICTURE_TYPE_PNG);
Drawing drawing = sheet.getDrawingPatriarch(); Drawing drawing = sheet.getDrawingPatriarch();

50
src/main/java/com/alibaba/excel/write/executor/ExcelWriteAddExecutor.java

@ -2,31 +2,32 @@ package com.alibaba.excel.write.executor;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.TreeMap; import java.util.TreeMap;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import com.alibaba.excel.context.WriteContext; import com.alibaba.excel.context.WriteContext;
import com.alibaba.excel.enums.HeadKindEnum; import com.alibaba.excel.enums.HeadKindEnum;
import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head; import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.property.ExcelContentProperty; import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.alibaba.excel.util.ClassUtils; import com.alibaba.excel.util.ClassUtils;
import com.alibaba.excel.util.CollectionUtils; import com.alibaba.excel.util.FieldUtils;
import com.alibaba.excel.util.WorkBookUtil; import com.alibaba.excel.util.WorkBookUtil;
import com.alibaba.excel.util.WriteHandlerUtils; import com.alibaba.excel.util.WriteHandlerUtils;
import com.alibaba.excel.write.metadata.WriteWorkbook; import com.alibaba.excel.write.metadata.CollectionRowData;
import com.alibaba.excel.write.metadata.holder.AbstractWriteHolder; import com.alibaba.excel.write.metadata.MapRowData;
import com.alibaba.excel.write.metadata.RowData;
import com.alibaba.excel.write.metadata.holder.WriteHolder; import com.alibaba.excel.write.metadata.holder.WriteHolder;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import net.sf.cglib.beans.BeanMap; import net.sf.cglib.beans.BeanMap;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
/** /**
* Add the data into excel * Add the data into excel
@ -39,9 +40,9 @@ public class ExcelWriteAddExecutor extends AbstractExcelWriteExecutor {
super(writeContext); super(writeContext);
} }
public void add(List data) { public void add(Collection<?> data) {
if (CollectionUtils.isEmpty(data)) { if (CollectionUtils.isEmpty(data)) {
data = new ArrayList(); data = new ArrayList<>();
} }
WriteSheetHolder writeSheetHolder = writeContext.writeSheetHolder(); WriteSheetHolder writeSheetHolder = writeContext.writeSheetHolder();
int newRowIndex = writeSheetHolder.getNewRowIndexAndStartDoWrite(); int newRowIndex = writeSheetHolder.getNewRowIndexAndStartDoWrite();
@ -49,11 +50,11 @@ public class ExcelWriteAddExecutor extends AbstractExcelWriteExecutor {
newRowIndex += writeContext.currentWriteHolder().relativeHeadRowIndex(); newRowIndex += writeContext.currentWriteHolder().relativeHeadRowIndex();
} }
// BeanMap is out of order,so use sortedAllFiledMap // BeanMap is out of order,so use sortedAllFiledMap
Map<Integer, Field> sortedAllFiledMap = new TreeMap<Integer, Field>(); Map<Integer, Field> sortedAllFiledMap = new TreeMap<>();
int relativeRowIndex = 0; int relativeRowIndex = 0;
for (Object oneRowData : data) { for (Object oneRowData : data) {
int n = relativeRowIndex + newRowIndex; int lastRowIndex = relativeRowIndex + newRowIndex;
addOneRowOfDataToExcel(oneRowData, n, relativeRowIndex, sortedAllFiledMap); addOneRowOfDataToExcel(oneRowData, lastRowIndex, relativeRowIndex, sortedAllFiledMap);
relativeRowIndex++; relativeRowIndex++;
} }
} }
@ -66,16 +67,19 @@ public class ExcelWriteAddExecutor extends AbstractExcelWriteExecutor {
WriteHandlerUtils.beforeRowCreate(writeContext, n, relativeRowIndex, Boolean.FALSE); WriteHandlerUtils.beforeRowCreate(writeContext, n, relativeRowIndex, Boolean.FALSE);
Row row = WorkBookUtil.createRow(writeContext.writeSheetHolder().getSheet(), n); Row row = WorkBookUtil.createRow(writeContext.writeSheetHolder().getSheet(), n);
WriteHandlerUtils.afterRowCreate(writeContext, row, relativeRowIndex, Boolean.FALSE); WriteHandlerUtils.afterRowCreate(writeContext, row, relativeRowIndex, Boolean.FALSE);
if (oneRowData instanceof List) {
addBasicTypeToExcel((List) oneRowData, row, relativeRowIndex); if (oneRowData instanceof Collection<?>) {
addBasicTypeToExcel(new CollectionRowData((Collection<?>)oneRowData), row, relativeRowIndex);
} else if (oneRowData instanceof Map) {
addBasicTypeToExcel(new MapRowData((Map<Integer, ?>)oneRowData), row, relativeRowIndex);
} else { } else {
addJavaObjectToExcel(oneRowData, row, relativeRowIndex, sortedAllFiledMap); addJavaObjectToExcel(oneRowData, row, relativeRowIndex, sortedAllFiledMap);
} }
WriteHandlerUtils.afterRowDispose(writeContext, row, relativeRowIndex, Boolean.FALSE); WriteHandlerUtils.afterRowDispose(writeContext, row, relativeRowIndex, Boolean.FALSE);
} }
private void addBasicTypeToExcel(List<Object> oneRowData, Row row, int relativeRowIndex) { private void addBasicTypeToExcel(RowData oneRowData, Row row, int relativeRowIndex) {
if (CollectionUtils.isEmpty(oneRowData)) { if (oneRowData.isEmpty()) {
return; return;
} }
Map<Integer, Head> headMap = writeContext.currentWriteHolder().excelWriteHeadProperty().getHeadMap(); Map<Integer, Head> headMap = writeContext.currentWriteHolder().excelWriteHeadProperty().getHeadMap();
@ -102,14 +106,15 @@ public class ExcelWriteAddExecutor extends AbstractExcelWriteExecutor {
} }
} }
private void doAddBasicTypeToExcel(List<Object> oneRowData, Head head, Row row, int relativeRowIndex, int dataIndex, private void doAddBasicTypeToExcel(RowData oneRowData, Head head, Row row, int relativeRowIndex,
int dataIndex,
int cellIndex) { int cellIndex) {
WriteHandlerUtils.beforeCellCreate(writeContext, row, head, cellIndex, relativeRowIndex, Boolean.FALSE); WriteHandlerUtils.beforeCellCreate(writeContext, row, head, cellIndex, relativeRowIndex, Boolean.FALSE);
Cell cell = WorkBookUtil.createCell(row, cellIndex); Cell cell = WorkBookUtil.createCell(row, cellIndex);
WriteHandlerUtils.afterCellCreate(writeContext, cell, head, relativeRowIndex, Boolean.FALSE); WriteHandlerUtils.afterCellCreate(writeContext, cell, head, relativeRowIndex, Boolean.FALSE);
Object value = oneRowData.get(dataIndex); Object value = oneRowData.get(dataIndex);
CellData cellData = converterAndSet(writeContext.currentWriteHolder(), value == null ? null : value.getClass(), CellData cellData = converterAndSet(writeContext.currentWriteHolder(), value == null ? null : value.getClass(),
cell, value, null, head, relativeRowIndex); null, cell, value, null, head, relativeRowIndex);
WriteHandlerUtils.afterCellDispose(writeContext, cellData, cell, head, relativeRowIndex, Boolean.FALSE); WriteHandlerUtils.afterCellDispose(writeContext, cellData, cell, head, relativeRowIndex, Boolean.FALSE);
} }
@ -127,7 +132,7 @@ public class ExcelWriteAddExecutor extends AbstractExcelWriteExecutor {
for (Map.Entry<Integer, ExcelContentProperty> entry : contentPropertyMap.entrySet()) { for (Map.Entry<Integer, ExcelContentProperty> entry : contentPropertyMap.entrySet()) {
cellIndex = entry.getKey(); cellIndex = entry.getKey();
ExcelContentProperty excelContentProperty = entry.getValue(); ExcelContentProperty excelContentProperty = entry.getValue();
String name = excelContentProperty.getField().getName(); String name = FieldUtils.resolveCglibFieldName(excelContentProperty.getField());
if (!beanMap.containsKey(name)) { if (!beanMap.containsKey(name)) {
continue; continue;
} }
@ -136,8 +141,9 @@ public class ExcelWriteAddExecutor extends AbstractExcelWriteExecutor {
Cell cell = WorkBookUtil.createCell(row, cellIndex); Cell cell = WorkBookUtil.createCell(row, cellIndex);
WriteHandlerUtils.afterCellCreate(writeContext, cell, head, relativeRowIndex, Boolean.FALSE); WriteHandlerUtils.afterCellCreate(writeContext, cell, head, relativeRowIndex, Boolean.FALSE);
Object value = beanMap.get(name); Object value = beanMap.get(name);
CellData cellData = converterAndSet(currentWriteHolder, excelContentProperty.getField().getType(), cell, CellData<?> cellData = converterAndSet(currentWriteHolder, excelContentProperty.getField().getType(),
value, excelContentProperty, head, relativeRowIndex); null,
cell, value, excelContentProperty, head, relativeRowIndex);
WriteHandlerUtils.afterCellDispose(writeContext, cellData, cell, head, relativeRowIndex, Boolean.FALSE); WriteHandlerUtils.afterCellDispose(writeContext, cellData, cell, head, relativeRowIndex, Boolean.FALSE);
beanMapHandledSet.add(name); beanMapHandledSet.add(name);
} }
@ -161,7 +167,7 @@ public class ExcelWriteAddExecutor extends AbstractExcelWriteExecutor {
WriteHandlerUtils.beforeCellCreate(writeContext, row, null, cellIndex, relativeRowIndex, Boolean.FALSE); WriteHandlerUtils.beforeCellCreate(writeContext, row, null, cellIndex, relativeRowIndex, Boolean.FALSE);
Cell cell = WorkBookUtil.createCell(row, cellIndex); Cell cell = WorkBookUtil.createCell(row, cellIndex);
WriteHandlerUtils.afterCellCreate(writeContext, cell, null, relativeRowIndex, Boolean.FALSE); WriteHandlerUtils.afterCellCreate(writeContext, cell, null, relativeRowIndex, Boolean.FALSE);
CellData cellData = converterAndSet(currentWriteHolder, value == null ? null : value.getClass(), cell, CellData<?> cellData = converterAndSet(currentWriteHolder, value == null ? null : value.getClass(), null, cell,
value, null, null, relativeRowIndex); value, null, null, relativeRowIndex);
WriteHandlerUtils.afterCellDispose(writeContext, cellData, cell, null, relativeRowIndex, Boolean.FALSE); WriteHandlerUtils.afterCellDispose(writeContext, cellData, cell, null, relativeRowIndex, Boolean.FALSE);
} }

40
src/main/java/com/alibaba/excel/write/executor/ExcelWriteFillExecutor.java

@ -9,12 +9,6 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import com.alibaba.excel.context.WriteContext; import com.alibaba.excel.context.WriteContext;
import com.alibaba.excel.enums.CellDataTypeEnum; import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.enums.WriteDirectionEnum; import com.alibaba.excel.enums.WriteDirectionEnum;
@ -22,7 +16,6 @@ import com.alibaba.excel.enums.WriteTemplateAnalysisCellTypeEnum;
import com.alibaba.excel.exception.ExcelGenerateException; import com.alibaba.excel.exception.ExcelGenerateException;
import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty; import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.excel.util.StringUtils; import com.alibaba.excel.util.StringUtils;
import com.alibaba.excel.util.WriteHandlerUtils; import com.alibaba.excel.util.WriteHandlerUtils;
import com.alibaba.excel.write.metadata.fill.AnalysisCell; import com.alibaba.excel.write.metadata.fill.AnalysisCell;
@ -31,6 +24,12 @@ import com.alibaba.excel.write.metadata.fill.FillWrapper;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import net.sf.cglib.beans.BeanMap; import net.sf.cglib.beans.BeanMap;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
/** /**
* Fill the data into excel * Fill the data into excel
@ -94,7 +93,7 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor {
Object realData; Object realData;
if (data instanceof FillWrapper) { if (data instanceof FillWrapper) {
FillWrapper fillWrapper = (FillWrapper) data; FillWrapper fillWrapper = (FillWrapper)data;
currentDataPrefix = fillWrapper.getName(); currentDataPrefix = fillWrapper.getName();
realData = fillWrapper.getCollectionData(); realData = fillWrapper.getCollectionData();
} else { } else {
@ -106,7 +105,7 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor {
// processing data // processing data
if (realData instanceof Collection) { if (realData instanceof Collection) {
List<AnalysisCell> analysisCellList = readTemplateData(templateCollectionAnalysisCache); List<AnalysisCell> analysisCellList = readTemplateData(templateCollectionAnalysisCache);
Collection collectionData = (Collection) realData; Collection collectionData = (Collection)realData;
if (CollectionUtils.isEmpty(collectionData)) { if (CollectionUtils.isEmpty(collectionData)) {
return; return;
} }
@ -179,9 +178,12 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor {
private void doFill(List<AnalysisCell> analysisCellList, Object oneRowData, FillConfig fillConfig, private void doFill(List<AnalysisCell> analysisCellList, Object oneRowData, FillConfig fillConfig,
Integer relativeRowIndex) { Integer relativeRowIndex) {
if (CollectionUtils.isEmpty(analysisCellList)) {
return;
}
Map dataMap; Map dataMap;
if (oneRowData instanceof Map) { if (oneRowData instanceof Map) {
dataMap = (Map) oneRowData; dataMap = (Map)oneRowData;
} else { } else {
dataMap = BeanMap.create(oneRowData); dataMap = BeanMap.create(oneRowData);
} }
@ -196,21 +198,21 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor {
continue; continue;
} }
Object value = dataMap.get(variable); Object value = dataMap.get(variable);
CellData cellData = converterAndSet(writeSheetHolder, value == null ? null : value.getClass(), cell, CellData<?> cellData = converterAndSet(writeSheetHolder, value == null ? null : value.getClass(), null,
value, fieldNameContentPropertyMap.get(variable), null, relativeRowIndex); cell, value, fieldNameContentPropertyMap.get(variable), null, relativeRowIndex);
WriteHandlerUtils.afterCellDispose(writeContext, cellData, cell, null, relativeRowIndex, Boolean.FALSE); WriteHandlerUtils.afterCellDispose(writeContext, cellData, cell, null, relativeRowIndex, Boolean.FALSE);
} else { } else {
StringBuilder cellValueBuild = new StringBuilder(); StringBuilder cellValueBuild = new StringBuilder();
int index = 0; int index = 0;
List<CellData> cellDataList = new ArrayList<CellData>(); List<CellData<?>> cellDataList = new ArrayList<>();
for (String variable : analysisCell.getVariableList()) { for (String variable : analysisCell.getVariableList()) {
cellValueBuild.append(analysisCell.getPrepareDataList().get(index++)); cellValueBuild.append(analysisCell.getPrepareDataList().get(index++));
if (!dataMap.containsKey(variable)) { if (!dataMap.containsKey(variable)) {
continue; continue;
} }
Object value = dataMap.get(variable); Object value = dataMap.get(variable);
CellData cellData = convert(writeSheetHolder, value == null ? null : value.getClass(), cell, value, CellData<?> cellData = convert(writeSheetHolder, value == null ? null : value.getClass(),
fieldNameContentPropertyMap.get(variable)); CellDataTypeEnum.STRING, cell, value, fieldNameContentPropertyMap.get(variable));
cellDataList.add(cellData); cellDataList.add(cellData);
CellDataTypeEnum type = cellData.getType(); CellDataTypeEnum type = cellData.getType();
if (type != null) { if (type != null) {
@ -291,7 +293,7 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor {
} }
Row row = createRowIfNecessary(sheet, cachedSheet, lastRowIndex, fillConfig, analysisCell, isOriginalCell); Row row = createRowIfNecessary(sheet, cachedSheet, lastRowIndex, fillConfig, analysisCell, isOriginalCell);
Cell cell = createCellIfNecessary(row,lastColumnIndex); Cell cell = createCellIfNecessary(row, lastColumnIndex);
Map<AnalysisCell, CellStyle> collectionFieldStyleMap = collectionFieldStyleCache.get(currentUniqueDataFlag); Map<AnalysisCell, CellStyle> collectionFieldStyleMap = collectionFieldStyleCache.get(currentUniqueDataFlag);
if (collectionFieldStyleMap == null) { if (collectionFieldStyleMap == null) {
@ -333,7 +335,8 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor {
row = cachedSheet.createRow(lastRowIndex); row = cachedSheet.createRow(lastRowIndex);
} else { } else {
// The last row of the middle disk inside empty rows, resulting in cachedSheet can not get inside. // The last row of the middle disk inside empty rows, resulting in cachedSheet can not get inside.
// Will throw Attempting to write a row[" + rownum + "] " + "in the range [0," + this._sh.getLastRowNum() + "] that is already written to disk. // Will throw Attempting to write a row[" + rownum + "] " + "in the range [0," + this._sh
// .getLastRowNum() + "] that is already written to disk.
try { try {
row = sheet.createRow(lastRowIndex); row = sheet.createRow(lastRowIndex);
} catch (IllegalArgumentException ignore) { } catch (IllegalArgumentException ignore) {
@ -412,7 +415,8 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor {
int startIndex = 0; int startIndex = 0;
int length = value.length(); int length = value.length();
int lastPrepareDataIndex = 0; int lastPrepareDataIndex = 0;
out: while (startIndex < length) { out:
while (startIndex < length) {
int prefixIndex = value.indexOf(FILL_PREFIX, startIndex); int prefixIndex = value.indexOf(FILL_PREFIX, startIndex);
if (prefixIndex < 0) { if (prefixIndex < 0) {
break out; break out;

4
src/main/java/com/alibaba/excel/write/handler/AbstractCellWriteHandler.java

@ -14,7 +14,9 @@ import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
* Abstract cell write handler * Abstract cell write handler
* *
* @author Jiaju Zhuang * @author Jiaju Zhuang
* @deprecated Please use it directly {@link CellWriteHandler}
**/ **/
@Deprecated
public abstract class AbstractCellWriteHandler implements CellWriteHandler { public abstract class AbstractCellWriteHandler implements CellWriteHandler {
@Override @Override
@ -37,7 +39,7 @@ public abstract class AbstractCellWriteHandler implements CellWriteHandler {
@Override @Override
public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { List<CellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
} }
} }

6
src/main/java/com/alibaba/excel/write/handler/AbstractRowWriteHandler.java

@ -1,15 +1,17 @@
package com.alibaba.excel.write.handler; package com.alibaba.excel.write.handler;
import org.apache.poi.ss.usermodel.Row;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder; import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import org.apache.poi.ss.usermodel.Row;
/** /**
* Abstract row write handler * Abstract row write handler
* *
* @author Jiaju Zhuang * @author Jiaju Zhuang
* @deprecated Please use it directly {@link RowWriteHandler}
**/ **/
@Deprecated
public abstract class AbstractRowWriteHandler implements RowWriteHandler { public abstract class AbstractRowWriteHandler implements RowWriteHandler {
@Override @Override
public void beforeRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Integer rowIndex, public void beforeRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Integer rowIndex,

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save