Browse Source

Merge branch '3.x' into 2.1.x

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

2
.github/ISSUE_TEMPLATE/bug.md

@ -7,6 +7,8 @@ assignees: zhuangjiaju
---
**建议先去看文档**
[快速开始](https://www.yuque.com/easyexcel/doc/easyexcel) 、[常见问题](https://www.yuque.com/easyexcel/faq)
**触发场景描述**
**触发Bug的代码**

4
.github/ISSUE_TEMPLATE/question.md

@ -1,12 +1,14 @@
---
name: question
about: 有使用疑问,请先阅读“快速使用”,上面无法解决再提交问题。处理完请关闭问题。
about: 有使用疑问,请先阅读“快速开始”,上面无法解决再提交问题。处理完请关闭问题。
title: ''
labels: help wanted
assignees: ''
---
**建议先去看文档**
[快速开始](https://www.yuque.com/easyexcel/doc/easyexcel) 、[常见问题](https://www.yuque.com/easyexcel/faq)
**异常代码**
```java
这里写你的代码

2
.github/ISSUE_TEMPLATE/suggest.md

@ -7,4 +7,6 @@ assignees: ''
---
**建议先去看文档**
[快速开始](https://www.yuque.com/easyexcel/doc/easyexcel) 、[常见问题](https://www.yuque.com/easyexcel/faq)
**建议描述**

8
CONTRIBUTING.md

@ -0,0 +1,8 @@
## 前言
非常感谢您愿意协助EasyExcel的开发,EasyExcel成长离不开大家的贡献。但是为了合作的更有效率,希望我们在贡献代码的时候能按照如下约定。
## 提前沟通
尽量把自己的想法和实现思路提前沟通,可以通过issue,钉钉,QQ都可以,可能很多问题我们内部已经讨论过,由于各种原因后续不会支持,但是您这边又开发好了,这样容易浪费您的时间。
## 代码规范
目前代码规范已经集成了自动校验,然后源代码尽量不要有中文注释。在新增功能的时候,尽量注意补充junit。core代表每次travis-ci都会跑的测试案例,然后demo用于对外看到,temp里面随便写。
## 提交分支
建议提交到最新的版本号.x上面,比如 3.x之类的版本,为了方便其他同学阅读源代码,所以目前的思路是master和maven center的最新版本代码保持一致,然后您提交过来的代码我们可能会稍微做一些修改。所以提交到开发分支会比较好。fork也可以直接fork该分支。

39
README.md

@ -1,26 +1,32 @@
easyexcel
EasyExcel
======================
[![Build Status](https://travis-ci.org/alibaba/easyexcel.svg?branch=master)](https://travis-ci.org/alibaba/easyexcel)
[![Maven central](https://maven-badges.herokuapp.com/maven-central/com.alibaba/easyexcel/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.alibaba/easyexcel)
[![License](http://img.shields.io/:license-apache-brightgreen.svg)](http://www.apache.org/licenses/LICENSE-2.0.html)
[QQ群: 662022184](//shang.qq.com/wpa/qunwpa?idkey=53d9d821b0833e3c14670f007488a61e300f00ff4f1b81fd950590d90dd80f80)
[钉钉群: 21960511](https://qr.dingtalk.com/action/joingroup?code=v1,k1,cchz6k12ci9B08NNqhNRFGXocNVHrZtW0kaOtTKg/Rk=&_dt_no_comment=1&origin=11)
[官方网站: https://alibaba-easyexcel.github.io/](https://alibaba-easyexcel.github.io/)
[QQ1群(已满): 662022184](https://jq.qq.com/?_wv=1027&k=1T21jJxh)
[QQ2群: 1097936804](https://jq.qq.com/?_wv=1027&k=j5zEy6Xl)
[钉钉1群(已满): 21960511](https://qr.dingtalk.com/action/joingroup?code=v1,k1,cchz6k12ci9B08NNqhNRFGXocNVHrZtW0kaOtTKg/Rk=&_dt_no_comment=1&origin=11)
[钉钉2群(已满): 32796397](https://qr.dingtalk.com/action/joingroup?code=v1,k1,jyU9GtEuNU5S0QTyklqYcYJ8qDZtUuTPMM7uPZTS8Hs=&_dt_no_comment=1&origin=11)
[钉钉3群(已满): 33797247](https://qr.dingtalk.com/action/joingroup?code=v1,k1,3UGlEScTGQaHpW2cIRo+gkxJ9EVZ5fz26M6nW3uFP30=&_dt_no_comment=1&origin=11)
[钉钉4群: 33491624](https://qr.dingtalk.com/action/joingroup?code=v1,k1,V14Pb65Too70rQkEaJ9ohb6lZBZbtp6jIL/q9EWh9vA=&_dt_no_comment=1&origin=11)
[官方网站: https://yuque.com/easyexcel](https://www.yuque.com/easyexcel/doc/easyexcel)
[常见问题](https://www.yuque.com/easyexcel/faq)
#### 因为公司不方便用QQ,所以建议加钉钉群
# JAVA解析Excel工具easyexcel
Java解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定程度的解决一些内存溢出的问题,但POI还是有一些缺陷,比如07版Excel解压缩以及解压后存储都是在内存中完成的,内存消耗依然很大。easyexcel重写了poi对07版Excel的解析,能够原本一个3M的excel用POI sax依然需要100M左右内存降低到几M,并且再大的excel不会出现内存溢出,03版依赖POI的sax模式。在上层做了模型转换的封装,让使用者更加简单方便
# JAVA解析Excel工具EasyExcel
Java解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定程度的解决一些内存溢出的问题,但POI还是有一些缺陷,比如07版Excel解压缩以及解压后存储都是在内存中完成的,内存消耗依然很大。easyexcel重写了poi对07版Excel的解析,一个3M的excel用POI sax解析依然需要100M左右内存,改用easyexcel可以降低到几M,并且再大的excel也不会出现内存溢出;03版依赖POI的sax模式,在上层做了模型转换的封装,让使用者更加简单方便
## 64M内存1分钟内读取75M(46W行25列)的Excel
当然还有速模式能更快,但是内存占用会在100M多一点
当然还有速模式能更快,但是内存占用会在100M多一点
![img](img/readme/large.png)
## 相关文档
* [快速使用](https://alibaba-easyexcel.github.io/)
* [快速开始](https://www.yuque.com/easyexcel/doc/easyexcel)
* [关于软件](/abouteasyexcel.md)
* [更新记事](/update.md)
* [贡献代码](https://alibaba-easyexcel.github.io/support/contribute.html)
* [贡献代码](https://www.yuque.com/easyexcel/doc/contribute)
## 维护者
玉霄、庄家钜、怀宇
@ -65,18 +71,21 @@ DEMO代码地址:[https://github.com/alibaba/easyexcel/blob/master/src/test/ja
```java
/**
* 文件下载(失败了会返回一个有部分数据的Excel)
* <p>1. 创建excel对应的实体对象 参照{@link DownloadData}
* <p>2. 设置返回的 参数
* <p>3. 直接写,这里注意,finish的时候会自动关闭OutputStream,当然你外面再关闭流问题不大
* <p>
* 1. 创建excel对应的实体对象 参照{@link DownloadData}
* <p>
* 2. 设置返回的 参数
* <p>
* 3. 直接写,这里注意,finish的时候会自动关闭OutputStream,当然你外面再关闭流问题不大
*/
@GetMapping("download")
public void download(HttpServletResponse response) throws IOException {
// 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman
response.setContentType("application/vnd.ms-excel");
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
String fileName = URLEncoder.encode("测试", "UTF-8");
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
EasyExcel.write(response.getOutputStream(), DownloadData.class).sheet("模板").doWrite(data());
}

50
pom.xml

@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.2.0-beta2</version>
<version>3.0.0-beta1</version>
<packaging>jar</packaging>
<name>easyexcel</name>
@ -16,7 +16,7 @@
<properties>
<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>
<maven.javadoc.skip>true</maven.javadoc.skip>
</properties>
@ -60,22 +60,22 @@
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>3.17</version>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.1</version>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
@ -85,8 +85,15 @@
<dependency>
<groupId>org.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>3.4.0</version>
<version>3.8.1</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
<scope>provided</scope>
</dependency>
<!--test-->
<dependency>
<groupId>ch.qos.logback</groupId>
@ -97,13 +104,7 @@
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.58</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
<version>1.2.71</version>
<scope>test</scope>
</dependency>
<dependency>
@ -121,7 +122,7 @@
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
</dependencies>
@ -162,6 +163,8 @@
<exclude>com/alibaba/excel/event/AnalysisEventListener.java</exclude>
<exclude>com/alibaba/excel/metadata/DataFormatter.java</exclude>
<exclude>com/alibaba/excel/util/DateUtils.java</exclude>
<exclude>com/alibaba/excel/metadata/format/DataFormatter.java</exclude>
<exclude>com/alibaba/excel/metadata/format/ExcelGeneralNumberFormat.java</exclude>
</excludes>
</configuration>
<executions>
@ -185,8 +188,8 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
@ -230,6 +233,19 @@
</execution>
</executions>
</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>
</build>
</project>

4
src/main/java/com/alibaba/excel/ExcelReader.java

@ -136,6 +136,8 @@ public class ExcelReader {
readWorkbook.setReadCache(new MapCache());
readWorkbook.setConvertAllFiled(Boolean.FALSE);
readWorkbook.setDefaultReturnMap(Boolean.FALSE);
// The previous logic was that Article 0 started reading
readWorkbook.setHeadRowNumber(0);
excelAnalyser = new ExcelAnalyserImpl(readWorkbook);
}
@ -274,8 +276,10 @@ public class ExcelReader {
* Complete the entire read file.Release the cache and close stream.
*/
public void finish() {
if (excelAnalyser != null) {
excelAnalyser.finish();
}
}
/**
* Prevents calls to {@link #finish} from freeing the cache

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

@ -3,6 +3,8 @@ package com.alibaba.excel;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.slf4j.Logger;
@ -142,7 +144,7 @@ public class ExcelWriter {
* Write to this sheet
* @return this current writer
*/
public ExcelWriter write(List data, WriteSheet writeSheet) {
public ExcelWriter write(Collection<?> data, WriteSheet writeSheet) {
return write(data, writeSheet, null);
}
@ -157,7 +159,7 @@ public class ExcelWriter {
* Write to this table
* @return this
*/
public ExcelWriter write(List data, WriteSheet writeSheet, WriteTable writeTable) {
public ExcelWriter write(Collection<?> data, WriteSheet writeSheet, WriteTable writeTable) {
excelBuilder.addContent(data, writeSheet, writeTable);
return this;
}
@ -194,7 +196,7 @@ public class ExcelWriter {
* @param sheet
* Write to this sheet
* @return this current writer
* @deprecated please use {@link ExcelWriter#write(List, WriteSheet)}
* @deprecated please use {@link ExcelWriter#write(Collection, WriteSheet)}
*/
@Deprecated
public ExcelWriter write(List data, Sheet sheet) {
@ -211,7 +213,7 @@ public class ExcelWriter {
* @param table
* Write to this table
* @return this
* @deprecated * @deprecated please use {@link ExcelWriter#write(List, WriteSheet,WriteTable)}
* @deprecated * @deprecated please use {@link ExcelWriter#write(Collection, WriteSheet,WriteTable)}
*/
@Deprecated
public ExcelWriter write(List data, Sheet sheet, Table table) {
@ -246,7 +248,7 @@ public class ExcelWriter {
* @param sheet
* Write to this sheet
* @return this current writer
* @deprecated please use {@link ExcelWriter#write(List, WriteSheet)}
* @deprecated please use {@link ExcelWriter#write(Collection, WriteSheet)}
*/
@Deprecated
public ExcelWriter write0(List data, Sheet sheet) {
@ -263,7 +265,7 @@ public class ExcelWriter {
* @param table
* Write to this table
* @return this
* @deprecated * @deprecated please use {@link ExcelWriter#write(List, WriteSheet,WriteTable)}
* @deprecated * @deprecated please use {@link ExcelWriter#write(Collection, WriteSheet,WriteTable)}
*/
@Deprecated
public ExcelWriter write0(List data, Sheet sheet, Table table) {
@ -278,7 +280,7 @@ public class ExcelWriter {
* @param sheet
* Write to this sheet
* @return this current writer
* @deprecated please use {@link ExcelWriter#write(List, WriteSheet)}
* @deprecated please use {@link ExcelWriter#write(Collection, WriteSheet)}
*/
@Deprecated
public ExcelWriter write1(List data, Sheet sheet) {
@ -295,7 +297,7 @@ public class ExcelWriter {
* @param table
* Write to this table
* @return this
* @deprecated * @deprecated please use {@link ExcelWriter#write(List, WriteSheet,WriteTable)}
* @deprecated * @deprecated please use {@link ExcelWriter#write(Collection, WriteSheet,WriteTable)}
*/
@Deprecated
public ExcelWriter write1(List data, Sheet sheet, Table table) {
@ -325,8 +327,10 @@ public class ExcelWriter {
* Close IO
*/
public void finish() {
if (excelBuilder != null) {
excelBuilder.finish(false);
}
}
/**
* Prevents calls to {@link #finish} from freeing the cache

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

13
src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java

@ -70,12 +70,12 @@ import com.alibaba.excel.read.metadata.holder.xls.XlsReadWorkbookHolder;
* <p>
* * To turn an excel file into a CSV or similar, then see * the XLS2CSVmra example *
* </p>
* * * @see <a href=
* "http://svn.apache.org/repos/asf/poi/trunk/src/examples/src/org/apache/poi/hssf/eventusermodel/examples/XLS2CSVmra.java">XLS2CSVmra</a>
* * * @see <a href= "http://svn.apache.org/repos/asf/poi/trunk/src/examples/src/org/apache/poi/hssf/eventusermodel/examples/XLS2CSVmra.java">XLS2CSVmra</a>
*
* @author jipengfei
*/
public class XlsSaxAnalyser implements HSSFListener, ExcelReadExecutor {
private static final Logger LOGGER = LoggerFactory.getLogger(XlsSaxAnalyser.class);
private static final short DUMMY_RECORD_SID = -1;
private XlsReadContext xlsReadContext;
@ -138,11 +138,6 @@ public class XlsSaxAnalyser implements HSSFListener, ExcelReadExecutor {
} catch (IOException e) {
throw new ExcelAnalysisException(e);
}
// Sometimes tables lack the end record of the last column
if (!xlsReadContext.xlsReadSheetHolder().getCellMap().isEmpty()) {
// Forge a termination data
processRecord(new LastCellOfRowDummyRecord(xlsReadContext.xlsReadSheetHolder().getRowIndex() + 1, -1));
}
}
@Override
@ -151,8 +146,8 @@ public class XlsSaxAnalyser implements HSSFListener, ExcelReadExecutor {
if (handler == null) {
return;
}
boolean ignoreRecord = (handler instanceof IgnorableXlsRecordHandler)
&& xlsReadContext.xlsReadSheetHolder() != null && xlsReadContext.xlsReadSheetHolder().getIgnoreRecord();
boolean ignoreRecord =
(handler instanceof IgnorableXlsRecordHandler) && xlsReadContext.xlsReadWorkbookHolder().getIgnoreRecord();
if (ignoreRecord) {
// No need to read the current sheet
return;

11
src/main/java/com/alibaba/excel/analysis/v03/handlers/BofRecordHandler.java

@ -26,6 +26,7 @@ public class BofRecordHandler extends AbstractXlsRecordHandler {
XlsReadWorkbookHolder xlsReadWorkbookHolder = xlsReadContext.xlsReadWorkbookHolder();
if (br.getType() == BOFRecord.TYPE_WORKBOOK) {
xlsReadWorkbookHolder.setReadSheetIndex(null);
xlsReadWorkbookHolder.setIgnoreRecord(Boolean.FALSE);
return;
}
if (br.getType() != BOFRecord.TYPE_WORKSHEET) {
@ -38,15 +39,15 @@ public class BofRecordHandler extends AbstractXlsRecordHandler {
readSheetIndex = 0;
xlsReadWorkbookHolder.setReadSheetIndex(readSheetIndex);
}
ReadSheet readSheet = xlsReadWorkbookHolder.getActualSheetDataList().get(readSheetIndex);
assert readSheet != null : "Can't find the sheet.";
ReadSheet actualReadSheet = xlsReadWorkbookHolder.getActualSheetDataList().get(readSheetIndex);
assert actualReadSheet != null : "Can't find the sheet.";
// Copy the parameter to the current sheet
readSheet = SheetUtils.match(readSheet, xlsReadContext);
ReadSheet readSheet = SheetUtils.match(actualReadSheet, xlsReadContext);
if (readSheet != null) {
xlsReadContext.currentSheet(readSheet);
xlsReadContext.xlsReadSheetHolder().setIgnoreRecord(Boolean.FALSE);
xlsReadContext.xlsReadWorkbookHolder().setIgnoreRecord(Boolean.FALSE);
} else {
xlsReadContext.xlsReadSheetHolder().setIgnoreRecord(Boolean.TRUE);
xlsReadContext.xlsReadWorkbookHolder().setIgnoreRecord(Boolean.TRUE);
}
// Go read the next one
xlsReadWorkbookHolder.setReadSheetIndex(xlsReadWorkbookHolder.getReadSheetIndex() + 1);

24
src/main/java/com/alibaba/excel/analysis/v03/handlers/EofRecordHandler.java

@ -1,9 +1,16 @@
package com.alibaba.excel.analysis.v03.handlers;
import java.util.LinkedHashMap;
import org.apache.poi.hssf.eventusermodel.dummyrecord.LastCellOfRowDummyRecord;
import org.apache.poi.hssf.record.Record;
import com.alibaba.excel.analysis.v03.IgnorableXlsRecordHandler;
import com.alibaba.excel.context.xls.XlsReadContext;
import com.alibaba.excel.enums.RowTypeEnum;
import com.alibaba.excel.metadata.Cell;
import com.alibaba.excel.read.metadata.holder.ReadRowHolder;
import com.alibaba.excel.read.metadata.holder.xls.XlsReadSheetHolder;
/**
* Record handler
@ -14,8 +21,21 @@ public class EofRecordHandler extends AbstractXlsRecordHandler implements Ignora
@Override
public void processRecord(XlsReadContext xlsReadContext, Record record) {
if (xlsReadContext.readSheetHolder() != null) {
xlsReadContext.analysisEventProcessor().endSheet(xlsReadContext);
if (xlsReadContext.readSheetHolder() == null) {
return;
}
// Sometimes tables lack the end record of the last column
if (!xlsReadContext.xlsReadSheetHolder().getCellMap().isEmpty()) {
XlsReadSheetHolder xlsReadSheetHolder = xlsReadContext.xlsReadSheetHolder();
// Forge a termination data
xlsReadContext.readRowHolder(new ReadRowHolder(xlsReadContext.xlsReadSheetHolder().getRowIndex() + 1,
xlsReadSheetHolder.getTempRowType(),
xlsReadContext.readSheetHolder().getGlobalConfiguration(), xlsReadSheetHolder.getCellMap()));
xlsReadContext.analysisEventProcessor().endRow(xlsReadContext);
xlsReadSheetHolder.setCellMap(new LinkedHashMap<Integer, Cell>());
xlsReadSheetHolder.setTempRowType(RowTypeEnum.EMPTY);
}
xlsReadContext.analysisEventProcessor().endSheet(xlsReadContext);
}
}

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

@ -3,20 +3,21 @@ package com.alibaba.excel.analysis.v03.handlers;
import java.math.BigDecimal;
import java.util.Map;
import org.apache.poi.hssf.model.HSSFFormulaParser;
import org.apache.poi.hssf.record.FormulaRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.ss.usermodel.CellType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.excel.analysis.v03.IgnorableXlsRecordHandler;
import com.alibaba.excel.constant.BuiltinFormats;
import com.alibaba.excel.context.xls.XlsReadContext;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.enums.RowTypeEnum;
import com.alibaba.excel.metadata.Cell;
import com.alibaba.excel.metadata.CellData;
import org.apache.poi.hssf.model.HSSFFormulaParser;
import org.apache.poi.hssf.record.FormulaRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.ss.usermodel.CellType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Record handler
*
@ -30,7 +31,7 @@ public class FormulaRecordHandler extends AbstractXlsRecordHandler implements Ig
public void processRecord(XlsReadContext xlsReadContext, Record record) {
FormulaRecord frec = (FormulaRecord)record;
Map<Integer, Cell> cellMap = xlsReadContext.xlsReadSheetHolder().getCellMap();
CellData tempCellData = new CellData();
CellData<?> tempCellData = new CellData<>();
tempCellData.setRowIndex(frec.getRow());
tempCellData.setColumnIndex((int)frec.getColumn());
CellType cellType = CellType.forInt(frec.getCachedResultType());
@ -43,6 +44,7 @@ public class FormulaRecordHandler extends AbstractXlsRecordHandler implements Ig
}
tempCellData.setFormula(Boolean.TRUE);
tempCellData.setFormulaValue(formulaValue);
xlsReadContext.xlsReadSheetHolder().setTempRowType(RowTypeEnum.DATA);
switch (cellType) {
case STRING:
// Formula result is a string
@ -55,8 +57,9 @@ public class FormulaRecordHandler extends AbstractXlsRecordHandler implements Ig
tempCellData.setNumberValue(BigDecimal.valueOf(frec.getValue()));
Integer dataFormat =
xlsReadContext.xlsReadWorkbookHolder().getFormatTrackingHSSFListener().getFormatIndex(frec);
tempCellData.setDataFormat(dataFormat);
tempCellData.setDataFormatString(BuiltinFormats.getBuiltinFormat(dataFormat,
Short dataFormatShort = dataFormat.shortValue();
tempCellData.setDataFormat(dataFormatShort);
tempCellData.setDataFormatString(BuiltinFormats.getBuiltinFormat(dataFormatShort,
xlsReadContext.xlsReadWorkbookHolder().getFormatTrackingHSSFListener().getFormatString(frec),
xlsReadContext.readSheetHolder().getGlobalConfiguration().getLocale()));
cellMap.put((int)frec.getColumn(), tempCellData);

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

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

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.UUID;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import com.alibaba.excel.analysis.ExcelReadExecutor;
import com.alibaba.excel.analysis.v07.handlers.sax.SharedStringsTableHandler;
import com.alibaba.excel.analysis.v07.handlers.sax.XlsxRowHandler;
import com.alibaba.excel.cache.ReadCache;
import com.alibaba.excel.context.xlsx.XlsxReadContext;
import com.alibaba.excel.enums.CellExtraTypeEnum;
import com.alibaba.excel.exception.ExcelAnalysisException;
import com.alibaba.excel.metadata.CellExtra;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.alibaba.excel.read.metadata.holder.xlsx.XlsxReadWorkbookHolder;
import com.alibaba.excel.util.FileUtils;
import com.alibaba.excel.util.SheetUtils;
import com.alibaba.excel.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackageAccess;
import org.apache.poi.openxml4j.opc.PackagePart;
@ -25,26 +42,13 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorkbookPr;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.WorkbookDocument;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import com.alibaba.excel.analysis.ExcelReadExecutor;
import com.alibaba.excel.analysis.v07.handlers.sax.SharedStringsTableHandler;
import com.alibaba.excel.analysis.v07.handlers.sax.XlsxRowHandler;
import com.alibaba.excel.cache.ReadCache;
import com.alibaba.excel.context.xlsx.XlsxReadContext;
import com.alibaba.excel.enums.CellExtraTypeEnum;
import com.alibaba.excel.exception.ExcelAnalysisException;
import com.alibaba.excel.metadata.CellExtra;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.alibaba.excel.read.metadata.holder.xlsx.XlsxReadWorkbookHolder;
import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.excel.util.FileUtils;
import com.alibaba.excel.util.SheetUtils;
import com.alibaba.excel.util.StringUtils;
/**
* @author jipengfei
*/
@Slf4j
public class XlsxSaxAnalyser implements ExcelReadExecutor {
private XlsxReadContext xlsxReadContext;
@ -78,7 +82,9 @@ public class XlsxSaxAnalyser implements ExcelReadExecutor {
XSSFReader xssfReader = new XSSFReader(pkg);
analysisUse1904WindowDate(xssfReader, xlsxReadWorkbookHolder);
xlsxReadWorkbookHolder.setStylesTable(xssfReader.getStylesTable());
// set style table
setStylesTable(xlsxReadWorkbookHolder, xssfReader);
sheetList = new ArrayList<ReadSheet>();
sheetMap = new HashMap<Integer, InputStream>();
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,
PackagePart sharedStringsTablePackagePart) {
ReadCache readCache = xlsxReadWorkbookHolder.getReadCacheSelector().readCache(sharedStringsTablePackagePart);
@ -147,9 +164,10 @@ public class XlsxSaxAnalyser implements ExcelReadExecutor {
xlsxReadWorkbookHolder.setTempFile(readTempFile);
File tempFile = new File(readTempFile.getPath(), UUID.randomUUID().toString() + ".xlsx");
if (decryptedStream != null) {
FileUtils.writeToFile(tempFile, decryptedStream);
FileUtils.writeToFile(tempFile, decryptedStream, false);
} else {
FileUtils.writeToFile(tempFile, xlsxReadWorkbookHolder.getInputStream());
FileUtils.writeToFile(tempFile, xlsxReadWorkbookHolder.getInputStream(),
xlsxReadWorkbookHolder.getAutoCloseStream());
}
return OPCPackage.open(tempFile, PackageAccess.READ);
}
@ -177,9 +195,7 @@ public class XlsxSaxAnalyser implements ExcelReadExecutor {
xmlReader.setContentHandler(handler);
xmlReader.parse(inputSource);
inputStream.close();
} catch (ExcelAnalysisException e) {
throw e;
} catch (Exception e) {
} catch (IOException | ParserConfigurationException | SAXException e) {
throw new ExcelAnalysisException(e);
} finally {
if (inputStream != null) {

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

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

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

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

@ -1,8 +1,5 @@
package com.alibaba.excel.analysis.v07.handlers;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.xml.sax.Attributes;
import com.alibaba.excel.constant.BuiltinFormats;
import com.alibaba.excel.constant.ExcelXmlConstants;
import com.alibaba.excel.context.xlsx.XlsxReadContext;
@ -12,6 +9,10 @@ import com.alibaba.excel.read.metadata.holder.xlsx.XlsxReadSheetHolder;
import com.alibaba.excel.util.PositionUtils;
import com.alibaba.excel.util.StringUtils;
import org.apache.poi.xssf.model.StylesTable;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.xml.sax.Attributes;
/**
* Cell Handler
*
@ -46,9 +47,12 @@ public class CellTagHandler extends AbstractXlsxTagHandler {
} else {
dateFormatIndexInteger = Integer.parseInt(dateFormatIndex);
}
XSSFCellStyle xssfCellStyle =
xlsxReadContext.xlsxReadWorkbookHolder().getStylesTable().getStyleAt(dateFormatIndexInteger);
int dataFormat = xssfCellStyle.getDataFormat();
StylesTable stylesTable = xlsxReadContext.xlsxReadWorkbookHolder().getStylesTable();
if (stylesTable == null) {
return;
}
XSSFCellStyle xssfCellStyle = stylesTable.getStyleAt(dateFormatIndexInteger);
short dataFormat = xssfCellStyle.getDataFormat();
xlsxReadSheetHolder.getTempCellData().setDataFormat(dataFormat);
xlsxReadSheetHolder.getTempCellData().setDataFormatString(BuiltinFormats.getBuiltinFormat(dataFormat,
xssfCellStyle.getDataFormatString(), xlsxReadSheetHolder.getGlobalConfiguration().getLocale()));

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.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.util.StringUtils;
/**
* Cell Value Handler
@ -17,6 +18,10 @@ public class CellValueTagHandler extends AbstractCellValueTagHandler {
CellData tempCellData = xlsxReadContext.xlsxReadSheetHolder().getTempCellData();
switch (tempCellData.getType()) {
case STRING:
// In some cases, although cell type is a string, it may be an empty tag
if(StringUtils.isEmpty(tempCellData.getStringValue())){
break;
}
String stringValue = xlsxReadContext.readWorkbookHolder().getReadCache()
.get(Integer.valueOf(tempCellData.getStringValue()));
if (stringValue != null && xlsxReadContext.currentReadHolder().globalConfiguration().getAutoTrim()) {

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

@ -2,8 +2,6 @@ package com.alibaba.excel.analysis.v07.handlers;
import java.util.LinkedHashMap;
import org.xml.sax.Attributes;
import com.alibaba.excel.constant.ExcelXmlConstants;
import com.alibaba.excel.context.xlsx.XlsxReadContext;
import com.alibaba.excel.enums.RowTypeEnum;
@ -12,6 +10,9 @@ import com.alibaba.excel.read.metadata.holder.ReadRowHolder;
import com.alibaba.excel.read.metadata.holder.xlsx.XlsxReadSheetHolder;
import com.alibaba.excel.util.PositionUtils;
import org.apache.commons.collections4.MapUtils;
import org.xml.sax.Attributes;
/**
* Cell Handler
*
@ -25,7 +26,6 @@ public class RowTagHandler extends AbstractXlsxTagHandler {
int rowIndex = PositionUtils.getRowByRowTagt(attributes.getValue(ExcelXmlConstants.ATTRIBUTE_R),
xlsxReadSheetHolder.getRowIndex());
Integer lastRowIndex = xlsxReadContext.readSheetHolder().getRowIndex();
if (lastRowIndex != null) {
while (lastRowIndex + 1 < rowIndex) {
xlsxReadContext.readRowHolder(new ReadRowHolder(lastRowIndex + 1, RowTypeEnum.EMPTY,
xlsxReadSheetHolder.getGlobalConfiguration(), new LinkedHashMap<Integer, Cell>()));
@ -34,18 +34,18 @@ public class RowTagHandler extends AbstractXlsxTagHandler {
xlsxReadSheetHolder.setCellMap(new LinkedHashMap<Integer, Cell>());
lastRowIndex++;
}
}
xlsxReadSheetHolder.setRowIndex(rowIndex);
}
@Override
public void endElement(XlsxReadContext xlsxReadContext, String name) {
XlsxReadSheetHolder xlsxReadSheetHolder = xlsxReadContext.xlsxReadSheetHolder();
xlsxReadContext.readRowHolder(new ReadRowHolder(xlsxReadSheetHolder.getRowIndex(), RowTypeEnum.DATA,
RowTypeEnum rowType = MapUtils.isEmpty(xlsxReadSheetHolder.getCellMap()) ? RowTypeEnum.EMPTY : RowTypeEnum.DATA;
xlsxReadContext.readRowHolder(new ReadRowHolder(xlsxReadSheetHolder.getRowIndex(), rowType,
xlsxReadSheetHolder.getGlobalConfiguration(), xlsxReadSheetHolder.getCellMap()));
xlsxReadContext.analysisEventProcessor().endRow(xlsxReadContext);
xlsxReadSheetHolder.setColumnIndex(null);
xlsxReadSheetHolder.setCellMap(new LinkedHashMap<Integer, Cell>());
xlsxReadSheetHolder.setCellMap(new LinkedHashMap<>());
}
}

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

@ -23,7 +23,7 @@ public @interface ExcelProperty {
* <p>
* write: It automatically merges when you have more than one head
* <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
*/
@ -32,12 +32,23 @@ public @interface ExcelProperty {
/**
* Index of column
*
* Read or write it on the index of column,If it's equal to -1, it's sorted by Java class
* Read or write it on the index of column,If it's equal to -1, it's sorted by Java class.
*
* priority: index &gt; order &gt; default sort
*
* @return Index of column
*/
int index() default -1;
/**
* Defines the sort order for an column.
*
* priority: index &gt; order &gt; default sort
*
* @return Order of column
*/
int order() default Integer.MAX_VALUE;
/**
* Force the current field to use this converter.
*

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

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

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

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

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

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

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

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

@ -6,22 +6,6 @@ import java.io.OutputStream;
import java.util.Map;
import java.util.UUID;
import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackageAccess;
import org.apache.poi.poifs.crypt.EncryptionInfo;
import org.apache.poi.poifs.crypt.EncryptionMode;
import org.apache.poi.poifs.crypt.Encryptor;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.excel.enums.WriteTypeEnum;
import com.alibaba.excel.exception.ExcelGenerateException;
import com.alibaba.excel.metadata.CellData;
@ -42,6 +26,22 @@ import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import com.alibaba.excel.write.property.ExcelWriteHeadProperty;
import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackageAccess;
import org.apache.poi.poifs.crypt.EncryptionInfo;
import org.apache.poi.poifs.crypt.EncryptionMode;
import org.apache.poi.poifs.crypt.Encryptor;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A context is the main anchorage point of a excel writer.
*
@ -50,6 +50,7 @@ import com.alibaba.excel.write.property.ExcelWriteHeadProperty;
public class WriteContextImpl implements WriteContext {
private static final Logger LOGGER = LoggerFactory.getLogger(WriteContextImpl.class);
private static final String NO_SHEETS="no sheets";
/**
* The Workbook currently written
@ -111,15 +112,25 @@ public class WriteContextImpl implements WriteContext {
if (selectSheetFromCache(writeSheet)) {
return;
}
initCurrentSheetHolder(writeSheet);
// Workbook handler need to supplementary execution
WriteHandlerUtils.beforeWorkbookCreate(this, true);
WriteHandlerUtils.afterWorkbookCreate(this, true);
// Initialization current sheet
initSheet(writeType);
}
private boolean selectSheetFromCache(WriteSheet writeSheet) {
writeSheetHolder = null;
if (writeSheet.getSheetNo() != null) {
writeSheetHolder = writeWorkbookHolder.getHasBeenInitializedSheetIndexMap().get(writeSheet.getSheetNo());
Integer sheetNo = writeSheet.getSheetNo();
if (sheetNo == null && StringUtils.isEmpty(writeSheet.getSheetName())) {
sheetNo = 0;
}
if (sheetNo != null) {
writeSheetHolder = writeWorkbookHolder.getHasBeenInitializedSheetIndexMap().get(sheetNo);
}
if (writeSheetHolder == null && !StringUtils.isEmpty(writeSheet.getSheetName())) {
writeSheetHolder = writeWorkbookHolder.getHasBeenInitializedSheetNameMap().get(writeSheet.getSheetName());
@ -153,17 +164,27 @@ public class WriteContextImpl implements WriteContext {
Sheet currentSheet;
try {
if (writeSheetHolder.getSheetNo() != null) {
// When the add default sort order of appearance
if (WriteTypeEnum.ADD.equals(writeType) && writeWorkbookHolder.getTempTemplateInputStream() == null) {
currentSheet = createSheet();
} else {
currentSheet = writeWorkbookHolder.getWorkbook().getSheetAt(writeSheetHolder.getSheetNo());
writeSheetHolder
.setCachedSheet(writeWorkbookHolder.getCachedWorkbook().getSheetAt(writeSheetHolder.getSheetNo()));
.setCachedSheet(
writeWorkbookHolder.getCachedWorkbook().getSheetAt(writeSheetHolder.getSheetNo()));
}
} else {
// sheet name must not null
currentSheet = writeWorkbookHolder.getWorkbook().getSheet(writeSheetHolder.getSheetName());
writeSheetHolder
.setCachedSheet(writeWorkbookHolder.getCachedWorkbook().getSheet(writeSheetHolder.getSheetName()));
}
} catch (Exception e) {
} catch (IllegalArgumentException e) {
if (e.getMessage() != null && e.getMessage().contains(NO_SHEETS)) {
currentSheet = createSheet();
} else {
throw e;
}
}
if (currentSheet == null) {
currentSheet = createSheet();
@ -201,8 +222,8 @@ public class WriteContextImpl implements WriteContext {
if (currentWriteHolder.automaticMergeHead()) {
addMergedRegionToCurrentSheet(excelWriteHeadProperty, newRowIndex);
}
for (int relativeRowIndex = 0, i = newRowIndex; i < excelWriteHeadProperty.getHeadRowNumber() + newRowIndex;
i++, relativeRowIndex++) {
for (int relativeRowIndex = 0, i = newRowIndex; i < excelWriteHeadProperty.getHeadRowNumber()
+ newRowIndex; i++, relativeRowIndex++) {
WriteHandlerUtils.beforeRowCreate(this, newRowIndex, relativeRowIndex, Boolean.TRUE);
Row row = WorkBookUtil.createRow(writeSheetHolder.getSheet(), i);
WriteHandlerUtils.afterRowCreate(this, row, relativeRowIndex, Boolean.TRUE);
@ -251,7 +272,15 @@ public class WriteContextImpl implements WriteContext {
}
return;
}
initCurrentTableHolder(writeTable);
// Workbook and sheet handler need to supplementary execution
WriteHandlerUtils.beforeWorkbookCreate(this, true);
WriteHandlerUtils.afterWorkbookCreate(this, true);
WriteHandlerUtils.beforeSheetCreate(this, true);
WriteHandlerUtils.afterSheetCreate(this, true);
initHead(writeTableHolder.excelWriteHeadProperty());
}

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

@ -10,10 +10,10 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty;
*
* @author Jiaju Zhuang
*/
public class AutoConverter implements Converter {
public class AutoConverter implements Converter<Object> {
@Override
public Class supportJavaTypeKey() {
public Class<?> supportJavaTypeKey() {
return null;
}
@ -23,13 +23,13 @@ public class AutoConverter implements Converter {
}
@Override
public Object convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
public Object convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
return null;
}
@Override
public CellData convertToExcelData(Object value, ExcelContentProperty contentProperty,
public CellData<?> convertToExcelData(Object value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
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.GlobalConfiguration;
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
*
* @author Dan Zheng
* @param <T>
* @author Dan Zheng
*/
public interface Converter<T> {
@ -18,44 +22,72 @@ public interface Converter<T> {
*
* @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
*
* @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
*
* @param cellData
* Excel cell data.NotNull.
* @param contentProperty
* Content property.Nullable.
* @param globalConfiguration
* Global configuration.NotNull.
* @param cellData Excel cell data.NotNull.
* @param contentProperty Content property.Nullable.
* @param readSheetHolder .NotNull.
* @return Data to put into a Java object
* @throws Exception
* Exception.
* @throws 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,
GlobalConfiguration globalConfiguration) throws Exception;
default CellData<?> convertToExcelData(T value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) throws Exception {
throw new UnsupportedOperationException("The current operation is not supported by the current converter.");
}
/**
* Convert Java objects to excel objects
*
* @param value
* Java Data.NotNull.
* @param contentProperty
* Content property.Nullable.
* @param globalConfiguration
* Global configuration.NotNull.
* @param value Java Data.NotNull.
* @param contentProperty Content property.Nullable.
* @param currentWriteHolder He would be {@link WriteSheetHolder} or {@link WriteTableHolder}.NotNull.
* @return Data to put into a Excel
* @throws Exception
* Exception.
* @throws Exception Exception.
*/
CellData convertToExcelData(T value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration)
throws Exception;
default CellData<?> convertToExcelData(T value, ExcelContentProperty contentProperty,
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;
import java.util.HashMap;
import java.util.Map;
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.
@ -12,7 +12,7 @@ import com.alibaba.excel.enums.CellDataTypeEnum;
*/
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 {
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());
}
public static String buildKey(Class clazz) {
public static String buildKey(Class<?> clazz) {
String className = clazz.getName();
String boxingClassName = BOXING_MAP.get(clazz.getName());
if (boxingClassName == null) {
@ -34,7 +34,11 @@ public class ConverterKeyBuild {
return boxingClassName;
}
public static String buildKey(Class clazz, CellDataTypeEnum cellDataTypeEnum) {
return buildKey(clazz) + "-" + cellDataTypeEnum.toString();
public static String buildKey(Class<?> clazz, CellDataTypeEnum cellDataTypeEnum) {
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;
import java.util.HashMap;
import java.util.Map;
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.ByteNumberConverter;
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.DateStringConverter;
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.StringStringConverter;
import com.alibaba.excel.converters.url.UrlImageConverter;
import com.alibaba.excel.util.MapUtils;
/**
* Load default handler
@ -45,8 +46,8 @@ import com.alibaba.excel.converters.url.UrlImageConverter;
* @author Jiaju Zhuang
*/
public class DefaultConverterLoader {
private static Map<String, Converter> defaultWriteConverter;
private static Map<String, Converter> allConverter;
private static Map<String, Converter<?>> defaultWriteConverter;
private static Map<String, Converter<?>> allConverter;
static {
initDefaultWriteConverter();
@ -54,7 +55,7 @@ public class DefaultConverterLoader {
}
private static void initAllConverter() {
allConverter = new HashMap<String, Converter>(64);
allConverter = MapUtils.newHashMapWithExpectedSize(40);
putAllConverter(new BigDecimalBooleanConverter());
putAllConverter(new BigDecimalNumberConverter());
putAllConverter(new BigDecimalStringConverter());
@ -97,11 +98,11 @@ public class DefaultConverterLoader {
}
private static void initDefaultWriteConverter() {
defaultWriteConverter = new HashMap<String, Converter>(32);
defaultWriteConverter = MapUtils.newHashMapWithExpectedSize(40);
putWriteConverter(new BigDecimalNumberConverter());
putWriteConverter(new BooleanBooleanConverter());
putWriteConverter(new ByteNumberConverter());
putWriteConverter(new DateStringConverter());
putWriteConverter(new DateDateConverter());
putWriteConverter(new DoubleNumberConverter());
putWriteConverter(new FloatNumberConverter());
putWriteConverter(new IntegerNumberConverter());
@ -113,6 +114,18 @@ public class DefaultConverterLoader {
putWriteConverter(new ByteArrayImageConverter());
putWriteConverter(new BoxingByteArrayImageConverter());
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
*/
public static Map<String, Converter> loadDefaultWriteConverter() {
public static Map<String, Converter<?>> loadDefaultWriteConverter() {
return defaultWriteConverter;
}
private static void putWriteConverter(Converter converter) {
private static void putWriteConverter(Converter<?> 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
*
* @return
*/
public static Map<String, Converter> loadDefaultReadConverter() {
public static Map<String, Converter<?>> loadDefaultReadConverter() {
return loadAllConverter();
}
@ -142,11 +160,11 @@ public class DefaultConverterLoader {
*
* @return
*/
public static Map<String, Converter> loadAllConverter() {
public static Map<String, Converter<?>> loadAllConverter() {
return allConverter;
}
private static void putAllConverter(Converter converter) {
private static void putAllConverter(Converter<?> converter) {
allConverter.put(ConverterKeyBuild.buildKey(converter.supportJavaTypeKey(), converter.supportExcelTypeKey()),
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> {
@Override
public Class supportJavaTypeKey() {
public Class<BigDecimal> supportJavaTypeKey() {
return BigDecimal.class;
}
@ -26,7 +26,7 @@ public class BigDecimalBooleanConverter implements Converter<BigDecimal> {
}
@Override
public BigDecimal convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
public BigDecimal convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
if (cellData.getBooleanValue()) {
return BigDecimal.ONE;
@ -35,12 +35,12 @@ public class BigDecimalBooleanConverter implements Converter<BigDecimal> {
}
@Override
public CellData convertToExcelData(BigDecimal value, ExcelContentProperty contentProperty,
public CellData<?> convertToExcelData(BigDecimal value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
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.GlobalConfiguration;
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
@ -16,7 +18,7 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty;
public class BigDecimalNumberConverter implements Converter<BigDecimal> {
@Override
public Class supportJavaTypeKey() {
public Class<BigDecimal> supportJavaTypeKey() {
return BigDecimal.class;
}
@ -26,14 +28,14 @@ public class BigDecimalNumberConverter implements Converter<BigDecimal> {
}
@Override
public BigDecimal convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
public BigDecimal convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
return cellData.getNumberValue();
}
@Override
public CellData convertToExcelData(BigDecimal value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
return new CellData(value);
public CellData<?> convertToExcelData(BigDecimal value, ExcelContentProperty contentProperty,
WriteHolder currentWriteHolder) {
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> {
@Override
public Class supportJavaTypeKey() {
public Class<BigDecimal> supportJavaTypeKey() {
return BigDecimal.class;
}
@ -28,14 +28,14 @@ public class BigDecimalStringConverter implements Converter<BigDecimal> {
}
@Override
public BigDecimal convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
public BigDecimal convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) throws ParseException {
return NumberUtils.parseBigDecimal(cellData.getStringValue(), contentProperty);
}
@Override
public CellData convertToExcelData(BigDecimal value, ExcelContentProperty contentProperty,
public CellData<?> convertToExcelData(BigDecimal value, ExcelContentProperty contentProperty,
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> {
@Override
public Class supportJavaTypeKey() {
public Class<?> supportJavaTypeKey() {
return Boolean.class;
}
@ -24,15 +24,15 @@ public class BooleanBooleanConverter implements Converter<Boolean> {
}
@Override
public Boolean convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
public Boolean convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
return cellData.getBooleanValue();
}
@Override
public CellData convertToExcelData(Boolean value, ExcelContentProperty contentProperty,
public CellData<?> convertToExcelData(Boolean value, ExcelContentProperty contentProperty,
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> {
@Override
public Class supportJavaTypeKey() {
public Class<?> supportJavaTypeKey() {
return Boolean.class;
}
@ -25,7 +25,7 @@ public class BooleanNumberConverter implements Converter<Boolean> {
}
@Override
public Boolean convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
public Boolean convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
if (BigDecimal.ONE.compareTo(cellData.getNumberValue()) == 0) {
return Boolean.TRUE;
@ -34,12 +34,12 @@ public class BooleanNumberConverter implements Converter<Boolean> {
}
@Override
public CellData convertToExcelData(Boolean value, ExcelContentProperty contentProperty,
public CellData<?> convertToExcelData(Boolean value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
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> {
@Override
public Class supportJavaTypeKey() {
public Class<?> supportJavaTypeKey() {
return Boolean.class;
}
@ -24,15 +24,15 @@ public class BooleanStringConverter implements Converter<Boolean> {
}
@Override
public Boolean convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
public Boolean convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
return Boolean.valueOf(cellData.getStringValue());
}
@Override
public CellData convertToExcelData(Boolean value, ExcelContentProperty contentProperty,
public CellData<?> convertToExcelData(Boolean value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
return new CellData(value.toString());
return new CellData<>(value.toString());
}
}

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

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

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

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

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;
@Override
public Class supportJavaTypeKey() {
public Class<?> supportJavaTypeKey() {
return Byte.class;
}
@ -26,7 +26,7 @@ public class ByteBooleanConverter implements Converter<Byte> {
}
@Override
public Byte convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
public Byte convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
if (cellData.getBooleanValue()) {
return ONE;
@ -35,12 +35,12 @@ public class ByteBooleanConverter implements Converter<Byte> {
}
@Override
public CellData convertToExcelData(Byte value, ExcelContentProperty contentProperty,
public CellData<?> convertToExcelData(Byte value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
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.GlobalConfiguration;
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
@ -16,7 +18,7 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty;
public class ByteNumberConverter implements Converter<Byte> {
@Override
public Class supportJavaTypeKey() {
public Class<?> supportJavaTypeKey() {
return Byte.class;
}
@ -26,15 +28,15 @@ public class ByteNumberConverter implements Converter<Byte> {
}
@Override
public Byte convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
public Byte convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
return cellData.getNumberValue().byteValue();
}
@Override
public CellData convertToExcelData(Byte value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
return new CellData(new BigDecimal(Byte.toString(value)));
public CellData<?> convertToExcelData(Byte value, ExcelContentProperty contentProperty,
WriteHolder currentWriteHolder) {
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> {
@Override
public Class supportJavaTypeKey() {
public Class<?> supportJavaTypeKey() {
return Byte.class;
}
@ -27,15 +27,15 @@ public class ByteStringConverter implements Converter<Byte> {
}
@Override
public Byte convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
public Byte convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) throws ParseException {
return NumberUtils.parseByte(cellData.getStringValue(), contentProperty);
}
@Override
public CellData convertToExcelData(Byte value, ExcelContentProperty contentProperty,
public CellData<?> convertToExcelData(Byte value, ExcelContentProperty contentProperty,
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> {
@Override
public Class supportJavaTypeKey() {
public Class<?> supportJavaTypeKey() {
return Date.class;
}
@ -29,7 +29,7 @@ public class DateNumberConverter implements Converter<Date> {
}
@Override
public Date convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
public Date convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
if (contentProperty == null || contentProperty.getDateTimeFormatProperty() == null) {
return DateUtil.getJavaDate(cellData.getNumberValue().doubleValue(),
@ -41,13 +41,13 @@ public class DateNumberConverter implements Converter<Date> {
}
@Override
public CellData convertToExcelData(Date value, ExcelContentProperty contentProperty,
public CellData<?> convertToExcelData(Date value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
if (contentProperty == null || contentProperty.getDateTimeFormatProperty() == null) {
return new CellData(
return new CellData<>(
BigDecimal.valueOf(DateUtil.getExcelDate(value, globalConfiguration.getUse1904windowing())));
} else {
return new CellData(BigDecimal.valueOf(
return new CellData<>(BigDecimal.valueOf(
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> {
@Override
public Class supportJavaTypeKey() {
public Class<?> supportJavaTypeKey() {
return Date.class;
}
@ -27,7 +27,7 @@ public class DateStringConverter implements Converter<Date> {
}
@Override
public Date convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
public Date convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) throws ParseException {
if (contentProperty == null || contentProperty.getDateTimeFormatProperty() == null) {
return DateUtils.parseDate(cellData.getStringValue(), null);
@ -38,12 +38,12 @@ public class DateStringConverter implements Converter<Date> {
}
@Override
public CellData convertToExcelData(Date value, ExcelContentProperty contentProperty,
public CellData<?> convertToExcelData(Date value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
if (contentProperty == null || contentProperty.getDateTimeFormatProperty() == null) {
return new CellData(DateUtils.format(value, null));
return new CellData<>(DateUtils.format(value, null));
} 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;
@Override
public Class supportJavaTypeKey() {
public Class<?> supportJavaTypeKey() {
return Double.class;
}
@ -26,7 +26,7 @@ public class DoubleBooleanConverter implements Converter<Double> {
}
@Override
public Double convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
public Double convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
if (cellData.getBooleanValue()) {
return ONE;
@ -35,12 +35,12 @@ public class DoubleBooleanConverter implements Converter<Double> {
}
@Override
public CellData convertToExcelData(Double value, ExcelContentProperty contentProperty,
public CellData<?> convertToExcelData(Double value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
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.GlobalConfiguration;
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
@ -16,7 +18,7 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty;
public class DoubleNumberConverter implements Converter<Double> {
@Override
public Class supportJavaTypeKey() {
public Class<?> supportJavaTypeKey() {
return Double.class;
}
@ -26,15 +28,14 @@ public class DoubleNumberConverter implements Converter<Double> {
}
@Override
public Double convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
public Double convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
return cellData.getNumberValue().doubleValue();
}
@Override
public CellData convertToExcelData(Double value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
return new CellData(BigDecimal.valueOf(value));
public CellData<?> convertToExcelData(Double value, ExcelContentProperty contentProperty,
WriteHolder currentWriteHolder) {
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> {
@Override
public Class supportJavaTypeKey() {
public Class<?> supportJavaTypeKey() {
return Double.class;
}
@ -27,14 +27,14 @@ public class DoubleStringConverter implements Converter<Double> {
}
@Override
public Double convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
public Double convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) throws ParseException {
return NumberUtils.parseDouble(cellData.getStringValue(), contentProperty);
}
@Override
public CellData convertToExcelData(Double value, ExcelContentProperty contentProperty,
public CellData<?> convertToExcelData(Double value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
return NumberUtils.formatToCellData(value, contentProperty);
return NumberUtils.formatToCellDataString(value, contentProperty);
}
}

6
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> {
@Override
public Class supportJavaTypeKey() {
public Class<?> supportJavaTypeKey() {
return File.class;
}
@ -27,13 +27,13 @@ public class FileImageConverter implements Converter<File> {
}
@Override
public File convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
public File convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
throw new UnsupportedOperationException("Cannot convert images to file");
}
@Override
public CellData convertToExcelData(File value, ExcelContentProperty contentProperty,
public CellData<?> convertToExcelData(File value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) throws IOException {
ImagePosition imagePosition = contentProperty.getField().getAnnotation(ImagePosition.class);
if (imagePosition != null) {

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;
@Override
public Class supportJavaTypeKey() {
public Class<?> supportJavaTypeKey() {
return Float.class;
}
@ -26,7 +26,7 @@ public class FloatBooleanConverter implements Converter<Float> {
}
@Override
public Float convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
public Float convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
if (cellData.getBooleanValue()) {
return ONE;
@ -35,12 +35,12 @@ public class FloatBooleanConverter implements Converter<Float> {
}
@Override
public CellData convertToExcelData(Float value, ExcelContentProperty contentProperty,
public CellData<?> convertToExcelData(Float value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
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;
import java.math.BigDecimal;
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.NumberUtils;
import com.alibaba.excel.write.metadata.holder.WriteHolder;
/**
* Float and number converter
@ -16,7 +16,7 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty;
public class FloatNumberConverter implements Converter<Float> {
@Override
public Class supportJavaTypeKey() {
public Class<?> supportJavaTypeKey() {
return Float.class;
}
@ -26,15 +26,14 @@ public class FloatNumberConverter implements Converter<Float> {
}
@Override
public Float convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
public Float convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
return cellData.getNumberValue().floatValue();
}
@Override
public CellData convertToExcelData(Float value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
return new CellData(new BigDecimal(Float.toString(value)));
public CellData<?> convertToExcelData(Float value, ExcelContentProperty contentProperty,
WriteHolder currentWriteHolder) {
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> {
@Override
public Class supportJavaTypeKey() {
public Class<?> supportJavaTypeKey() {
return Float.class;
}
@ -27,14 +27,14 @@ public class FloatStringConverter implements Converter<Float> {
}
@Override
public Float convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
public Float convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) throws ParseException {
return NumberUtils.parseFloat(cellData.getStringValue(), contentProperty);
}
@Override
public CellData convertToExcelData(Float value, ExcelContentProperty contentProperty,
public CellData<?> convertToExcelData(Float value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
return NumberUtils.formatToCellData(value, contentProperty);
return NumberUtils.formatToCellDataString(value, contentProperty);
}
}

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

@ -20,7 +20,7 @@ import com.alibaba.excel.util.IoUtils;
*/
public class InputStreamImageConverter implements Converter<InputStream> {
@Override
public Class supportJavaTypeKey() {
public Class<?> supportJavaTypeKey() {
return InputStream.class;
}
@ -30,13 +30,13 @@ public class InputStreamImageConverter implements Converter<InputStream> {
}
@Override
public InputStream convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
public InputStream convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
throw new UnsupportedOperationException("Cannot convert images to input stream");
}
@Override
public CellData convertToExcelData(InputStream value, ExcelContentProperty contentProperty,
public CellData<?> convertToExcelData(InputStream value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) throws IOException {
ImagePosition imagePosition = contentProperty.getField().getAnnotation(ImagePosition.class);
if (imagePosition != null) {

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;
@Override
public Class supportJavaTypeKey() {
public Class<?> supportJavaTypeKey() {
return Integer.class;
}
@ -26,7 +26,7 @@ public class IntegerBooleanConverter implements Converter<Integer> {
}
@Override
public Integer convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
public Integer convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
if (cellData.getBooleanValue()) {
return ONE;
@ -35,12 +35,12 @@ public class IntegerBooleanConverter implements Converter<Integer> {
}
@Override
public CellData convertToExcelData(Integer value, ExcelContentProperty contentProperty,
public CellData<?> convertToExcelData(Integer value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
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;
import java.math.BigDecimal;
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.NumberUtils;
import com.alibaba.excel.write.metadata.holder.WriteHolder;
/**
* Integer and number converter
@ -16,7 +16,7 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty;
public class IntegerNumberConverter implements Converter<Integer> {
@Override
public Class supportJavaTypeKey() {
public Class<?> supportJavaTypeKey() {
return Integer.class;
}
@ -26,15 +26,15 @@ public class IntegerNumberConverter implements Converter<Integer> {
}
@Override
public Integer convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
public Integer convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
return cellData.getNumberValue().intValue();
}
@Override
public CellData convertToExcelData(Integer value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
return new CellData(new BigDecimal(Integer.toString(value)));
public CellData<?> convertToExcelData(Integer value, ExcelContentProperty contentProperty,
WriteHolder currentWriteHolder) {
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> {
@Override
public Class supportJavaTypeKey() {
public Class<?> supportJavaTypeKey() {
return Integer.class;
}
@ -27,14 +27,14 @@ public class IntegerStringConverter implements Converter<Integer> {
}
@Override
public Integer convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
public Integer convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) throws ParseException {
return NumberUtils.parseInteger(cellData.getStringValue(), contentProperty);
}
@Override
public CellData convertToExcelData(Integer value, ExcelContentProperty contentProperty,
public CellData<?> convertToExcelData(Integer value, ExcelContentProperty contentProperty,
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;
@Override
public Class supportJavaTypeKey() {
public Class<Long> supportJavaTypeKey() {
return Long.class;
}
@ -26,7 +26,7 @@ public class LongBooleanConverter implements Converter<Long> {
}
@Override
public Long convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
public Long convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
if (cellData.getBooleanValue()) {
return ONE;
@ -35,12 +35,12 @@ public class LongBooleanConverter implements Converter<Long> {
}
@Override
public CellData convertToExcelData(Long value, ExcelContentProperty contentProperty,
public CellData<?> convertToExcelData(Long value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
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;
import java.math.BigDecimal;
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.NumberUtils;
import com.alibaba.excel.write.metadata.holder.WriteHolder;
/**
* Long and number converter
@ -16,7 +16,7 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty;
public class LongNumberConverter implements Converter<Long> {
@Override
public Class supportJavaTypeKey() {
public Class<Long> supportJavaTypeKey() {
return Long.class;
}
@ -26,15 +26,15 @@ public class LongNumberConverter implements Converter<Long> {
}
@Override
public Long convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
public Long convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
return cellData.getNumberValue().longValue();
}
@Override
public CellData convertToExcelData(Long value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
return new CellData(BigDecimal.valueOf(value));
public CellData<?> convertToExcelData(Long value, ExcelContentProperty contentProperty,
WriteHolder currentWriteHolder) {
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> {
@Override
public Class supportJavaTypeKey() {
public Class<Long> supportJavaTypeKey() {
return Long.class;
}
@ -27,14 +27,14 @@ public class LongStringConverter implements Converter<Long> {
}
@Override
public Long convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
public Long convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) throws ParseException {
return NumberUtils.parseLong(cellData.getStringValue(), contentProperty);
}
@Override
public CellData convertToExcelData(Long value, ExcelContentProperty contentProperty,
public CellData<?> convertToExcelData(Long value, ExcelContentProperty contentProperty,
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;
@Override
public Class supportJavaTypeKey() {
public Class<Short> supportJavaTypeKey() {
return Short.class;
}
@ -26,7 +26,7 @@ public class ShortBooleanConverter implements Converter<Short> {
}
@Override
public Short convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
public Short convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
if (cellData.getBooleanValue()) {
return ONE;
@ -35,12 +35,12 @@ public class ShortBooleanConverter implements Converter<Short> {
}
@Override
public CellData convertToExcelData(Short value, ExcelContentProperty contentProperty,
public CellData<?> convertToExcelData(Short value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
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.GlobalConfiguration;
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
@ -16,7 +18,7 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty;
public class ShortNumberConverter implements Converter<Short> {
@Override
public Class supportJavaTypeKey() {
public Class<Short> supportJavaTypeKey() {
return Short.class;
}
@ -26,15 +28,14 @@ public class ShortNumberConverter implements Converter<Short> {
}
@Override
public Short convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
public Short convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
return cellData.getNumberValue().shortValue();
}
@Override
public CellData convertToExcelData(Short value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
return new CellData(new BigDecimal(Short.toString(value)));
public CellData<?> convertToExcelData(Short value, ExcelContentProperty contentProperty,
WriteHolder currentWriteHolder) {
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> {
@Override
public Class supportJavaTypeKey() {
public Class<?> supportJavaTypeKey() {
return Short.class;
}
@ -27,14 +27,14 @@ public class ShortStringConverter implements Converter<Short> {
}
@Override
public Short convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
public Short convertToJavaData(CellData<?>cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) throws ParseException {
return NumberUtils.parseShort(cellData.getStringValue(), contentProperty);
}
@Override
public CellData convertToExcelData(Short value, ExcelContentProperty contentProperty,
public CellData<?>convertToExcelData(Short value, ExcelContentProperty contentProperty,
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> {
@Override
public Class supportJavaTypeKey() {
public Class<?> supportJavaTypeKey() {
return String.class;
}
@ -24,15 +24,15 @@ public class StringBooleanConverter implements Converter<String> {
}
@Override
public String convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
public String convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
return cellData.getBooleanValue().toString();
}
@Override
public CellData convertToExcelData(String value, ExcelContentProperty contentProperty,
public CellData<?> convertToExcelData(String value, ExcelContentProperty contentProperty,
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> {
@Override
public Class supportJavaTypeKey() {
public Class<String> supportJavaTypeKey() {
return String.class;
}
@ -23,15 +23,15 @@ public class StringErrorConverter implements Converter<String> {
}
@Override
public String convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
public String convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
return cellData.getStringValue();
}
@Override
public CellData convertToExcelData(String value, ExcelContentProperty contentProperty,
public CellData<?> convertToExcelData(String value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
return new CellData(CellDataTypeEnum.ERROR, value);
return new CellData<>(CellDataTypeEnum.ERROR, value);
}
}

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

@ -20,7 +20,7 @@ import com.alibaba.excel.util.IoUtils;
*/
public class StringImageConverter implements Converter<String> {
@Override
public Class supportJavaTypeKey() {
public Class<?> supportJavaTypeKey() {
return String.class;
}
@ -30,13 +30,13 @@ public class StringImageConverter implements Converter<String> {
}
@Override
public String convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
public String convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
throw new UnsupportedOperationException("Cannot convert images to string");
}
@Override
public CellData convertToExcelData(String value, ExcelContentProperty contentProperty,
public CellData<?> convertToExcelData(String value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) throws IOException {
ImagePosition imagePosition = contentProperty.getField().getAnnotation(ImagePosition.class);
if (imagePosition != null) {

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> {
@Override
public Class supportJavaTypeKey() {
public Class<?> supportJavaTypeKey() {
return String.class;
}
@ -32,7 +32,7 @@ public class StringNumberConverter implements Converter<String> {
}
@Override
public String convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
public String convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
// If there are "DateTimeFormat", read as date
if (contentProperty != null && contentProperty.getDateTimeFormatProperty() != null) {
@ -55,8 +55,8 @@ public class StringNumberConverter implements Converter<String> {
}
@Override
public CellData convertToExcelData(String value, ExcelContentProperty contentProperty,
public CellData<?> convertToExcelData(String value, ExcelContentProperty contentProperty,
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> {
@Override
public Class supportJavaTypeKey() {
public Class<?> supportJavaTypeKey() {
return String.class;
}
@ -23,15 +23,15 @@ public class StringStringConverter implements Converter<String> {
}
@Override
public String convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
public String convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
return cellData.getStringValue();
}
@Override
public CellData convertToExcelData(String value, ExcelContentProperty contentProperty,
public CellData<?> convertToExcelData(String value, ExcelContentProperty contentProperty,
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> {
@Override
public Class supportJavaTypeKey() {
public Class<?> supportJavaTypeKey() {
return URL.class;
}
@ -29,19 +29,19 @@ public class UrlImageConverter implements Converter<URL> {
}
@Override
public URL convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
public URL convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
throw new UnsupportedOperationException("Cannot convert images to url.");
}
@Override
public CellData convertToExcelData(URL value, ExcelContentProperty contentProperty,
public CellData<?> convertToExcelData(URL value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) throws IOException {
InputStream inputStream = null;
try {
inputStream = value.openStream();
byte[] bytes = IoUtils.toByteArray(inputStream);
return new CellData(bytes);
return new CellData<>(bytes);
} finally {
if (inputStream != null) {
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
*/
IMAGE;
IMAGE,
/**
* date.Support only when writing.
*/
DATE,
;
private static final Map<String, CellDataTypeEnum> TYPE_ROUTING_MAP = new HashMap<String, CellDataTypeEnum>(16);
static {
TYPE_ROUTING_MAP.put("s", 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> {
@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);
}

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.write.builder.ExcelWriterBuilder;
import lombok.Getter;
import lombok.Setter;
/**
* Data convert exception
*
* @author Jiaju Zhuang
*/
@Getter
@Setter
public class ExcelDataConvertException extends RuntimeException {
/**
* NotNull.
@ -21,7 +26,7 @@ public class ExcelDataConvertException extends RuntimeException {
/**
* NotNull.
*/
private CellData cellData;
private CellData<?> cellData;
/**
* 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;
}
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;
}
}

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

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

15
src/main/java/com/alibaba/excel/metadata/BasicParameter.java

@ -41,6 +41,13 @@ public class BasicParameter {
*/
private Locale locale;
/**
* Whether to use scientific Format.
*
* default is false
*/
private Boolean useScientificFormat;
public List<List<String>> getHead() {
return head;
}
@ -88,4 +95,12 @@ public class BasicParameter {
public void setLocale(Locale locale) {
this.locale = locale;
}
public Boolean getUseScientificFormat() {
return useScientificFormat;
}
public void setUseScientificFormat(Boolean useScientificFormat) {
this.useScientificFormat = useScientificFormat;
}
}

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

@ -2,10 +2,14 @@ package com.alibaba.excel.metadata;
import java.math.BigDecimal;
import com.alibaba.excel.annotation.write.style.ImagePosition;
import java.util.Date;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.property.ImagePositionProperty;
import com.alibaba.excel.util.StringUtils;
import lombok.Getter;
import lombok.Setter;
/**
* Excel internal cell data.
*
@ -13,6 +17,8 @@ import com.alibaba.excel.util.StringUtils;
*
* @author Jiaju Zhuang
*/
@Getter
@Setter
public class CellData<T> extends AbstractCell {
private CellDataTypeEnum type;
/**
@ -41,11 +47,15 @@ public class CellData<T> extends AbstractCell {
*/
private Boolean useImagePositionProperty = false;
/**
* 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;
/**
@ -66,6 +76,8 @@ public class CellData<T> extends AbstractCell {
this.dataFormat = other.dataFormat;
this.dataFormatString = other.dataFormatString;
this.data = other.data;
setRowIndex(other.getRowIndex());
setColumnIndex(other.getColumnIndex());
}
public CellData() {}
@ -137,108 +149,21 @@ public class CellData<T> extends AbstractCell {
this.formula = Boolean.FALSE;
}
public CellData(CellDataTypeEnum type) {
if (type == null) {
throw new IllegalArgumentException("Type can not be null");
public CellData(Date dateValue) {
if (dateValue == null) {
throw new IllegalArgumentException("DateValue can not be null");
}
this.type = type;
this.type = CellDataTypeEnum.DATE;
this.dateValue = dateValue;
this.formula = Boolean.FALSE;
}
public CellDataTypeEnum getType() {
return type;
}
public void setType(CellDataTypeEnum type) {
this.type = type;
}
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 ImagePositionProperty getImagePositionProperty() {
return imagePositionProperty;
}
public void setImagePositionProperty(ImagePositionProperty imagePositionProperty) {
this.imagePositionProperty = imagePositionProperty;
}
public Boolean getUseImagePositionProperty() {
return useImagePositionProperty;
}
public void setUseImagePositionProperty(Boolean useImagePositionProperty) {
this.useImagePositionProperty = useImagePositionProperty;
}
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 CellData(CellDataTypeEnum type) {
if (type == null) {
throw new IllegalArgumentException("Type can not be null");
}
public void setData(T data) {
this.data = data;
this.type = type;
}
/**
@ -269,37 +194,37 @@ public class CellData<T> extends AbstractCell {
}
}
public static CellData newEmptyInstance() {
public static CellData<?> newEmptyInstance() {
return newEmptyInstance(null, null);
}
public static CellData newEmptyInstance(Integer rowIndex, Integer columnIndex) {
CellData cellData = new CellData(CellDataTypeEnum.EMPTY);
public static CellData<?> newEmptyInstance(Integer rowIndex, Integer columnIndex) {
CellData<?> cellData = new CellData<>(CellDataTypeEnum.EMPTY);
cellData.setRowIndex(rowIndex);
cellData.setColumnIndex(columnIndex);
return cellData;
}
public static CellData newInstance(Boolean booleanValue) {
public static CellData<?> newInstance(Boolean booleanValue) {
return newInstance(booleanValue, null, null);
}
public static CellData newInstance(Boolean booleanValue, Integer rowIndex, Integer columnIndex) {
CellData cellData = new CellData(booleanValue);
public static CellData<?> newInstance(Boolean booleanValue, Integer rowIndex, Integer columnIndex) {
CellData<?> cellData = new CellData<>(booleanValue);
cellData.setRowIndex(rowIndex);
cellData.setColumnIndex(columnIndex);
return cellData;
}
public static CellData newInstance(String stringValue, Integer rowIndex, Integer columnIndex) {
CellData cellData = new CellData(stringValue);
public static CellData<?> newInstance(String stringValue, Integer rowIndex, Integer columnIndex) {
CellData<?> cellData = new CellData<>(stringValue);
cellData.setRowIndex(rowIndex);
cellData.setColumnIndex(columnIndex);
return cellData;
}
public static CellData newInstance(BigDecimal numberValue, Integer rowIndex, Integer columnIndex) {
CellData cellData = new CellData(numberValue);
public static CellData<?> newInstance(BigDecimal numberValue, Integer rowIndex, Integer columnIndex) {
CellData<?> cellData = new CellData<>(numberValue);
cellData.setRowIndex(rowIndex);
cellData.setColumnIndex(columnIndex);
return cellData;
@ -312,14 +237,28 @@ public class CellData<T> extends AbstractCell {
}
switch (type) {
case NUMBER:
if (numberValue == null) {
return StringUtils.EMPTY;
}
return numberValue.toString();
case BOOLEAN:
if (booleanValue == null) {
return StringUtils.EMPTY;
}
return booleanValue.toString();
case DIRECT_STRING:
case STRING:
case ERROR:
return stringValue;
case DATE:
if (dateValue == null) {
return StringUtils.EMPTY;
}
return dateValue.toString();
case IMAGE:
if (imageValue == null) {
return StringUtils.EMPTY;
}
return "image[" + imageValue.length + "]";
default:
return StringUtils.EMPTY;

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

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

14
src/main/java/com/alibaba/excel/metadata/GlobalConfiguration.java

@ -25,6 +25,12 @@ public class GlobalConfiguration {
* used when formatting dates and numbers.
*/
private Locale locale;
/**
* Whether to use scientific Format.
*
* default is false
*/
private Boolean useScientificFormat;
public Boolean getUse1904windowing() {
return use1904windowing;
@ -49,4 +55,12 @@ public class GlobalConfiguration {
public void setLocale(Locale locale) {
this.locale = locale;
}
public Boolean getUseScientificFormat() {
return useScientificFormat;
}
public void setUseScientificFormat(Boolean useScientificFormat) {
this.useScientificFormat = useScientificFormat;
}
}

119
src/main/java/com/alibaba/excel/metadata/DataFormatter.java → src/main/java/com/alibaba/excel/metadata/format/DataFormatter.java

@ -15,7 +15,7 @@
* can be found in svn at location root/projects/3rd-party/src
* ====================================================================
*/
package com.alibaba.excel.metadata;
package com.alibaba.excel.metadata.format;
import java.math.BigDecimal;
import java.math.RoundingMode;
@ -34,13 +34,15 @@ import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.poi.ss.format.CellFormat;
import org.apache.poi.ss.format.CellFormatResult;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.ExcelGeneralNumberFormat;
import org.apache.poi.ss.usermodel.ExcelStyleDateFormatter;
import org.apache.poi.ss.usermodel.FractionFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.util.DateUtils;
/**
@ -138,45 +140,92 @@ public class DataFormatter {
* @return
*/
private Boolean use1904windowing;
/**
* Creates a formatter using the {@link Locale#getDefault() default locale}.
* Whether to use scientific Format.
*
* default is false
*/
public DataFormatter() {
this(null, null);
}
private Boolean useScientificFormat;
/**
* Creates a formatter using the given locale.
*
*/
public DataFormatter(Locale locale, Boolean use1904windowing) {
this.use1904windowing = use1904windowing != null ? use1904windowing : Boolean.FALSE;
this.locale = locale != null ? locale : Locale.getDefault();
public DataFormatter(GlobalConfiguration globalConfiguration) {
if (globalConfiguration == null) {
this.use1904windowing = Boolean.FALSE;
this.locale = Locale.getDefault();
this.useScientificFormat = Boolean.FALSE;
} else {
this.use1904windowing =
globalConfiguration.getUse1904windowing() != null ? globalConfiguration.getUse1904windowing()
: Boolean.FALSE;
this.locale =
globalConfiguration.getLocale() != null ? globalConfiguration.getLocale() : Locale.getDefault();
this.useScientificFormat =
globalConfiguration.getUseScientificFormat() != null ? globalConfiguration.getUseScientificFormat()
: Boolean.FALSE;
}
this.dateSymbols = DateFormatSymbols.getInstance(this.locale);
this.decimalSymbols = DecimalFormatSymbols.getInstance(this.locale);
}
private Format getFormat(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.
// That however would require other code to be re factored.
// String[] formatBits = formatStrIn.split(";");
// int i = cellValue > 0.0 ? 0 : cellValue < 0.0 ? 1 : 2;
// String formatStr = (i < formatBits.length) ? formatBits[i] : formatBits[0];
String formatStr = dataFormatString;
// Excel supports 2+ part conditional data formats, eg positive/negative/zero,
// or (>1000),(>0),(0),(negative). As Java doesn't handle these kinds
// of different formats for different ranges, just +ve/-ve, we need to
// handle these ourselves in a special way.
// For now, if we detect 2+ parts, we call out to CellFormat to handle it
// TODO Going forward, we should really merge the logic between the two classes
if (formatStr.contains(";") &&
(formatStr.indexOf(';') != formatStr.lastIndexOf(';')
|| rangeConditionalPattern.matcher(formatStr).matches()
) ) {
try {
// Ask CellFormat to get a formatter for it
CellFormat cfmt = CellFormat.getInstance(locale, formatStr);
// CellFormat requires callers to identify date vs not, so do so
Object cellValueO = data;
if (DateUtil.isADateFormat(dataFormat, formatStr) &&
// don't try to handle Date value 0, let a 3 or 4-part format take care of it
data.doubleValue() != 0.0) {
cellValueO = DateUtil.getJavaDate(data, use1904windowing);
}
// Wrap and return (non-cachable - CellFormat does that)
return new CellFormatResultWrapper( cfmt.apply(cellValueO) );
} catch (Exception e) {
LOGGER.warn("Formatting failed for format {}, falling back",formatStr, e);
}
}
// See if we already have it cached
Format format = formats.get(dataFormatString);
Format format = formats.get(formatStr);
if (format != null) {
return format;
}
// Is it one of the special built in types, General or @?
if ("General".equalsIgnoreCase(dataFormatString) || "@".equals(dataFormatString)) {
if ("General".equalsIgnoreCase(formatStr) || "@".equals(formatStr)) {
format = getDefaultFormat();
addFormat(dataFormatString, format);
addFormat(formatStr, format);
return format;
}
// Build a formatter, and cache it
format = createFormat(dataFormat, dataFormatString);
addFormat(dataFormatString, format);
format = createFormat(dataFormat, formatStr);
addFormat(formatStr, format);
return format;
}
private Format createFormat(Integer dataFormat, String dataFormatString) {
private Format createFormat(Short dataFormat, String dataFormatString) {
String formatStr = dataFormatString;
Format format = checkSpecialConverter(formatStr);
@ -519,7 +568,7 @@ public class DataFormatter {
try {
return new InternalDecimalFormatWithScale(format, symbols);
} catch (IllegalArgumentException iae) {
LOGGER.debug("Formatting failed for format {}, falling back", formatStr, iae);
LOGGER.error("Formatting failed for format {}, falling back", formatStr, iae);
// the pattern could not be parsed correctly,
// so fall back to the default number format
return getDefaultFormat();
@ -532,7 +581,7 @@ public class DataFormatter {
return defaultNumFormat;
// otherwise use general format
}
defaultNumFormat = new ExcelGeneralNumberFormat(locale);
defaultNumFormat = new ExcelGeneralNumberFormat(locale, useScientificFormat);
return defaultNumFormat;
}
@ -558,8 +607,8 @@ public class DataFormatter {
* @param dataFormatString
* @return Formatted value
*/
private String getFormattedDateString(Double data, Integer dataFormat, String dataFormatString) {
Format dateFormat = getFormat(dataFormat, dataFormatString);
private String getFormattedDateString(Double data, Short dataFormat, String dataFormatString) {
Format dateFormat = getFormat(data, dataFormat, dataFormatString);
if (dateFormat instanceof ExcelStyleDateFormatter) {
// Hint about the raw excel value
((ExcelStyleDateFormatter)dateFormat).setDateToBeFormatted(data);
@ -581,8 +630,8 @@ public class DataFormatter {
* @param dataFormatString
* @return a formatted number string
*/
private String getFormattedNumberString(Double data, Integer dataFormat, String dataFormatString) {
Format numberFormat = getFormat(dataFormat, dataFormatString);
private String getFormattedNumberString(Double data, Short dataFormat, String dataFormatString) {
Format numberFormat = getFormat(data, dataFormat, dataFormatString);
String formatted = numberFormat.format(data);
return formatted.replaceFirst("E(\\d)", "E+$1"); // to match Excel's E-notation
}
@ -595,7 +644,7 @@ public class DataFormatter {
* @param dataFormatString
* @return
*/
public String format(Double data, Integer dataFormat, String dataFormatString) {
public String format(Double data, Short dataFormat, String dataFormatString) {
if (DateUtils.isADateFormat(dataFormat, dataFormatString)) {
return getFormattedDateString(data, dataFormat, dataFormatString);
}
@ -783,4 +832,26 @@ public class DataFormatter {
}
}
/**
* Workaround until we merge {@link org.apache.poi.ss.usermodel.DataFormatter} with {@link CellFormat}. Constant, non-cachable wrapper around a
* {@link CellFormatResult}
*/
private final class CellFormatResultWrapper extends Format {
private final CellFormatResult result;
private CellFormatResultWrapper(CellFormatResult result) {
this.result = result;
}
@Override
public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) {
return toAppendTo.append(result.text.trim());
}
@Override
public Object parseObject(String source, ParsePosition pos) {
return null; // Not supported
}
}
}

81
src/main/java/com/alibaba/excel/metadata/format/ExcelGeneralNumberFormat.java

@ -0,0 +1,81 @@
package com.alibaba.excel.metadata.format;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.FieldPosition;
import java.text.Format;
import java.text.ParsePosition;
import java.util.Locale;
import org.apache.poi.ss.usermodel.DataFormatter;
/**
* Written with reference to {@link org.apache.poi.ss.usermodel.ExcelGeneralNumberFormat }.
* <p>
* Supported Do not use scientific notation.
*
* @author JiaJu Zhuang
**/
public class ExcelGeneralNumberFormat extends Format {
private static final long serialVersionUID = 1L;
private static final MathContext TO_10_SF = new MathContext(10, RoundingMode.HALF_UP);
private final DecimalFormatSymbols decimalSymbols;
private final DecimalFormat integerFormat;
private final DecimalFormat decimalFormat;
private final DecimalFormat scientificFormat;
public ExcelGeneralNumberFormat(final Locale locale, final boolean useScientificFormat) {
decimalSymbols = DecimalFormatSymbols.getInstance(locale);
// Supported Do not use scientific notation.
if (useScientificFormat) {
scientificFormat = new DecimalFormat("0.#####E0", decimalSymbols);
} else {
scientificFormat = new DecimalFormat("#", decimalSymbols);
}
org.apache.poi.ss.usermodel.DataFormatter.setExcelStyleRoundingMode(scientificFormat);
integerFormat = new DecimalFormat("#", decimalSymbols);
org.apache.poi.ss.usermodel.DataFormatter.setExcelStyleRoundingMode(integerFormat);
decimalFormat = new DecimalFormat("#.##########", decimalSymbols);
DataFormatter.setExcelStyleRoundingMode(decimalFormat);
}
@Override
public StringBuffer format(Object number, StringBuffer toAppendTo, FieldPosition pos) {
final double value;
if (number instanceof Number) {
value = ((Number) number).doubleValue();
if (Double.isInfinite(value) || Double.isNaN(value)) {
return integerFormat.format(number, toAppendTo, pos);
}
} else {
// testBug54786 gets here with a date, so retain previous behaviour
return integerFormat.format(number, toAppendTo, pos);
}
final double abs = Math.abs(value);
if (abs >= 1E11 || (abs <= 1E-10 && abs > 0)) {
return scientificFormat.format(number, toAppendTo, pos);
} else if (Math.floor(value) == value || abs >= 1E10) {
// integer, or integer portion uses all 11 allowed digits
return integerFormat.format(number, toAppendTo, pos);
}
// Non-integers of non-scientific magnitude are formatted as "up to 11
// numeric characters, with the decimal point counting as a numeric
// character". We know there is a decimal point, so limit to 10 digits.
// https://support.microsoft.com/en-us/kb/65903
final double rounded = new BigDecimal(value).round(TO_10_SF).doubleValue();
return decimalFormat.format(rounded, toAppendTo, pos);
}
@Override
public Object parseObject(String source, ParsePosition pos) {
throw new UnsupportedOperationException();
}
}

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

@ -10,6 +10,7 @@ import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -119,116 +120,31 @@ public class ExcelHeadProperty {
return;
}
// Declared fields
List<Field> defaultFieldList = new ArrayList<Field>();
Map<Integer, Field> customFieldMap = new TreeMap<Integer, Field>();
ClassUtils.declaredFields(headClazz, defaultFieldList, customFieldMap, ignoreMap, convertAllField);
Map<Integer, Field> sortedAllFiledMap = new TreeMap<Integer, Field>();
Map<Integer, Field> indexFiledMap = new TreeMap<Integer, Field>();
List<Map.Entry<Field, Boolean>> exportFieldBoolPairsList = new ArrayList<Map.Entry<Field, Boolean>>();
int index = 0;
while (customFieldMap.containsKey(index)) {
Field field = customFieldMap.get(index);
Map.Entry<Field, Boolean> fieldBooleanPair =
new AbstractMap.SimpleEntry<Field, Boolean>(field, Boolean.TRUE);
exportFieldBoolPairsList.add(fieldBooleanPair);
index++;
}
for (Field field : defaultFieldList) {
Map.Entry<Field, Boolean> fieldBoolPair = new AbstractMap.SimpleEntry<Field, Boolean>(field, Boolean.FALSE);
exportFieldBoolPairsList.add(fieldBoolPair);
}
sortExportColumnFields(holder, exportFieldBoolPairsList);
initColumnProperties(holder, exportFieldBoolPairsList);
boolean needIgnore = (holder instanceof AbstractWriteHolder) && (
!CollectionUtils.isEmpty(((AbstractWriteHolder) holder).getExcludeColumnFiledNames()) || !CollectionUtils
.isEmpty(((AbstractWriteHolder) holder).getExcludeColumnIndexes()) || !CollectionUtils
.isEmpty(((AbstractWriteHolder) holder).getIncludeColumnFiledNames()) || !CollectionUtils
.isEmpty(((AbstractWriteHolder) holder).getIncludeColumnIndexes()));
ClassUtils.declaredFields(headClazz, sortedAllFiledMap, indexFiledMap, ignoreMap, convertAllFiled, needIgnore,
holder);
for (Map.Entry<Integer, Field> entry : customFieldMap.entrySet()) {
initOneColumnProperty(holder, entry.getKey(), entry.getValue(), Boolean.TRUE);
}
headKind = HeadKindEnum.CLASS;
}
/**
* Give the field and flag pair list and arrange them in the specified order according to the user's settings. The
* field is what the user want to export to excel, the flag indicates whether the order of the field in excel is
* specified.
*
* @param holder
* Write holder which keeps the parameters of a sheet.
* @param exportFieldBoolPairList
* Keep all the fields and the flag(which indicate whether the field order is specified) of the head
* class except the ignored. It will be modified after this function is called.
*/
private void sortExportColumnFields(Holder holder, List<Map.Entry<Field, Boolean>> exportFieldBoolPairList) {
if (holder instanceof AbstractWriteHolder) {
Collection<String> includeColumnFieldNames = ((AbstractWriteHolder)holder).getIncludeColumnFieldNames();
if (includeColumnFieldNames != null) {
Map<String, Map.Entry<Field, Boolean>> exportFieldMap =
new TreeMap<String, Map.Entry<Field, Boolean>>();
List<String> includeColumnFieldNameList = new ArrayList<String>(includeColumnFieldNames);
for (Map.Entry<Field, Boolean> fieldBoolPair : exportFieldBoolPairList) {
if (includeColumnFieldNameList.contains(fieldBoolPair.getKey().getName())) {
exportFieldMap.put(fieldBoolPair.getKey().getName(), fieldBoolPair);
}
}
exportFieldBoolPairList.clear();
for (String fieldName : includeColumnFieldNameList) {
exportFieldBoolPairList.add(exportFieldMap.get(fieldName));
}
return;
}
Collection<Integer> includeColumnIndexes = ((AbstractWriteHolder)holder).getIncludeColumnIndexes();
if (includeColumnIndexes != null) {
List<Map.Entry<Field, Boolean>> tempFieldsList = new ArrayList<Map.Entry<Field, Boolean>>();
for (Integer includeColumnIndex : includeColumnIndexes) {
tempFieldsList.add(exportFieldBoolPairList.get(includeColumnIndex));
}
exportFieldBoolPairList.clear();
exportFieldBoolPairList.addAll(tempFieldsList);
return;
}
int index = 0;
for (Map.Entry<Field, Boolean> fieldBoolPair : exportFieldBoolPairList) {
if (((AbstractWriteHolder)holder).ignore(fieldBoolPair.getKey().getName(), index)) {
exportFieldBoolPairList.remove(fieldBoolPair);
}
index++;
}
}
}
/**
* Initialize column properties.
*
* @param holder
* Write holder which keeps the parameters of a sheet.
* @param exportFieldBoolPairList
* Keep the fields which will be exported to excel and the flag which indicate whether the field order in
* excel is specified.
*/
private void initColumnProperties(Holder holder, List<Map.Entry<Field, Boolean>> exportFieldBoolPairList) {
int index = 0;
for (Map.Entry<Field, Boolean> fieldBoolPair : exportFieldBoolPairList) {
initOneColumnProperty(holder, index, fieldBoolPair.getKey(), fieldBoolPair.getValue());
index++;
for (Map.Entry<Integer, Field> entry : sortedAllFiledMap.entrySet()) {
initOneColumnProperty(entry.getKey(), entry.getValue(), indexFiledMap.containsKey(entry.getKey()));
}
}
/**
* Initialization column property
*
* @param holder
* @param index
* @param field
* @param forceIndex
* @return Ignore current field
*/
private boolean initOneColumnProperty(Holder holder, int index, Field field, Boolean forceIndex) {
if (holder instanceof AbstractWriteHolder) {
if (((AbstractWriteHolder)holder).ignore(field.getName(), index)) {
return true;
}
}
private void initOneColumnProperty(int index, Field field, Boolean forceIndex) {
ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
List<String> tmpHeadList = new ArrayList<String>();
boolean notForceName = excelProperty == null || excelProperty.value().length <= 0
@ -264,7 +180,6 @@ public class ExcelHeadProperty {
headMap.put(index, head);
contentPropertyMap.put(index, excelContentProperty);
fieldNameContentPropertyMap.put(field.getName(), excelContentProperty);
return false;
}
public Class getHeadClazz() {

13
src/main/java/com/alibaba/excel/read/builder/AbstractExcelReaderParameterBuilder.java

@ -31,6 +31,19 @@ public abstract class AbstractExcelReaderParameterBuilder<T extends AbstractExce
return self();
}
/**
* Whether to use scientific Format.
*
* default is false
*
* @param useScientificFormat
* @return
*/
public T useScientificFormat(Boolean useScientificFormat) {
parameter().setUseScientificFormat(useScientificFormat);
return self();
}
/**
* Custom type listener run after default
*

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.Head;
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.util.ConverterUtils;
import com.alibaba.excel.util.FieldUtils;
import net.sf.cglib.beans.BeanMap;
@ -25,28 +26,28 @@ import net.sf.cglib.beans.BeanMap;
*
* @author jipengfei
*/
public class ModelBuildEventListener extends AbstractIgnoreExceptionReadListener<Map<Integer, CellData>> {
public class ModelBuildEventListener extends AbstractIgnoreExceptionReadListener<Map<Integer, CellData<?>>> {
@Override
public void invokeHead(Map<Integer, CellData> cellDataMap, AnalysisContext context) {}
public void invokeHead(Map<Integer, CellData<?>> cellDataMap, AnalysisContext context) {}
@Override
public void invoke(Map<Integer, CellData> cellDataMap, AnalysisContext context) {
ReadHolder currentReadHolder = context.currentReadHolder();
if (HeadKindEnum.CLASS.equals(currentReadHolder.excelReadHeadProperty().getHeadKind())) {
public void invoke(Map<Integer, CellData<?>> cellDataMap, AnalysisContext context) {
ReadSheetHolder readSheetHolder = context.readSheetHolder();
if (HeadKindEnum.CLASS.equals(readSheetHolder.excelReadHeadProperty().getHeadKind())) {
context.readRowHolder()
.setCurrentRowAnalysisResult(buildUserModel(cellDataMap, currentReadHolder, context));
.setCurrentRowAnalysisResult(buildUserModel(cellDataMap, readSheetHolder, context));
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) {
int index = 0;
if (context.readWorkbookHolder().getDefaultReturnMap()) {
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();
CellData cellData = entry.getValue();
while (index < key) {
@ -59,10 +60,10 @@ public class ModelBuildEventListener extends AbstractIgnoreExceptionReadListener
continue;
}
map.put(key,
(String)ConverterUtils.convertToJavaObject(cellData, null, null, currentReadHolder.converterMap(),
currentReadHolder.globalConfiguration(), context.readRowHolder().getRowIndex(), key));
(String)ConverterUtils.convertToJavaObject(cellData, null, null, readSheetHolder.converterMap(),
readSheetHolder, context.readRowHolder().getRowIndex(), key));
}
int headSize = currentReadHolder.excelReadHeadProperty().getHeadMap().size();
int headSize = readSheetHolder.excelReadHeadProperty().getHeadMap().size();
while (index < headSize) {
map.put(index, null);
index++;
@ -70,10 +71,10 @@ public class ModelBuildEventListener extends AbstractIgnoreExceptionReadListener
return map;
} else {
// Compatible with the old code the old code returns a list
List<String> list = new ArrayList<String>();
for (Map.Entry<Integer, CellData> entry : cellDataMap.entrySet()) {
List<String> list = new ArrayList<>();
for (Map.Entry<Integer, CellData<?>> entry : cellDataMap.entrySet()) {
Integer key = entry.getKey();
CellData cellData = entry.getValue();
CellData<?> cellData = entry.getValue();
while (index < key) {
list.add(null);
index++;
@ -84,10 +85,10 @@ public class ModelBuildEventListener extends AbstractIgnoreExceptionReadListener
continue;
}
list.add(
(String)ConverterUtils.convertToJavaObject(cellData, null, null, currentReadHolder.converterMap(),
currentReadHolder.globalConfiguration(), context.readRowHolder().getRowIndex(), key));
(String)ConverterUtils.convertToJavaObject(cellData, null, null, readSheetHolder.converterMap(),
readSheetHolder, context.readRowHolder().getRowIndex(), key));
}
int headSize = currentReadHolder.excelReadHeadProperty().getHeadMap().size();
int headSize = readSheetHolder.excelReadHeadProperty().getHeadMap().size();
while (index < headSize) {
list.add(null);
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) {
ExcelReadHeadProperty excelReadHeadProperty = currentReadHolder.excelReadHeadProperty();
ExcelReadHeadProperty excelReadHeadProperty = readSheetHolder.excelReadHeadProperty();
Object resultModel;
try {
resultModel = excelReadHeadProperty.getHeadClazz().newInstance();
} catch (Exception e) {
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);
}
Map<Integer, Head> headMap = excelReadHeadProperty.getHeadMap();
@ -115,16 +116,16 @@ public class ModelBuildEventListener extends AbstractIgnoreExceptionReadListener
if (!cellDataMap.containsKey(index)) {
continue;
}
CellData cellData = cellDataMap.get(index);
CellData<?> cellData = cellDataMap.get(index);
if (cellData.getType() == CellDataTypeEnum.EMPTY) {
continue;
}
ExcelContentProperty excelContentProperty = contentPropertyMap.get(index);
Object value = ConverterUtils.convertToJavaObject(cellData, excelContentProperty.getField(),
excelContentProperty, currentReadHolder.converterMap(), currentReadHolder.globalConfiguration(),
excelContentProperty, readSheetHolder.converterMap(), readSheetHolder,
context.readRowHolder().getRowIndex(), index);
if (value != null) {
map.put(excelContentProperty.getField().getName(), value);
map.put(FieldUtils.resolveCglibFieldName(excelContentProperty.getField()), value);
}
}
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 context
*/
void invokeHead(Map<Integer, CellData> headMap, AnalysisContext context);
void invokeHead(Map<Integer, CellData<?>> headMap, AnalysisContext context);
/**
* When analysis one row trigger invoke function.

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

@ -1,12 +1,8 @@
package com.alibaba.excel.read.metadata.holder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.converters.ConverterKeyBuild;
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.ReadWorkbook;
import com.alibaba.excel.read.metadata.property.ExcelReadHeadProperty;
import com.alibaba.excel.util.ListUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Read Holder
@ -24,8 +24,6 @@ import com.alibaba.excel.read.metadata.property.ExcelReadHeadProperty;
* @author Jiaju Zhuang
*/
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.
*
@ -56,6 +54,17 @@ public abstract class AbstractReadHolder extends AbstractHolder implements ReadH
getGlobalConfiguration().setUse1904windowing(readBasicParameter.getUse1904windowing());
}
if (readBasicParameter.getUseScientificFormat() == null) {
if (parentAbstractReadHolder == null) {
getGlobalConfiguration().setUseScientificFormat(Boolean.FALSE);
} else {
getGlobalConfiguration()
.setUseScientificFormat(parentAbstractReadHolder.getGlobalConfiguration().getUseScientificFormat());
}
} else {
getGlobalConfiguration().setUseScientificFormat(readBasicParameter.getUseScientificFormat());
}
// Initialization property
this.excelReadHeadProperty = new ExcelReadHeadProperty(this, getClazz(), getHead(), convertAllFiled);
if (readBasicParameter.getHeadRowNumber() == null) {
@ -73,9 +82,9 @@ public abstract class AbstractReadHolder extends AbstractHolder implements ReadH
}
if (parentAbstractReadHolder == null) {
this.readListenerList = new ArrayList<ReadListener>();
this.readListenerList = ListUtils.newArrayList();
} else {
this.readListenerList = new ArrayList<ReadListener>(parentAbstractReadHolder.getReadListenerList());
this.readListenerList = ListUtils.newArrayList(parentAbstractReadHolder.getReadListenerList());
}
if (HolderEnum.WORKBOOK.equals(holderType())) {
Boolean useDefaultListener = ((ReadWorkbook)readBasicParameter).getUseDefaultListener();
@ -91,11 +100,11 @@ public abstract class AbstractReadHolder extends AbstractHolder implements ReadH
if (parentAbstractReadHolder == null) {
setConverterMap(DefaultConverterLoader.loadDefaultReadConverter());
} else {
setConverterMap(new HashMap<String, Converter>(parentAbstractReadHolder.getConverterMap()));
setConverterMap(new HashMap<>(parentAbstractReadHolder.getConverterMap()));
}
if (readBasicParameter.getCustomConverterList() != null
&& !readBasicParameter.getCustomConverterList().isEmpty()) {
for (Converter converter : readBasicParameter.getCustomConverterList()) {
for (Converter<?> converter : readBasicParameter.getCustomConverterList()) {
getConverterMap().put(
ConverterKeyBuild.buildKey(converter.supportJavaTypeKey(), converter.supportExcelTypeKey()),
converter);

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

@ -15,6 +15,7 @@ import com.alibaba.excel.read.metadata.ReadSheet;
* @author Jiaju Zhuang
*/
public class ReadSheetHolder extends AbstractReadHolder {
/**
* current param
*/
@ -50,7 +51,7 @@ public class ReadSheetHolder extends AbstractReadHolder {
/**
* Current CellData
*/
private CellData tempCellData;
private CellData<?> tempCellData;
public ReadSheetHolder(ReadSheet readSheet, ReadWorkbookHolder readWorkbookHolder) {
super(readSheet, readWorkbookHolder, readWorkbookHolder.getReadWorkbook().getConvertAllFiled());
@ -59,6 +60,7 @@ public class ReadSheetHolder extends AbstractReadHolder {
this.sheetNo = readSheet.getSheetNo();
this.sheetName = readSheet.getSheetName();
this.cellMap = new LinkedHashMap<Integer, Cell>();
this.rowIndex = -1;
}
public ReadSheet getReadSheet() {
@ -133,11 +135,11 @@ public class ReadSheetHolder extends AbstractReadHolder {
this.rowIndex = rowIndex;
}
public CellData getTempCellData() {
public CellData<?> getTempCellData() {
return tempCellData;
}
public void setTempCellData(CellData tempCellData) {
public void setTempCellData(CellData<?> tempCellData) {
this.tempCellData = tempCellData;
}

12
src/main/java/com/alibaba/excel/read/metadata/holder/xls/XlsReadSheetHolder.java

@ -18,10 +18,6 @@ public class XlsReadSheetHolder extends ReadSheetHolder {
* Row type.Temporary storage, last set in <code>ReadRowHolder</code>.
*/
private RowTypeEnum tempRowType;
/**
* Ignore record.
*/
private Boolean ignoreRecord;
/**
* Temp object index.
*/
@ -33,7 +29,6 @@ public class XlsReadSheetHolder extends ReadSheetHolder {
public XlsReadSheetHolder(ReadSheet readSheet, ReadWorkbookHolder readWorkbookHolder) {
super(readSheet, readWorkbookHolder);
ignoreRecord = Boolean.FALSE;
tempRowType = RowTypeEnum.EMPTY;
objectCacheMap = new HashMap<Integer, String>(16);
}
@ -46,13 +41,6 @@ public class XlsReadSheetHolder extends ReadSheetHolder {
this.tempRowType = tempRowType;
}
public Boolean getIgnoreRecord() {
return ignoreRecord;
}
public void setIgnoreRecord(Boolean ignoreRecord) {
this.ignoreRecord = ignoreRecord;
}
public Integer getTempObjectIndex() {
return tempObjectIndex;

13
src/main/java/com/alibaba/excel/read/metadata/holder/xls/XlsReadWorkbookHolder.java

@ -42,6 +42,10 @@ public class XlsReadWorkbookHolder extends ReadWorkbookHolder {
* Sheet Index
*/
private Integer readSheetIndex;
/**
* Ignore record.
*/
private Boolean ignoreRecord;
public XlsReadWorkbookHolder(ReadWorkbook readWorkbook) {
super(readWorkbook);
@ -51,6 +55,7 @@ public class XlsReadWorkbookHolder extends ReadWorkbookHolder {
if (getGlobalConfiguration().getUse1904windowing() == null) {
getGlobalConfiguration().setUse1904windowing(Boolean.FALSE);
}
ignoreRecord = Boolean.FALSE;
}
public POIFSFileSystem getPoifsFileSystem() {
@ -100,4 +105,12 @@ public class XlsReadWorkbookHolder extends ReadWorkbookHolder {
public void setReadSheetIndex(Integer readSheetIndex) {
this.readSheetIndex = readSheetIndex;
}
public Boolean getIgnoreRecord() {
return ignoreRecord;
}
public void setIgnoreRecord(Boolean ignoreRecord) {
this.ignoreRecord = ignoreRecord;
}
}

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) {
ReadRowHolder readRowHolder = analysisContext.readRowHolder();
Map<Integer, CellData> cellDataMap = (Map)readRowHolder.getCellMap();
Map<Integer, CellData<?>> cellDataMap = (Map)readRowHolder.getCellMap();
readRowHolder.setCurrentRowAnalysisResult(cellDataMap);
int rowIndex = readRowHolder.getRowIndex();
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())) {
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);
}
}

192
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.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
@ -14,8 +16,12 @@ import java.util.concurrent.ConcurrentHashMap;
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.event.Handler;
import com.alibaba.excel.exception.ExcelCommonException;
import com.alibaba.excel.metadata.BaseRowModel;
import com.alibaba.excel.metadata.Holder;
import com.alibaba.excel.write.handler.WriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteHolder;
/**
* Class utils
@ -23,26 +29,54 @@ import com.alibaba.excel.metadata.BaseRowModel;
* @author Jiaju Zhuang
**/
public class ClassUtils {
private static final Map<Class, SoftReference<FieldCache>> FIELD_CACHE =
new ConcurrentHashMap<Class, SoftReference<FieldCache>>();
public static void declaredFields(Class clazz, List<Field> defaultFieldList, Map<Integer, Field> customFiledMap,
Map<String, Field> ignoreMap, Boolean convertAllFiled) {
public static void declaredFields(Class clazz, Map<Integer, Field> sortedAllFiledMap,
Map<Integer, Field> indexFiledMap, Map<String, Field> ignoreMap, Boolean convertAllFiled,
Boolean needIgnore, Holder holder) {
FieldCache fieldCache = getFieldCache(clazz, convertAllFiled);
if (fieldCache != null) {
defaultFieldList.addAll(fieldCache.getDefaultFieldList());
customFiledMap.putAll(fieldCache.getCustomFiledMap());
if (fieldCache == null) {
return;
}
if (ignoreMap != null) {
ignoreMap.putAll(fieldCache.getIgnoreMap());
}
Map<Integer, Field> tempIndexFildMap = indexFiledMap;
if (tempIndexFildMap == null) {
tempIndexFildMap = new TreeMap<Integer, Field>();
}
tempIndexFildMap.putAll(fieldCache.getIndexFiledMap());
public static void declaredFields(Class clazz, List<Field> fieldList, Boolean convertAllFiled) {
FieldCache fieldCache = getFieldCache(clazz, convertAllFiled);
if (fieldCache != null) {
fieldList.addAll(fieldCache.getAllFieldList());
if (!needIgnore) {
sortedAllFiledMap.putAll(fieldCache.getSortedAllFiledMap());
return;
}
int index = 0;
for (Map.Entry<Integer, Field> entry : fieldCache.getSortedAllFiledMap().entrySet()) {
Field field = entry.getValue();
if (((WriteHolder) holder).ignore(entry.getValue().getName(), entry.getKey())) {
if (ignoreMap != null) {
ignoreMap.put(field.getName(), field);
}
while (tempIndexFildMap.containsKey(index)) {
tempIndexFildMap.remove(index);
index++;
}
} else {
sortedAllFiledMap.put(index, field);
index++;
}
}
}
public static void declaredFields(Class clazz, Map<Integer, Field> sortedAllFiledMap, Boolean convertAllFiled,
Boolean needIgnore, WriteHolder writeHolder) {
declaredFields(clazz, sortedAllFiledMap, null, null, convertAllFiled, needIgnore, writeHolder);
}
private static FieldCache getFieldCache(Class clazz, Boolean convertAllFiled) {
if (clazz == null) {
return null;
@ -72,79 +106,155 @@ public class ClassUtils {
tempClass = tempClass.getSuperclass();
}
// Screening of field
List<Field> defaultFieldList = new ArrayList<Field>();
Map<Integer, Field> customFiledMap = new TreeMap<Integer, Field>();
List<Field> allFieldList = new ArrayList<Field>();
Map<Integer, List<Field>> orderFiledMap = new TreeMap<Integer, List<Field>>();
Map<Integer, Field> indexFiledMap = new TreeMap<Integer, Field>();
Map<String, Field> ignoreMap = new HashMap<String, Field>(16);
ExcelIgnoreUnannotated excelIgnoreUnannotated =
(ExcelIgnoreUnannotated) clazz.getAnnotation(ExcelIgnoreUnannotated.class);
for (Field field : tempFieldList) {
declaredOneField(field, orderFiledMap, indexFiledMap, ignoreMap, excelIgnoreUnannotated, convertAllFiled);
}
FIELD_CACHE.put(clazz, new SoftReference<FieldCache>(
new FieldCache(buildSortedAllFiledMap(orderFiledMap, indexFiledMap), indexFiledMap, ignoreMap)));
}
private static Map<Integer, Field> buildSortedAllFiledMap(Map<Integer, List<Field>> orderFiledMap,
Map<Integer, Field> indexFiledMap) {
Map<Integer, Field> sortedAllFiledMap = new HashMap<Integer, Field>(
(orderFiledMap.size() + indexFiledMap.size()) * 4 / 3 + 1);
Map<Integer, Field> tempIndexFiledMap = new HashMap<Integer, Field>(indexFiledMap);
int index = 0;
for (List<Field> fieldList : orderFiledMap.values()) {
for (Field field : fieldList) {
while (tempIndexFiledMap.containsKey(index)) {
sortedAllFiledMap.put(index, tempIndexFiledMap.get(index));
tempIndexFiledMap.remove(index);
index++;
}
sortedAllFiledMap.put(index, field);
index++;
}
}
sortedAllFiledMap.putAll(tempIndexFiledMap);
return sortedAllFiledMap;
}
private static void declaredOneField(Field field, Map<Integer, List<Field>> orderFiledMap,
Map<Integer, Field> indexFiledMap, Map<String, Field> ignoreMap, ExcelIgnoreUnannotated excelIgnoreUnannotated,
Boolean convertAllFiled) {
ExcelIgnore excelIgnore = field.getAnnotation(ExcelIgnore.class);
if (excelIgnore != null) {
ignoreMap.put(field.getName(), field);
continue;
return;
}
ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
boolean noExcelProperty = excelProperty == null
&& ((convertAllFiled != null && !convertAllFiled) || excelIgnoreUnannotated != null);
if (noExcelProperty) {
ignoreMap.put(field.getName(), field);
continue;
return;
}
boolean isStaticFinalOrTransient =
(Modifier.isStatic(field.getModifiers()) && Modifier.isFinal(field.getModifiers()))
|| Modifier.isTransient(field.getModifiers());
if (excelProperty == null && isStaticFinalOrTransient) {
ignoreMap.put(field.getName(), field);
continue;
return;
}
if (excelProperty == null || excelProperty.index() < 0) {
defaultFieldList.add(field);
allFieldList.add(field);
continue;
}
if (customFiledMap.containsKey(excelProperty.index())) {
throw new ExcelCommonException("The index of '" + customFiledMap.get(excelProperty.index()).getName()
if (excelProperty != null && excelProperty.index() >= 0) {
if (indexFiledMap.containsKey(excelProperty.index())) {
throw new ExcelCommonException("The index of '" + indexFiledMap.get(excelProperty.index()).getName()
+ "' and '" + field.getName() + "' must be inconsistent");
}
customFiledMap.put(excelProperty.index(), field);
allFieldList.add(field);
indexFiledMap.put(excelProperty.index(), field);
return;
}
FIELD_CACHE.put(clazz,
new SoftReference<FieldCache>(new FieldCache(defaultFieldList, customFiledMap, allFieldList, ignoreMap)));
int order = Integer.MAX_VALUE;
if (excelProperty != null) {
order = excelProperty.order();
}
List<Field> orderFiledList = orderFiledMap.get(order);
if (orderFiledList == null) {
orderFiledList = new ArrayList<Field>();
orderFiledMap.put(order, orderFiledList);
}
orderFiledList.add(field);
}
private static class FieldCache {
private List<Field> defaultFieldList;
private Map<Integer, Field> customFiledMap;
private List<Field> allFieldList;
private Map<Integer, Field> sortedAllFiledMap;
private Map<Integer, Field> indexFiledMap;
private Map<String, Field> ignoreMap;
public FieldCache(List<Field> defaultFieldList, Map<Integer, Field> customFiledMap, List<Field> allFieldList,
public FieldCache(Map<Integer, Field> sortedAllFiledMap, Map<Integer, Field> indexFiledMap,
Map<String, Field> ignoreMap) {
this.defaultFieldList = defaultFieldList;
this.customFiledMap = customFiledMap;
this.allFieldList = allFieldList;
this.sortedAllFiledMap = sortedAllFiledMap;
this.indexFiledMap = indexFiledMap;
this.ignoreMap = ignoreMap;
}
public List<Field> getDefaultFieldList() {
return defaultFieldList;
}
public Map<Integer, Field> getCustomFiledMap() {
return customFiledMap;
public Map<Integer, Field> getSortedAllFiledMap() {
return sortedAllFiledMap;
}
public List<Field> getAllFieldList() {
return allFieldList;
public Map<Integer, Field> getIndexFiledMap() {
return indexFiledMap;
}
public Map<String, Field> getIgnoreMap() {
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.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
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.exception.ExcelDataConvertException;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.alibaba.excel.read.metadata.holder.ReadHolder;
import com.alibaba.excel.read.metadata.holder.ReadSheetHolder;
/**
* Converting objects
@ -32,13 +31,13 @@ public class ConverterUtils {
* @param context
* @return
*/
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);
ReadHolder currentReadHolder = context.currentReadHolder();
public static Map<Integer, String> convertToStringMap(Map<Integer, CellData<?>> cellDataMap, AnalysisContext context) {
Map<Integer, String> stringMap = MapUtils.newHashMapWithExpectedSize(cellDataMap.size());
ReadSheetHolder readSheetHolder = context.readSheetHolder();
int index = 0;
for (Map.Entry<Integer, CellData> entry : cellDataMap.entrySet()) {
for (Map.Entry<Integer, CellData<?>> entry : cellDataMap.entrySet()) {
Integer key = entry.getKey();
CellData cellData = entry.getValue();
CellData<?> cellData = entry.getValue();
while (index < key) {
stringMap.put(index, null);
index++;
@ -48,15 +47,15 @@ public class ConverterUtils {
stringMap.put(key, null);
continue;
}
Converter converter =
currentReadHolder.converterMap().get(ConverterKeyBuild.buildKey(String.class, cellData.getType()));
Converter<?> converter =
readSheetHolder.converterMap().get(ConverterKeyBuild.buildKey(String.class, cellData.getType()));
if (converter == null) {
throw new ExcelDataConvertException(context.readRowHolder().getRowIndex(), key, cellData, null,
"Converter not found, convert " + cellData.getType() + " to String");
}
try {
stringMap.put(key,
(String)(converter.convertToJavaData(cellData, null, currentReadHolder.globalConfiguration())));
(String)(converter.convertToJavaData(cellData, null, readSheetHolder)));
} catch (Exception e) {
throw new ExcelDataConvertException(context.readRowHolder().getRowIndex(), key, cellData, null,
"Convert data " + cellData + " to String error ", e);
@ -72,15 +71,15 @@ public class ConverterUtils {
* @param field
* @param contentProperty
* @param converterMap
* @param globalConfiguration
* @param readSheetHolder
* @param rowIndex
* @param columnIndex
* @return
*/
public static Object convertToJavaObject(CellData cellData, Field field, ExcelContentProperty contentProperty,
Map<String, Converter> converterMap, GlobalConfiguration globalConfiguration, Integer rowIndex,
public static Object convertToJavaObject(CellData<?> cellData, Field field, ExcelContentProperty contentProperty,
Map<String, Converter<?>> converterMap, ReadSheetHolder readSheetHolder, Integer rowIndex,
Integer columnIndex) {
Class clazz;
Class<?> clazz;
if (field == null) {
clazz = String.class;
} else {
@ -88,37 +87,37 @@ public class ConverterUtils {
}
if (clazz == CellData.class) {
Type type = field.getGenericType();
Class classGeneric;
Class<?> classGeneric;
if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType)type;
classGeneric = (Class)parameterizedType.getActualTypeArguments()[0];
classGeneric = (Class<?>)parameterizedType.getActualTypeArguments()[0];
} else {
classGeneric = String.class;
}
CellData cellDataReturn = new CellData(cellData);
CellData<Object> cellDataReturn = new CellData<Object>(cellData);
cellDataReturn.setData(doConvertToJavaObject(cellData, classGeneric, contentProperty, converterMap,
globalConfiguration, rowIndex, columnIndex));
readSheetHolder, rowIndex, columnIndex));
return cellDataReturn;
}
return doConvertToJavaObject(cellData, clazz, contentProperty, converterMap, globalConfiguration, rowIndex,
return doConvertToJavaObject(cellData, clazz, contentProperty, converterMap, readSheetHolder, rowIndex,
columnIndex);
}
/**
*
* @param cellData
* @param clazz
* @param contentProperty
* @param converterMap
* @param globalConfiguration
* @param readSheetHolder
* @param rowIndex
* @param columnIndex
* @return
*/
private static Object doConvertToJavaObject(CellData cellData, Class clazz, ExcelContentProperty contentProperty,
Map<String, Converter> converterMap, GlobalConfiguration globalConfiguration, Integer rowIndex,
private static Object doConvertToJavaObject(CellData<?> cellData, Class<?> clazz,
ExcelContentProperty contentProperty,
Map<String, Converter<?>> converterMap, ReadSheetHolder readSheetHolder, Integer rowIndex,
Integer columnIndex) {
Converter converter = null;
Converter<?> converter = null;
if (contentProperty != null) {
converter = contentProperty.getConverter();
}
@ -130,7 +129,7 @@ public class ConverterUtils {
"Converter not found, convert " + cellData.getType() + " to " + clazz.getName());
}
try {
return converter.convertToJavaData(cellData, contentProperty, globalConfiguration);
return converter.convertToJavaData(cellData, contentProperty, readSheetHolder);
} catch (Exception e) {
throw new ExcelDataConvertException(rowIndex, columnIndex, cellData, contentProperty,
"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
*/
private static final ThreadLocal<Map<Integer, Boolean>> DATE_THREAD_LOCAL =
new ThreadLocal<Map<Integer, Boolean>>();
private static final ThreadLocal<Map<Short, Boolean>> DATE_THREAD_LOCAL =
new ThreadLocal<>();
/**
* Is a cache of dates
*/
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_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_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_19 = "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 = "-";
public static String defaultDateFormat = DATE_FORMAT_19;
private DateUtils() {}
/**
@ -91,6 +95,12 @@ public class DateUtils {
} else {
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:
return DATE_FORMAT_17;
case 14:
@ -126,7 +136,7 @@ public class DateUtils {
return "";
}
if (StringUtils.isEmpty(dateFormat)) {
dateFormat = DATE_FORMAT_19;
dateFormat = defaultDateFormat;
}
return getCacheDateFormat(dateFormat).format(date);
}
@ -154,13 +164,13 @@ public class DateUtils {
* @param formatString
* @return
*/
public static boolean isADateFormat(Integer formatIndex, String formatString) {
public static boolean isADateFormat(Short formatIndex, String formatString) {
if (formatIndex == null) {
return false;
}
Map<Integer, Boolean> isDateCache = DATE_THREAD_LOCAL.get();
Map<Short, Boolean> isDateCache = DATE_THREAD_LOCAL.get();
if (isDateCache == null) {
isDateCache = new HashMap<Integer, Boolean>();
isDateCache = MapUtils.newHashMap();
DATE_THREAD_LOCAL.set(isDateCache);
} else {
Boolean isDateCachedData = isDateCache.get(formatIndex);
@ -180,7 +190,7 @@ public class DateUtils {
* @param formatString
* @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?
if (isInternalDateFormat(formatIndex)) {
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.
*
* @see #isADateFormat(Integer, String)
* @see #isADateFormat(Short, String)
*/
public static boolean isInternalDateFormat(int format) {
public static boolean isInternalDateFormat(short format) {
switch (format) {
// Internal Date Formats as described on page 427 in
// 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.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.ExcelCommonException;
import org.apache.poi.util.DefaultTempFileCreationStrategy;
import org.apache.poi.util.TempFile;
/**
*
* @author jipengfei
@ -100,10 +100,21 @@ public class FileUtils {
/**
* Write inputStream to file
*
* @param file
* @param inputStream
* @param file file
* @param 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;
try {
outputStream = new FileOutputStream(file);
@ -122,7 +133,7 @@ public class FileUtils {
throw new ExcelAnalysisException("Can not close 'outputStream'!", e);
}
}
if (inputStream != null) {
if (inputStream != null && closeInputStream) {
try {
inputStream.close();
} catch (IOException e) {
@ -132,6 +143,7 @@ public class FileUtils {
}
}
public static void createPoiFilesDirectory() {
File poiFilesPathFile = new File(poiFilesPath);
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;
}
}

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

@ -1,6 +1,6 @@
package com.alibaba.excel.util;
import com.alibaba.excel.metadata.DataFormatter;
import com.alibaba.excel.metadata.format.DataFormatter;
import com.alibaba.excel.metadata.GlobalConfiguration;
/**
@ -9,6 +9,7 @@ import com.alibaba.excel.metadata.GlobalConfiguration;
* @author Jiaju Zhuang
**/
public class NumberDataFormatterUtils {
/**
* Cache DataFormatter.
*/
@ -18,22 +19,16 @@ public class NumberDataFormatterUtils {
* Format number data.
*
* @param data
* @param dataFormat
* Not null.
* @param dataFormat Not null.
* @param dataFormatString
* @param globalConfiguration
* @return
*/
public static String format(Double data, Integer dataFormat, String dataFormatString,
public static String format(Double data, Short dataFormat, String dataFormatString,
GlobalConfiguration globalConfiguration) {
DataFormatter dataFormatter = DATA_FORMATTER_THREAD_LOCAL.get();
if (dataFormatter == null) {
if (globalConfiguration != null) {
dataFormatter =
new DataFormatter(globalConfiguration.getLocale(), globalConfiguration.getUse1904windowing());
} else {
dataFormatter = new DataFormatter();
}
dataFormatter = new DataFormatter(globalConfiguration);
DATA_FORMATTER_THREAD_LOCAL.set(dataFormatter);
}
return dataFormatter.format(data, dataFormat, dataFormatString);

25
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.property.ExcelContentProperty;
import com.alibaba.excel.write.metadata.holder.WriteHolder;
/**
* Number utils
@ -46,8 +47,27 @@ public class NumberUtils {
* @param contentProperty
* @return
*/
public static CellData formatToCellData(Number num, ExcelContentProperty contentProperty) {
return new CellData(format(num, contentProperty));
public static CellData<?> formatToCellDataString(Number num, ExcelContentProperty 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;
}
/**
@ -167,6 +187,7 @@ public class NumberUtils {
RoundingMode roundingMode = contentProperty.getNumberFormatProperty().getRoundingMode();
DecimalFormat decimalFormat = new DecimalFormat(format);
decimalFormat.setRoundingMode(roundingMode);
decimalFormat.setParseBigDecimal(true);
return decimalFormat.parse(string);
}
}

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

Loading…
Cancel
Save