Browse Source

Merge pull request #724 from alibaba/2.1.0-beta1

2.1.0 beta1
bugfix
Jiaju Zhuang 5 years ago committed by GitHub
parent
commit
8a6abd9456
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 13
      README.md
  2. 5
      docs/API.md
  3. 4
      docs/LARGEREAD.md
  4. BIN
      img/readme/large.png
  5. BIN
      img/readme/quickstart/fill/complexFill.png
  6. BIN
      img/readme/quickstart/fill/complexFillTemplate.png
  7. BIN
      img/readme/quickstart/fill/complexFillWithTable.png
  8. BIN
      img/readme/quickstart/fill/complexFillWithTableTemplate.png
  9. BIN
      img/readme/quickstart/fill/horizontalFill.png
  10. BIN
      img/readme/quickstart/fill/horizontalFillTemplate.png
  11. BIN
      img/readme/quickstart/fill/listFill.png
  12. BIN
      img/readme/quickstart/fill/listFillTemplate.png
  13. BIN
      img/readme/quickstart/fill/simpleFill.png
  14. BIN
      img/readme/quickstart/fill/simpleFillTemplate.png
  15. 2
      pom.xml
  16. 116
      problem.md
  17. 1130
      quickstart.md
  18. 2
      src/main/java/com/alibaba/excel/EasyExcelFactory.java
  19. 39
      src/main/java/com/alibaba/excel/ExcelReader.java
  20. 25
      src/main/java/com/alibaba/excel/ExcelWriter.java
  21. 14
      src/main/java/com/alibaba/excel/analysis/ExcelAnalyser.java
  22. 53
      src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java
  23. 26
      src/main/java/com/alibaba/excel/analysis/ExcelExecutor.java
  24. 30
      src/main/java/com/alibaba/excel/analysis/ExcelReadExecutor.java
  25. 6
      src/main/java/com/alibaba/excel/analysis/v03/XlsListSheetListener.java
  26. 19
      src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java
  27. 42
      src/main/java/com/alibaba/excel/analysis/v03/handlers/BofRecordHandler.java
  28. 25
      src/main/java/com/alibaba/excel/analysis/v07/XlsxSaxAnalyser.java
  29. 18
      src/main/java/com/alibaba/excel/annotation/ExcelIgnoreUnannotated.java
  30. 6
      src/main/java/com/alibaba/excel/context/AnalysisContext.java
  31. 57
      src/main/java/com/alibaba/excel/context/AnalysisContextImpl.java
  32. 8
      src/main/java/com/alibaba/excel/context/WriteContext.java
  33. 295
      src/main/java/com/alibaba/excel/context/WriteContextImpl.java
  34. 17
      src/main/java/com/alibaba/excel/enums/WriteDirectionEnum.java
  35. 2
      src/main/java/com/alibaba/excel/enums/WriteLastRowTypeEnum.java
  36. 17
      src/main/java/com/alibaba/excel/enums/WriteTemplateAnalysisCellTypeEnum.java
  37. 17
      src/main/java/com/alibaba/excel/enums/WriteTypeEnum.java
  38. 57
      src/main/java/com/alibaba/excel/exception/ExcelDataConvertException.java
  39. 1
      src/main/java/com/alibaba/excel/metadata/BasicParameter.java
  40. 33
      src/main/java/com/alibaba/excel/metadata/CellData.java
  41. 41
      src/main/java/com/alibaba/excel/metadata/property/ExcelHeadProperty.java
  42. 18
      src/main/java/com/alibaba/excel/read/builder/ExcelReaderBuilder.java
  43. 36
      src/main/java/com/alibaba/excel/read/listener/ModelBuildEventListener.java
  44. 13
      src/main/java/com/alibaba/excel/read/metadata/ReadSheet.java
  45. 12
      src/main/java/com/alibaba/excel/read/metadata/ReadWorkbook.java
  46. 27
      src/main/java/com/alibaba/excel/read/metadata/holder/ReadWorkbookHolder.java
  47. 8
      src/main/java/com/alibaba/excel/support/ExcelTypeEnum.java
  48. 54
      src/main/java/com/alibaba/excel/util/ConverterUtils.java
  49. 9
      src/main/java/com/alibaba/excel/util/FileUtils.java
  50. 67
      src/main/java/com/alibaba/excel/util/SheetUtils.java
  51. 3
      src/main/java/com/alibaba/excel/util/StringUtils.java
  52. 46
      src/main/java/com/alibaba/excel/util/WorkBookUtil.java
  53. 196
      src/main/java/com/alibaba/excel/util/WriteHandlerUtils.java
  54. 19
      src/main/java/com/alibaba/excel/write/ExcelBuilder.java
  55. 359
      src/main/java/com/alibaba/excel/write/ExcelBuilderImpl.java
  56. 24
      src/main/java/com/alibaba/excel/write/builder/ExcelWriterBuilder.java
  57. 24
      src/main/java/com/alibaba/excel/write/builder/ExcelWriterSheetBuilder.java
  58. 11
      src/main/java/com/alibaba/excel/write/builder/ExcelWriterTableBuilder.java
  59. 140
      src/main/java/com/alibaba/excel/write/executor/AbstractExcelWriteExecutor.java
  60. 179
      src/main/java/com/alibaba/excel/write/executor/ExcelWriteAddExecutor.java
  61. 9
      src/main/java/com/alibaba/excel/write/executor/ExcelWriteExecutor.java
  62. 377
      src/main/java/com/alibaba/excel/write/executor/ExcelWriteFillExecutor.java
  63. 44
      src/main/java/com/alibaba/excel/write/handler/CellWriteHandler.java
  64. 4
      src/main/java/com/alibaba/excel/write/handler/DefaultWriteHandlerLoader.java
  65. 33
      src/main/java/com/alibaba/excel/write/handler/RowWriteHandler.java
  66. 4
      src/main/java/com/alibaba/excel/write/handler/SheetWriteHandler.java
  67. 11
      src/main/java/com/alibaba/excel/write/handler/WorkbookWriteHandler.java
  68. 12
      src/main/java/com/alibaba/excel/write/merge/AbstractMergeStrategy.java
  69. 12
      src/main/java/com/alibaba/excel/write/metadata/WriteBasicParameter.java
  70. 17
      src/main/java/com/alibaba/excel/write/metadata/WriteWorkbook.java
  71. 89
      src/main/java/com/alibaba/excel/write/metadata/fill/AnalysisCell.java
  72. 83
      src/main/java/com/alibaba/excel/write/metadata/fill/FillConfig.java
  73. 26
      src/main/java/com/alibaba/excel/write/metadata/holder/AbstractWriteHolder.java
  74. 60
      src/main/java/com/alibaba/excel/write/metadata/holder/WriteSheetHolder.java
  75. 93
      src/main/java/com/alibaba/excel/write/metadata/holder/WriteWorkbookHolder.java
  76. 40
      src/main/java/com/alibaba/excel/write/style/AbstractCellStyleStrategy.java
  77. 4
      src/main/java/com/alibaba/excel/write/style/AbstractVerticalCellStyleStrategy.java
  78. 4
      src/main/java/com/alibaba/excel/write/style/HorizontalCellStyleStrategy.java
  79. 19
      src/main/java/com/alibaba/excel/write/style/column/AbstractColumnWidthStyleStrategy.java
  80. 11
      src/main/java/com/alibaba/excel/write/style/column/AbstractHeadColumnWidthStyleStrategy.java
  81. 20
      src/main/java/com/alibaba/excel/write/style/column/LongestMatchColumnWidthStyleStrategy.java
  82. 15
      src/main/java/com/alibaba/excel/write/style/row/AbstractRowHeightStyleStrategy.java
  83. 2
      src/test/java/com/alibaba/easyexcel/test/core/annotation/AnnotationData.java
  84. 1
      src/test/java/com/alibaba/easyexcel/test/core/annotation/AnnotationDataTest.java
  85. 21
      src/test/java/com/alibaba/easyexcel/test/core/celldata/CellDataData.java
  86. 37
      src/test/java/com/alibaba/easyexcel/test/core/celldata/CellDataDataListener.java
  87. 71
      src/test/java/com/alibaba/easyexcel/test/core/celldata/CellDataDataTest.java
  88. 14
      src/test/java/com/alibaba/easyexcel/test/core/encrypt/EncryptData.java
  89. 35
      src/test/java/com/alibaba/easyexcel/test/core/encrypt/EncryptDataListener.java
  90. 88
      src/test/java/com/alibaba/easyexcel/test/core/encrypt/EncryptDataTest.java
  91. 2
      src/test/java/com/alibaba/easyexcel/test/core/exception/ExceptionDataListener.java
  92. 18
      src/test/java/com/alibaba/easyexcel/test/core/fill/FillData.java
  93. 157
      src/test/java/com/alibaba/easyexcel/test/core/fill/FillDataTest.java
  94. 63
      src/test/java/com/alibaba/easyexcel/test/core/large/LargeDataTest.java
  95. 14
      src/test/java/com/alibaba/easyexcel/test/core/multiplesheets/MultipleSheetsDataTest.java
  96. 1
      src/test/java/com/alibaba/easyexcel/test/core/multiplesheets/MultipleSheetsListener.java
  97. 12
      src/test/java/com/alibaba/easyexcel/test/demo/fill/FillData.java
  98. 181
      src/test/java/com/alibaba/easyexcel/test/demo/fill/FillTest.java
  99. 50
      src/test/java/com/alibaba/easyexcel/test/demo/read/CellDataDemoHeadDataListener.java
  100. 22
      src/test/java/com/alibaba/easyexcel/test/demo/read/CellDataReadDemoData.java
  101. Some files were not shown because too many files have changed in this diff Show More

13
README.md

@ -4,16 +4,21 @@ 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)
[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/)
# 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模式。在上层做了模型转换的封装,让使用者更加简单方便
## 64M内存1分钟内读取75M(46W行25列)的Excel
当然还有急速模式能更快,但是内存占用会在100M多一点
![img](img/readme/large.png)
## 相关文档
* [快速使用](/quickstart.md)
* [快速使用](https://alibaba-easyexcel.github.io/)
* [关于软件](/abouteasyexcel.md)
* [常见问题](/problem.md)
* [更新记事](/update.md)
* [English-README](/easyexcel_en.md)
## 维护者
玉霄、庄家钜、怀宇

5
docs/API.md

@ -12,6 +12,7 @@
* `ExcelIgnore` 默认所有字段都会和excel去匹配,加了这个注解会忽略该字段
* `DateTimeFormat` 日期转换,用`String`去接收excel日期格式的数据会调用这个注解。里面的`value`参照`java.text.SimpleDateFormat`
* `NumberFormat` 数字转换,用`String`去接收excel数字格式的数据会调用这个注解。里面的`value`参照`java.text.DecimalFormat`
* `ExcelIgnoreUnannotated` 默认不加`ExcelProperty` 的注解的都会参与读写,加了不会参与
### 参数
#### 通用参数
`ReadWorkbook`,`ReadSheet` 都会有的参数,如果为空,默认使用上级。
@ -21,6 +22,7 @@
* `head` 与`clazz`二选一。读取文件头对应的列表,会根据列表匹配数据,建议使用class。
* `clazz` 与`head`二选一。读取文件的头对应的class,也可以使用注解。如果两个都不指定,则会读取全部数据。
* `autoTrim` 字符串、表头等数据自动trim
* `password` 读的时候是否需要使用密码
#### ReadWorkbook(理解成excel对象)参数
* `excelType` 当前excel的类型 默认会自动判断
* `inputStream` 与`file`二选一。读取文件的流,如果接收到的是流就只用,不用流建议使用`file`参数。因为使用了`inputStream` easyexcel会帮忙创建临时文件,最终还是`file`
@ -36,6 +38,7 @@
* `ExcelIgnore` 默认所有字段都会写入excel,这个注解会忽略这个字段
* `DateTimeFormat` 日期转换,将`Date`写到excel会调用这个注解。里面的`value`参照`java.text.SimpleDateFormat`
* `NumberFormat` 数字转换,用`Number`写excel会调用这个注解。里面的`value`参照`java.text.DecimalFormat`
* `ExcelIgnoreUnannotated` 默认不加`ExcelProperty` 的注解的都会参与读写,加了不会参与
### 参数
#### 通用参数
`WriteWorkbook`,`WriteSheet` ,`WriteTable`都会有的参数,如果为空,默认使用上级。
@ -53,6 +56,8 @@
* `templateInputStream` 模板的文件流
* `templateFile` 模板文件
* `autoCloseStream` 自动关闭流。
* `password` 写的时候是否需要使用密码
* `useDefaultStyle` 写的时候是否是使用默认头
#### WriteSheet(就是excel的一个Sheet)参数
* `sheetNo` 需要写入的编码。默认0
* `sheetName` 需要些的Sheet名称,默认同`sheetNo`

4
docs/LARGEREAD.md

@ -9,6 +9,7 @@
```java
// 强制使用内存存储,这样大概一个20M的excel使用150M(很多临时对象,所以100M会一直GC)的内存
// 这样效率会比上面的复杂的策略高很多
// 这里再说明下 就是加了个readCache(new MapCache()) 参数而已,其他的参照其他demo写 这里没有写全
EasyExcel.read().readCache(new MapCache());
```
### 对并发要求较高,而且都是经常有超级大文件
@ -16,7 +17,10 @@
// 第一个参数的意思是 多少M共享字符串以后 采用文件存储 单位MB 默认5M
// 第二个参数 文件存储时,内存存放多少M缓存数据 默认20M
// 比如 你希望用100M内存(这里说的是解析过程中的永久占用,临时对象不算)来解析excel,前面算过了 大概是 20M+90M 所以设置参数为:20 和 90
// 这里再说明下 就是加了个readCacheSelector(new SimpleReadCacheSelector(5, 20))参数而已,其他的参照其他demo写 这里没有写全
EasyExcel.read().readCacheSelector(new SimpleReadCacheSelector(5, 20));
```
### 关于maxCacheActivateSize 也就是前面第二个参数的详细说明
easyexcel在使用文件存储的时候,会把共享字符串拆分成1000条一批,然后放到文件存储。然后excel来读取共享字符串大概率是按照顺序的,所以默认20M的1000条的数据放在内存,命中后直接返回,没命中去读文件。所以不能设置太小,太小了,很难命中,一直去读取文件,太大了的话会占用过多的内存。
### 如何判断 maxCacheActivateSize是否需要调整
开启debug日志会输出`Already put :4000000` 最后一次输出,大概可以得出值为400W,然后看`Cache misses count:4001`得到值为4K,400W/4K=1000 这代表已经`maxCacheActivateSize` 已经非常合理了。如果小于500 问题就非常大了,500到1000 应该都还行。

BIN
img/readme/large.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

BIN
img/readme/quickstart/fill/complexFill.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

BIN
img/readme/quickstart/fill/complexFillTemplate.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
img/readme/quickstart/fill/complexFillWithTable.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

BIN
img/readme/quickstart/fill/complexFillWithTableTemplate.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
img/readme/quickstart/fill/horizontalFill.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
img/readme/quickstart/fill/horizontalFillTemplate.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
img/readme/quickstart/fill/listFill.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
img/readme/quickstart/fill/listFillTemplate.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 811 B

BIN
img/readme/quickstart/fill/simpleFill.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
img/readme/quickstart/fill/simpleFillTemplate.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

2
pom.xml

@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.0.5</version>
<version>2.1.0-beta1</version>
<packaging>jar</packaging>
<name>easyexcel</name>

116
problem.md

@ -1,116 +0,0 @@
# 常见问题汇总
## 1、系统环境变量缺失或JDK版本不支持
```
java.lang.NullPointerException
at sun.awt.FontConfiguration.getVersion(FontConfiguration.java:1264)
at sun.awt.FontConfiguration.readFontConfigFile(FontConfiguration.java:219)
at sun.awt.FontConfiguration.init(FontConfiguration.java:107)
at sun.awt.X11FontManager.createFontConfiguration(X11FontManager.java:774)
at sun.font.SunFontManager$2.run(SunFontManager.java:431)
at java.security.AccessController.doPrivileged(Native Method)
at sun.font.SunFontManager.<init>(SunFontManager.java:376)
at sun.awt.FcFontManager.<init>(FcFontManager.java:35)
at sun.awt.X11FontManager.<init>(X11FontManager.java:57)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at java.lang.Class.newInstance(Class.java:442)
at sun.font.FontManagerFactory$1.run(FontManagerFactory.java:83)
at java.security.AccessController.doPrivileged(Native Method)
at sun.font.FontManagerFactory.getInstance(FontManagerFactory.java:74)
at java.awt.Font.getFont2D(Font.java:495)
at java.awt.Font.canDisplayUpTo(Font.java:2080)
at java.awt.font.TextLayout.singleFont(TextLayout.java:470)
at java.awt.font.TextLayout.<init>(TextLayout.java:531)
at org.apache.poi.ss.util.SheetUtil.getDefaultCharWidth(SheetUtil.java:275)
at org.apache.poi.xssf.streaming.AutoSizeColumnTracker.<init>(AutoSizeColumnTracker.java:117)
at org.apache.poi.xssf.streaming.SXSSFSheet.<init>(SXSSFSheet.java:79)
at org.apache.poi.xssf.streaming.SXSSFWorkbook.createAndRegisterSXSSFSheet(SXSSFWorkbook.java:656)
at org.apache.poi.xssf.streaming.SXSSFWorkbook.createSheet(SXSSFWorkbook.java:677)
at org.apache.poi.xssf.streaming.SXSSFWorkbook.createSheet(SXSSFWorkbook.java:83)
at com.alibaba.excel.write.context.GenerateContextImpl.buildCurrentSheet(GenerateContextImpl.java:93)
at com.alibaba.excel.write.ExcelBuilderImpl.addContent(ExcelBuilderImpl.java:53)
at com.alibaba.excel.ExcelWriter.write(ExcelWriter.java:44)
```
### 解决方法
该异常由于自己的环境变量缺少swing需要的字体配置,检查自己应用是否有配置-Djava.awt.headless=true,如果没有请加上该系统参数,可以解决问题。如果仍旧不行,在dockerfile中增加字体安装命令:
![粘贴图片.png](http://ata2-img.cn-hangzhou.img-pub.aliyun-inc.com/a857edfbc8199db7bb35b9e99f1f57d5.png)
参考:
https://lark.alipay.com/aone355606/gfqllg/ulptif
https://stackoverflow.com/questions/30626136/cannot-load-font-in-jre-8 http://www.jianshu.com/p/c05b5fc71bd0
## 2、xls格式错用xlsx方式解析
```
org.apache.poi.openxml4j.exceptions.OLE2NotOfficeXmlFileException: The supplied data appears to be in the OLE2 Format. You are calling the part of POI that deals with OOXML (Office Open XML) Documents. You need to call a different part of POI to process this data (eg HSSF instead of XSSF)
at org.apache.poi.openxml4j.opc.internal.ZipHelper.verifyZipHeader(ZipHelper.java:172)
at org.apache.poi.openxml4j.opc.internal.ZipHelper.openZipStream(ZipHelper.java:229)
at org.apache.poi.openxml4j.opc.ZipPackage.<init>(ZipPackage.java:97)
at org.apache.poi.openxml4j.opc.OPCPackage.open(OPCPackage.java:342)
at com.alibaba.excel.read.v07.XlsxSaxAnalyser.<init>(XlsxSaxAnalyser.java:46)
at com.alibaba.excel.read.ExcelAnalyserImpl.getSaxAnalyser(ExcelAnalyserImpl.java:30)
at com.alibaba.excel.read.ExcelAnalyserImpl.analysis(ExcelAnalyserImpl.java:51)
at com.alibaba.excel.ExcelReader.read(ExcelReader.java:55)
at read.v07.Read2007Xlsx.noModel(Read2007Xlsx.java:42)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at mockit.integration.junit4.internal.BlockJUnit4ClassRunnerDecorator.executeTest(BlockJUnit4ClassRunnerDecorator.java:126)
at mockit.integration.junit4.internal.BlockJUnit4ClassRunnerDecorator.invokeExplosively(BlockJUnit4ClassRunnerDecorator.java:104)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:237)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
```
### 解决方法
该异常时由于03版的xls,文件用07版的方式做解析的报错,请检查excelType是否设置错误。或者是不是手动去修改了excel文件名后缀的xls为xlsx。
## 3、xlsx错用xls解析
```
org.apache.poi.poifs.filesystem.OfficeXmlFileException: The supplied data appears to be in the Office 2007+ XML. You are calling the part of POI that deals with OLE2 Office Documents. You need to call a different part of POI to process this data (eg XSSF instead of HSSF)
at org.apache.poi.poifs.storage.HeaderBlock.<init>(HeaderBlock.java:152)
at org.apache.poi.poifs.storage.HeaderBlock.<init>(HeaderBlock.java:140)
at org.apache.poi.poifs.filesystem.NPOIFSFileSystem.<init>(NPOIFSFileSystem.java:302)
at org.apache.poi.poifs.filesystem.POIFSFileSystem.<init>(POIFSFileSystem.java:87)
at com.alibaba.excel.read.v03.XlsSaxAnalyser.<init>(XlsSaxAnalyser.java:55)
at com.alibaba.excel.read.ExcelAnalyserImpl.getSaxAnalyser(ExcelAnalyserImpl.java:27)
at com.alibaba.excel.read.ExcelAnalyserImpl.analysis(ExcelAnalyserImpl.java:51)
at com.alibaba.excel.ExcelReader.read(ExcelReader.java:55)
at read.v03.XLS2003FunctionTest.testExcel2003NoModel(XLS2003FunctionTest.java:31)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at mockit.integration.junit3.internal.JUnitTestCaseDecorator.runTest(JUnitTestCaseDecorator.java:142)
at mockit.integration.junit3.internal.JUnitTestCaseDecorator.originalRunBare(JUnitTestCaseDecorator.java:102)
at mockit.integration.junit3.internal.JUnitTestCaseDecorator.runBare(JUnitTestCaseDecorator.java:87)
```
原理和原因大致同上

1130
quickstart.md

File diff suppressed because it is too large Load Diff

2
src/main/java/com/alibaba/excel/EasyExcelFactory.java

@ -73,7 +73,7 @@ public class EasyExcelFactory {
* read sheet.
* @param listener
* Callback method after each row is parsed.
* @deprecated please use 'EasyExcel.read(in,head,listener).sheet(sheetNo).doRead().finish();'
* @deprecated please use 'EasyExcel.read(in,head,listener).sheet(sheetNo).doRead();'
*/
@Deprecated
public static void readBySax(InputStream in, Sheet sheet, AnalysisEventListener listener) {

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

@ -2,6 +2,7 @@ package com.alibaba.excel;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.slf4j.Logger;
@ -9,7 +10,7 @@ import org.slf4j.LoggerFactory;
import com.alibaba.excel.analysis.ExcelAnalyser;
import com.alibaba.excel.analysis.ExcelAnalyserImpl;
import com.alibaba.excel.analysis.ExcelExecutor;
import com.alibaba.excel.analysis.ExcelReadExecutor;
import com.alibaba.excel.cache.MapCache;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
@ -147,27 +148,41 @@ public class ExcelReader {
/**
* Parse all sheet content by default
*
* @deprecated lease use {@link #readAll()}
*/
@Deprecated
public void read() {
ExcelExecutor excelExecutor = excelAnalyser.excelExecutor();
if (excelExecutor.sheetList().isEmpty()) {
LOGGER.warn("Excel doesn't have any sheets.");
return;
}
for (ReadSheet readSheet : excelExecutor.sheetList()) {
read(readSheet);
readAll();
}
/***
* Parse all sheet content by default
*/
public void readAll() {
checkFinished();
excelAnalyser.analysis(null, Boolean.TRUE);
}
/**
* Parse the specified sheetSheetNo start from 1
* Parse the specified sheetSheetNo start from 0
*
* @param readSheet
* Read sheet
*/
public ExcelReader read(ReadSheet readSheet) {
public ExcelReader read(ReadSheet... readSheet) {
return read(Arrays.asList(readSheet));
}
/**
* Read multiple sheets.
*
* @param readSheetList
* @return
*/
public ExcelReader read(List<ReadSheet> readSheetList) {
checkFinished();
excelAnalyser.analysis(readSheet);
excelAnalyser.analysis(readSheetList, Boolean.FALSE);
return this;
}
@ -225,7 +240,7 @@ public class ExcelReader {
*
* @return
*/
public ExcelExecutor excelExecutor() {
public ExcelReadExecutor excelExecutor() {
checkFinished();
return excelAnalyser.excelExecutor();
}

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

@ -17,6 +17,7 @@ import com.alibaba.excel.write.merge.OnceAbsoluteMergeStrategy;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.WriteTable;
import com.alibaba.excel.write.metadata.WriteWorkbook;
import com.alibaba.excel.write.metadata.fill.FillConfig;
/**
* Excel Writer This tool is used to write value out to Excel via POI. This object can perform the following two
@ -156,6 +157,30 @@ public class ExcelWriter {
return this;
}
/**
* Fill value to a sheet
*
* @param data
* @param writeSheet
* @return
*/
public ExcelWriter fill(Object data, WriteSheet writeSheet) {
return fill(data, null, writeSheet);
}
/**
* Fill value to a sheet
*
* @param data
* @param fillConfig
* @param writeSheet
* @return
*/
public ExcelWriter fill(Object data, FillConfig fillConfig, WriteSheet writeSheet) {
excelBuilder.fill(data, fillConfig, writeSheet);
return this;
}
/**
* Write data to a sheet
*

14
src/main/java/com/alibaba/excel/analysis/ExcelAnalyser.java

@ -1,5 +1,7 @@
package com.alibaba.excel.analysis;
import java.util.List;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.metadata.ReadSheet;
@ -10,12 +12,14 @@ import com.alibaba.excel.read.metadata.ReadSheet;
*/
public interface ExcelAnalyser {
/**
* parse one sheet
* parse the sheet
*
* @param readSheet
* sheet to read
* @param readSheetList
* Which sheets you need to read.
* @param readAll
* The <code>readSheetList</code> parameter is ignored, and all sheets are read.
*/
void analysis(ReadSheet readSheet);
void analysis(List<ReadSheet> readSheetList, Boolean readAll);
/**
* Complete the entire read file.Release the cache and close stream
@ -27,7 +31,7 @@ public interface ExcelAnalyser {
*
* @return Excel file Executor
*/
ExcelExecutor excelExecutor();
ExcelReadExecutor excelExecutor();
/**
* get the analysis context.

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

@ -1,8 +1,13 @@
package com.alibaba.excel.analysis;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.List;
import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.crypt.Decryptor;
import org.apache.poi.poifs.crypt.EncryptionInfo;
import org.apache.poi.poifs.filesystem.DocumentFactoryHelper;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.util.IOUtils;
@ -19,7 +24,9 @@ import com.alibaba.excel.read.metadata.ReadSheet;
import com.alibaba.excel.read.metadata.ReadWorkbook;
import com.alibaba.excel.read.metadata.holder.ReadWorkbookHolder;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.excel.util.FileUtils;
import com.alibaba.excel.util.StringUtils;
/**
* @author jipengfei
@ -29,7 +36,7 @@ public class ExcelAnalyserImpl implements ExcelAnalyser {
private AnalysisContext analysisContext;
private ExcelExecutor excelExecutor;
private ExcelReadExecutor excelReadExecutor;
public ExcelAnalyserImpl(ReadWorkbook readWorkbook) {
try {
@ -48,12 +55,12 @@ public class ExcelAnalyserImpl implements ExcelAnalyser {
ReadWorkbookHolder readWorkbookHolder = analysisContext.readWorkbookHolder();
ExcelTypeEnum excelType = readWorkbookHolder.getExcelType();
if (excelType == null) {
excelExecutor = new XlsxSaxAnalyser(analysisContext, null);
excelReadExecutor = new XlsxSaxAnalyser(analysisContext, null);
return;
}
switch (excelType) {
case XLS:
POIFSFileSystem poifsFileSystem = null;
POIFSFileSystem poifsFileSystem;
if (readWorkbookHolder.getFile() != null) {
poifsFileSystem = new POIFSFileSystem(readWorkbookHolder.getFile());
} else {
@ -64,8 +71,9 @@ public class ExcelAnalyserImpl implements ExcelAnalyser {
InputStream decryptedStream = null;
try {
decryptedStream =
DocumentFactoryHelper.getDecryptedStream(poifsFileSystem.getRoot().getFileSystem(), null);
excelExecutor = new XlsxSaxAnalyser(analysisContext, decryptedStream);
DocumentFactoryHelper.getDecryptedStream(poifsFileSystem.getRoot().getFileSystem(),
analysisContext.readWorkbookHolder().getPassword());
excelReadExecutor = new XlsxSaxAnalyser(analysisContext, decryptedStream);
return;
} finally {
IOUtils.closeQuietly(decryptedStream);
@ -74,27 +82,37 @@ public class ExcelAnalyserImpl implements ExcelAnalyser {
poifsFileSystem.close();
}
}
excelExecutor = new XlsSaxAnalyser(analysisContext, poifsFileSystem);
if (analysisContext.readWorkbookHolder().getPassword() != null) {
Biff8EncryptionKey.setCurrentUserPassword(analysisContext.readWorkbookHolder().getPassword());
}
excelReadExecutor = new XlsSaxAnalyser(analysisContext, poifsFileSystem);
break;
case XLSX:
excelExecutor = new XlsxSaxAnalyser(analysisContext, null);
excelReadExecutor = new XlsxSaxAnalyser(analysisContext, null);
break;
default:
}
}
@Override
public void analysis(ReadSheet readSheet) {
public void analysis(List<ReadSheet> readSheetList, Boolean readAll) {
try {
analysisContext.currentSheet(excelExecutor, readSheet);
if (!readAll && CollectionUtils.isEmpty(readSheetList)) {
throw new IllegalArgumentException("Specify at least one read sheet.");
}
try {
excelExecutor.execute();
excelReadExecutor.execute(readSheetList, readAll);
} catch (ExcelAnalysisStopException e) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Custom stop!");
}
}
// The last sheet is read
if (excelReadExecutor instanceof XlsSaxAnalyser) {
if (analysisContext.readSheetHolder() != null) {
analysisContext.readSheetHolder().notifyAfterAllAnalysed(analysisContext);
}
}
} catch (RuntimeException e) {
finish();
throw e;
@ -110,6 +128,7 @@ public class ExcelAnalyserImpl implements ExcelAnalyser {
return;
}
ReadWorkbookHolder readWorkbookHolder = analysisContext.readWorkbookHolder();
try {
if (readWorkbookHolder.getReadCache() != null) {
readWorkbookHolder.getReadCache().destroy();
@ -146,6 +165,16 @@ public class ExcelAnalyserImpl implements ExcelAnalyser {
} catch (Throwable t) {
throwCanNotCloseIo(t);
}
clearEncrypt03();
}
private void clearEncrypt03() {
if (StringUtils.isEmpty(analysisContext.readWorkbookHolder().getPassword())
|| !ExcelTypeEnum.XLS.equals(analysisContext.readWorkbookHolder().getExcelType())) {
return;
}
Biff8EncryptionKey.setCurrentUserPassword(null);
}
private void throwCanNotCloseIo(Throwable t) {
@ -153,8 +182,8 @@ public class ExcelAnalyserImpl implements ExcelAnalyser {
}
@Override
public com.alibaba.excel.analysis.ExcelExecutor excelExecutor() {
return excelExecutor;
public ExcelReadExecutor excelExecutor() {
return excelReadExecutor;
}
@Override

26
src/main/java/com/alibaba/excel/analysis/ExcelExecutor.java

@ -1,26 +0,0 @@
package com.alibaba.excel.analysis;
import java.util.List;
import com.alibaba.excel.read.metadata.ReadSheet;
/**
* Excel file Executor
*
* @author Jiaju Zhuang
*/
public interface ExcelExecutor {
/**
* Returns the actual sheet in excel
*
* @return Actual sheet in excel
*/
List<ReadSheet> sheetList();
/**
* Read sheet
*/
void execute();
}

30
src/main/java/com/alibaba/excel/analysis/ExcelReadExecutor.java

@ -0,0 +1,30 @@
package com.alibaba.excel.analysis;
import java.util.List;
import com.alibaba.excel.read.metadata.ReadSheet;
/**
* Excel file Executor
*
* @author Jiaju Zhuang
*/
public interface ExcelReadExecutor {
/**
* Returns the actual sheet in excel
*
* @return Actual sheet in excel
*/
List<ReadSheet> sheetList();
/**
* Read the sheet.
*
* @param readSheetList
* Which sheets you need to read.
* @param readAll
* The <code>readSheetList</code> parameter is ignored, and all sheets are read.
*/
void execute(List<ReadSheet> readSheetList, Boolean readAll);
}

6
src/main/java/com/alibaba/excel/analysis/v03/XlsListSheetListener.java

@ -10,7 +10,6 @@ import org.apache.poi.hssf.eventusermodel.HSSFEventFactory;
import org.apache.poi.hssf.eventusermodel.HSSFListener;
import org.apache.poi.hssf.eventusermodel.HSSFRequest;
import org.apache.poi.hssf.eventusermodel.MissingRecordAwareHSSFListener;
import org.apache.poi.hssf.record.BoundSheetRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
@ -27,13 +26,14 @@ import com.alibaba.excel.read.metadata.ReadSheet;
public class XlsListSheetListener implements HSSFListener {
private POIFSFileSystem poifsFileSystem;
private List<ReadSheet> sheetList;
private XlsRecordHandler bofRecordHandler;
private BofRecordHandler bofRecordHandler;
public XlsListSheetListener(AnalysisContext analysisContext, POIFSFileSystem poifsFileSystem) {
this.poifsFileSystem = poifsFileSystem;
sheetList = new ArrayList<ReadSheet>();
bofRecordHandler = new BofRecordHandler(analysisContext, sheetList, false);
bofRecordHandler = new BofRecordHandler(analysisContext, sheetList, false, false);
bofRecordHandler.init();
bofRecordHandler.init(null, true);
}
@Override

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

@ -22,7 +22,7 @@ import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.excel.analysis.ExcelExecutor;
import com.alibaba.excel.analysis.ExcelReadExecutor;
import com.alibaba.excel.analysis.v03.handlers.BlankOrErrorRecordHandler;
import com.alibaba.excel.analysis.v03.handlers.BofRecordHandler;
import com.alibaba.excel.analysis.v03.handlers.FormulaRecordHandler;
@ -56,10 +56,12 @@ import com.alibaba.excel.util.CollectionUtils;
*
* @author jipengfei
*/
public class XlsSaxAnalyser implements HSSFListener, ExcelExecutor {
public class XlsSaxAnalyser implements HSSFListener, ExcelReadExecutor {
private static final Logger LOGGER = LoggerFactory.getLogger(XlsSaxAnalyser.class);
private POIFSFileSystem poifsFileSystem;
private Boolean readAll;
private List<ReadSheet> readSheetList;
private int lastRowNumber;
private int lastColumnNumber;
/**
@ -91,8 +93,9 @@ public class XlsSaxAnalyser implements HSSFListener, ExcelExecutor {
}
@Override
public void execute() {
analysisContext.readSheetHolder().getSheetNo();
public void execute(List<ReadSheet> readSheetList, Boolean readAll) {
this.readAll = readAll;
this.readSheetList = readSheetList;
MissingRecordAwareHSSFListener listener = new MissingRecordAwareHSSFListener(this);
formatListener = new FormatTrackingHSSFListener(listener);
workbookBuildingListener = new EventWorkbookBuilder.SheetRecordCollectingListener(formatListener);
@ -196,9 +199,9 @@ public class XlsSaxAnalyser implements HSSFListener, ExcelExecutor {
// The table has been counted and there are no duplicate statistics
if (sheets == null) {
sheets = new ArrayList<ReadSheet>();
recordHandlers.add(new BofRecordHandler(analysisContext, sheets, false));
recordHandlers.add(new BofRecordHandler(analysisContext, sheets, false, true));
} else {
recordHandlers.add(new BofRecordHandler(analysisContext, sheets, true));
recordHandlers.add(new BofRecordHandler(analysisContext, sheets, true, true));
}
recordHandlers.add(new FormulaRecordHandler(stubWorkbook, formatListener));
recordHandlers.add(new LabelRecordHandler());
@ -212,6 +215,10 @@ public class XlsSaxAnalyser implements HSSFListener, ExcelExecutor {
for (XlsRecordHandler x : recordHandlers) {
x.init();
if (x instanceof BofRecordHandler) {
BofRecordHandler bofRecordHandler = (BofRecordHandler)x;
bofRecordHandler.init(readSheetList, readAll);
}
}
}
}

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

@ -10,6 +10,7 @@ import org.apache.poi.hssf.record.Record;
import com.alibaba.excel.analysis.v03.AbstractXlsRecordHandler;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.alibaba.excel.util.SheetUtils;
/**
* Record handler
@ -21,13 +22,18 @@ public class BofRecordHandler extends AbstractXlsRecordHandler {
private BoundSheetRecord[] orderedBsrs;
private int sheetIndex;
private List<ReadSheet> sheets;
private Boolean readAll;
private List<ReadSheet> readSheetList;
private AnalysisContext context;
private boolean alreadyInit;
private boolean needInitSheet;
public BofRecordHandler(AnalysisContext context, List<ReadSheet> sheets, boolean alreadyInit) {
public BofRecordHandler(AnalysisContext context, List<ReadSheet> sheets, boolean alreadyInit,
boolean needInitSheet) {
this.context = context;
this.sheets = sheets;
this.alreadyInit = alreadyInit;
this.needInitSheet = needInitSheet;
}
@Override
@ -45,15 +51,34 @@ public class BofRecordHandler extends AbstractXlsRecordHandler {
if (orderedBsrs == null) {
orderedBsrs = BoundSheetRecord.orderByBofPosition(boundSheetRecords);
}
String sheetName = orderedBsrs[sheetIndex].getSheetname();
// Find the currently read sheet
ReadSheet readSheet = null;
if (!alreadyInit) {
ReadSheet readSheet = new ReadSheet(sheetIndex, orderedBsrs[sheetIndex].getSheetname());
readSheet = new ReadSheet(sheetIndex, sheetName);
sheets.add(readSheet);
}
if (context.readSheetHolder() != null) {
if (sheetIndex == context.readSheetHolder().getSheetNo()) {
context.readWorkbookHolder().setIgnoreRecord03(Boolean.FALSE);
} else {
if (needInitSheet) {
if (readSheet == null) {
for (ReadSheet sheet : sheets) {
if (sheet.getSheetNo() == sheetIndex) {
readSheet = sheet;
break;
}
}
}
assert readSheet != null : "Can't find the sheet.";
context.readWorkbookHolder().setIgnoreRecord03(Boolean.TRUE);
// Copy the parameter to the current sheet
readSheet = SheetUtils.match(readSheet, readSheetList, readAll,
context.readWorkbookHolder().getGlobalConfiguration());
if (readSheet != null) {
if (readSheet.getSheetNo() != 0) {
// Prompt for the end of the previous form read
context.readSheetHolder().notifyAfterAllAnalysed(context);
}
context.currentSheet(readSheet);
context.readWorkbookHolder().setIgnoreRecord03(Boolean.FALSE);
}
}
sheetIndex++;
@ -71,6 +96,11 @@ public class BofRecordHandler extends AbstractXlsRecordHandler {
}
}
public void init(List<ReadSheet> readSheetList, Boolean readAll) {
this.readSheetList = readSheetList;
this.readAll = readAll;
}
@Override
public int getOrder() {
return 0;

25
src/main/java/com/alibaba/excel/analysis/v07/XlsxSaxAnalyser.java

@ -13,7 +13,9 @@ import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackageAccess;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.model.StylesTable;
import org.apache.poi.xssf.usermodel.XSSFRelation;
@ -24,7 +26,7 @@ import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import com.alibaba.excel.analysis.ExcelExecutor;
import com.alibaba.excel.analysis.ExcelReadExecutor;
import com.alibaba.excel.cache.ReadCache;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.exception.ExcelAnalysisException;
@ -32,12 +34,14 @@ import com.alibaba.excel.read.metadata.ReadSheet;
import com.alibaba.excel.read.metadata.holder.ReadWorkbookHolder;
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
*/
public class XlsxSaxAnalyser implements ExcelExecutor {
public class XlsxSaxAnalyser implements ExcelReadExecutor {
private AnalysisContext analysisContext;
private List<ReadSheet> sheetList;
@ -135,7 +139,7 @@ public class XlsxSaxAnalyser implements ExcelExecutor {
} else {
FileUtils.writeToFile(tempFile, readWorkbookHolder.getInputStream());
}
return OPCPackage.open(tempFile);
return OPCPackage.open(tempFile, PackageAccess.READ);
}
@Override
@ -171,9 +175,16 @@ public class XlsxSaxAnalyser implements ExcelExecutor {
}
@Override
public void execute() {
parseXmlSource(sheetMap.get(analysisContext.readSheetHolder().getSheetNo()),
new XlsxRowHandler(analysisContext, stylesTable));
public void execute(List<ReadSheet> readSheetList, Boolean readAll) {
for (ReadSheet readSheet : sheetList) {
readSheet = SheetUtils.match(readSheet, readSheetList, readAll,
analysisContext.readWorkbookHolder().getGlobalConfiguration());
if (readSheet != null) {
analysisContext.currentSheet(readSheet);
parseXmlSource(sheetMap.get(readSheet.getSheetNo()), new XlsxRowHandler(analysisContext, stylesTable));
// The last sheet is read
analysisContext.readSheetHolder().notifyAfterAllAnalysed(analysisContext);
}
}
}
}

18
src/main/java/com/alibaba/excel/annotation/ExcelIgnoreUnannotated.java

@ -0,0 +1,18 @@
package com.alibaba.excel.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Ignore all unannotated fields.
*
* @author Jiaju Zhuang
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface ExcelIgnoreUnannotated {
}

6
src/main/java/com/alibaba/excel/context/AnalysisContext.java

@ -2,7 +2,7 @@ package com.alibaba.excel.context;
import java.io.InputStream;
import com.alibaba.excel.analysis.ExcelExecutor;
import com.alibaba.excel.analysis.ExcelReadExecutor;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.read.metadata.ReadSheet;
@ -22,12 +22,10 @@ public interface AnalysisContext {
/**
* Select the current table
*
* @param excelExecutor
* Excel file Executor
* @param readSheet
* sheet to read
*/
void currentSheet(ExcelExecutor excelExecutor, ReadSheet readSheet);
void currentSheet(ReadSheet readSheet);
/**
* All information about the workbook you are currently working on

57
src/main/java/com/alibaba/excel/context/AnalysisContextImpl.java

@ -5,8 +5,6 @@ import java.io.InputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.excel.analysis.ExcelExecutor;
import com.alibaba.excel.analysis.v07.XlsxSaxAnalyser;
import com.alibaba.excel.exception.ExcelAnalysisException;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.read.metadata.ReadSheet;
@ -16,7 +14,6 @@ import com.alibaba.excel.read.metadata.holder.ReadRowHolder;
import com.alibaba.excel.read.metadata.holder.ReadSheetHolder;
import com.alibaba.excel.read.metadata.holder.ReadWorkbookHolder;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.util.StringUtils;
/**
*
@ -53,13 +50,9 @@ public class AnalysisContextImpl implements AnalysisContext {
}
@Override
public void currentSheet(ExcelExecutor excelExecutor, ReadSheet readSheet) {
if (readSheet == null) {
throw new IllegalArgumentException("Sheet argument cannot be null.");
}
public void currentSheet(ReadSheet readSheet) {
readSheetHolder = new ReadSheetHolder(readSheet, readWorkbookHolder);
currentReadHolder = readSheetHolder;
selectSheet(excelExecutor);
if (readWorkbookHolder.getHasReadSheet().contains(readSheetHolder.getSheetNo())) {
throw new ExcelAnalysisException("Cannot read sheet repeatedly.");
}
@ -69,54 +62,6 @@ public class AnalysisContextImpl implements AnalysisContext {
}
}
private void selectSheet(ExcelExecutor excelExecutor) {
if (excelExecutor instanceof XlsxSaxAnalyser) {
selectSheet07(excelExecutor);
} else {
selectSheet03();
}
}
private void selectSheet03() {
if (readSheetHolder.getSheetNo() != null && readSheetHolder.getSheetNo() >= 0) {
return;
}
if (!StringUtils.isEmpty(readSheetHolder.getSheetName())) {
LOGGER.warn("Excel 2003 does not support matching sheets by name, defaults to the first one.");
}
readSheetHolder.setSheetNo(0);
}
private void selectSheet07(ExcelExecutor excelExecutor) {
if (readSheetHolder.getSheetNo() != null && readSheetHolder.getSheetNo() >= 0) {
for (ReadSheet readSheetExcel : excelExecutor.sheetList()) {
if (readSheetExcel.getSheetNo().equals(readSheetHolder.getSheetNo())) {
readSheetHolder.setSheetName(readSheetExcel.getSheetName());
return;
}
}
throw new ExcelAnalysisException("Can not find sheet:" + readSheetHolder.getSheetNo());
}
if (!StringUtils.isEmpty(readSheetHolder.getSheetName())) {
for (ReadSheet readSheetExcel : excelExecutor.sheetList()) {
String sheetName = readSheetExcel.getSheetName();
if (sheetName == null) {
continue;
}
if (readSheetHolder.globalConfiguration().getAutoTrim()) {
sheetName = sheetName.trim();
}
if (sheetName.equals(readSheetHolder.getSheetName())) {
readSheetHolder.setSheetNo(readSheetExcel.getSheetNo());
return;
}
}
}
ReadSheet readSheetExcel = excelExecutor.sheetList().get(0);
readSheetHolder.setSheetNo(readSheetExcel.getSheetNo());
readSheetHolder.setSheetName(readSheetExcel.getSheetName());
}
@Override
public ReadWorkbookHolder readWorkbookHolder() {
return readWorkbookHolder;

8
src/main/java/com/alibaba/excel/context/WriteContext.java

@ -5,6 +5,7 @@ import java.io.OutputStream;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import com.alibaba.excel.enums.WriteTypeEnum;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.WriteTable;
import com.alibaba.excel.write.metadata.holder.WriteHolder;
@ -21,9 +22,11 @@ public interface WriteContext {
/**
* If the current sheet already exists, select it; if not, create it
*
* @param writeSheet Current sheet
* @param writeSheet
* Current sheet
* @param writeType
*/
void currentSheet(WriteSheet writeSheet);
void currentSheet(WriteSheet writeSheet, WriteTypeEnum writeType);
/**
* If the current table already exists, select it; if not, create it
@ -66,6 +69,7 @@ public interface WriteContext {
*/
void finish();
/**
* Current sheet
*

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

@ -1,9 +1,28 @@
package com.alibaba.excel.context;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.util.FileUtils;
import com.alibaba.excel.util.StringUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.security.GeneralSecurityException;
import java.util.Map;
import java.util.UUID;
import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackageAccess;
import org.apache.poi.poifs.crypt.Decryptor;
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.DocumentOutputStream;
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;
@ -13,14 +32,12 @@ 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;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.util.WorkBookUtil;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.handler.RowWriteHandler;
import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.handler.WorkbookWriteHandler;
import com.alibaba.excel.write.handler.WriteHandler;
import com.alibaba.excel.util.WriteHandlerUtils;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.WriteTable;
import com.alibaba.excel.write.metadata.WriteWorkbook;
@ -64,42 +81,18 @@ public class WriteContextImpl implements WriteContext {
LOGGER.debug("Begin to Initialization 'WriteContextImpl'");
}
initCurrentWorkbookHolder(writeWorkbook);
beforeWorkbookCreate();
WriteHandlerUtils.beforeWorkbookCreate(this);
try {
writeWorkbookHolder.setWorkbook(WorkBookUtil.createWorkBook(writeWorkbookHolder));
WorkBookUtil.createWorkBook(writeWorkbookHolder);
} catch (Exception e) {
throw new ExcelGenerateException("Create workbook failure", e);
}
afterWorkbookCreate();
WriteHandlerUtils.afterWorkbookCreate(this);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Initialization 'WriteContextImpl' complete");
}
}
private void beforeWorkbookCreate() {
List<WriteHandler> handlerList = currentWriteHolder.writeHandlerMap().get(WorkbookWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof WorkbookWriteHandler) {
((WorkbookWriteHandler)writeHandler).beforeWorkbookCreate();
}
}
}
private void afterWorkbookCreate() {
List<WriteHandler> handlerList = currentWriteHolder.writeHandlerMap().get(WorkbookWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof WorkbookWriteHandler) {
((WorkbookWriteHandler)writeHandler).afterWorkbookCreate(writeWorkbookHolder);
}
}
}
private void initCurrentWorkbookHolder(WriteWorkbook writeWorkbook) {
writeWorkbookHolder = new WriteWorkbookHolder(writeWorkbook);
currentWriteHolder = writeWorkbookHolder;
@ -112,7 +105,7 @@ public class WriteContextImpl implements WriteContext {
* @param writeSheet
*/
@Override
public void currentSheet(WriteSheet writeSheet) {
public void currentSheet(WriteSheet writeSheet, WriteTypeEnum writeType) {
if (writeSheet == null) {
throw new IllegalArgumentException("Sheet argument cannot be null");
}
@ -136,38 +129,9 @@ public class WriteContextImpl implements WriteContext {
return;
}
initCurrentSheetHolder(writeSheet);
beforeSheetCreate();
WriteHandlerUtils.beforeSheetCreate(this);
// Initialization current sheet
initSheet();
afterSheetCreate();
}
private void beforeSheetCreate() {
List<WriteHandler> handlerList = currentWriteHolder.writeHandlerMap().get(SheetWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof SheetWriteHandler) {
((SheetWriteHandler)writeHandler).beforeSheetCreate(writeWorkbookHolder, writeSheetHolder);
}
}
}
private void afterSheetCreate() {
List<WriteHandler> handlerList = currentWriteHolder.writeHandlerMap().get(SheetWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof SheetWriteHandler) {
((SheetWriteHandler)writeHandler).afterSheetCreate(writeWorkbookHolder, writeSheetHolder);
}
}
if (null != writeWorkbookHolder.getWriteWorkbook().getWriteHandler()) {
writeWorkbookHolder.getWriteWorkbook().getWriteHandler().sheet(writeSheetHolder.getSheetNo(),
writeSheetHolder.getSheet());
}
initSheet(writeType);
}
private void initCurrentSheetHolder(WriteSheet writeSheet) {
@ -180,20 +144,26 @@ public class WriteContextImpl implements WriteContext {
}
}
private void initSheet() {
private void initSheet(WriteTypeEnum writeType) {
Sheet currentSheet;
try {
currentSheet = writeWorkbookHolder.getWorkbook().getSheetAt(writeSheetHolder.getSheetNo());
writeSheetHolder
.setCachedSheet(writeWorkbookHolder.getCachedWorkbook().getSheetAt(writeSheetHolder.getSheetNo()));
} catch (Exception e) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Can not find sheet:{} ,now create it", writeSheetHolder.getSheetNo());
}
currentSheet = WorkBookUtil.createSheet(writeWorkbookHolder.getWorkbook(), writeSheetHolder.getSheetName());
writeSheetHolder.setCachedSheet(currentSheet);
}
writeSheetHolder.setSheet(currentSheet);
WriteHandlerUtils.afterSheetCreate(this);
if (WriteTypeEnum.ADD.equals(writeType)) {
// Initialization head
initHead(writeSheetHolder.excelWriteHeadProperty());
}
}
public void initHead(ExcelWriteHeadProperty excelWriteHeadProperty) {
if (!currentWriteHolder.needHead() || !currentWriteHolder.excelWriteHeadProperty().hasHead()) {
@ -205,42 +175,13 @@ public class WriteContextImpl implements WriteContext {
addMergedRegionToCurrentSheet(excelWriteHeadProperty, newRowIndex);
for (int relativeRowIndex = 0, i = newRowIndex; i < excelWriteHeadProperty.getHeadRowNumber() + newRowIndex;
i++, relativeRowIndex++) {
beforeRowCreate(newRowIndex, relativeRowIndex);
WriteHandlerUtils.beforeRowCreate(this, newRowIndex, relativeRowIndex, Boolean.TRUE);
Row row = WorkBookUtil.createRow(writeSheetHolder.getSheet(), i);
afterRowCreate(row, relativeRowIndex);
WriteHandlerUtils.afterRowCreate(this, row, relativeRowIndex, Boolean.TRUE);
addOneRowOfHeadDataToExcel(row, excelWriteHeadProperty.getHeadMap(), relativeRowIndex);
}
}
private void beforeRowCreate(int rowIndex, int relativeRowIndex) {
List<WriteHandler> handlerList = currentWriteHolder.writeHandlerMap().get(RowWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof RowWriteHandler) {
((RowWriteHandler)writeHandler).beforeRowCreate(writeSheetHolder, writeTableHolder, rowIndex,
relativeRowIndex, true);
}
}
}
private void afterRowCreate(Row row, int relativeRowIndex) {
List<WriteHandler> handlerList = currentWriteHolder.writeHandlerMap().get(RowWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof RowWriteHandler) {
((RowWriteHandler)writeHandler).afterRowCreate(writeSheetHolder, writeTableHolder, row,
relativeRowIndex, true);
}
}
if (null != writeWorkbookHolder.getWriteWorkbook().getWriteHandler()) {
writeWorkbookHolder.getWriteWorkbook().getWriteHandler().row(row.getRowNum(), row);
}
}
private void addMergedRegionToCurrentSheet(ExcelWriteHeadProperty excelWriteHeadProperty, int rowIndex) {
for (com.alibaba.excel.metadata.CellRange cellRangeModel : excelWriteHeadProperty.headCellRangeList()) {
writeSheetHolder.getSheet().addMergedRegion(new CellRangeAddress(cellRangeModel.getFirstRow() + rowIndex,
@ -251,38 +192,13 @@ public class WriteContextImpl implements WriteContext {
private void addOneRowOfHeadDataToExcel(Row row, Map<Integer, Head> headMap, int relativeRowIndex) {
for (Map.Entry<Integer, Head> entry : headMap.entrySet()) {
Head head = entry.getValue();
beforeCellCreate(row, head, relativeRowIndex);
Cell cell = WorkBookUtil.createCell(row, entry.getKey(), head.getHeadNameList().get(relativeRowIndex));
afterCellCreate(head, cell, relativeRowIndex);
}
}
private void beforeCellCreate(Row row, Head head, int relativeRowIndex) {
List<WriteHandler> handlerList = currentWriteHolder.writeHandlerMap().get(CellWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof CellWriteHandler) {
((CellWriteHandler)writeHandler).beforeCellCreate(writeSheetHolder, writeTableHolder, row, head,
relativeRowIndex, true);
}
}
}
private void afterCellCreate(Head head, Cell cell, int relativeRowIndex) {
List<WriteHandler> handlerList = currentWriteHolder.writeHandlerMap().get(CellWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof CellWriteHandler) {
((CellWriteHandler)writeHandler).afterCellCreate(writeSheetHolder, writeTableHolder, null, cell, head,
relativeRowIndex, true);
}
}
if (null != writeWorkbookHolder.getWriteWorkbook().getWriteHandler()) {
writeWorkbookHolder.getWriteWorkbook().getWriteHandler().cell(cell.getRowIndex(), cell);
int columnIndex = entry.getKey();
WriteHandlerUtils.beforeCellCreate(this, row, head, columnIndex, relativeRowIndex, Boolean.TRUE);
Cell cell = row.createCell(columnIndex);
WriteHandlerUtils.afterCellCreate(this, cell, head, relativeRowIndex, Boolean.TRUE);
cell.setCellValue(head.getHeadNameList().get(relativeRowIndex));
CellData cellData = null;
WriteHandlerUtils.afterCellDispose(this, cellData, cell, head, relativeRowIndex, Boolean.TRUE);
}
}
@ -341,16 +257,27 @@ public class WriteContextImpl implements WriteContext {
@Override
public void finish() {
WriteHandlerUtils.afterWorkbookDispose(this);
if (writeWorkbookHolder == null) {
return;
}
boolean isOutputStreamEncrypt = false;
try {
isOutputStreamEncrypt = doOutputStreamEncrypt07();
} catch (Throwable t) {
throwCanNotCloseIo(t);
}
if (!isOutputStreamEncrypt) {
try {
writeWorkbookHolder.getWorkbook().write(writeWorkbookHolder.getOutputStream());
writeWorkbookHolder.getWorkbook().close();
} catch (Throwable t) {
throwCanNotCloseIo(t);
}
}
try {
Workbook workbook = writeWorkbookHolder.getWorkbook();
if (workbook instanceof SXSSFWorkbook) {
@ -359,6 +286,7 @@ public class WriteContextImpl implements WriteContext {
} catch (Throwable t) {
throwCanNotCloseIo(t);
}
try {
if (writeWorkbookHolder.getAutoCloseStream() && writeWorkbookHolder.getOutputStream() != null) {
writeWorkbookHolder.getOutputStream().close();
@ -366,21 +294,25 @@ public class WriteContextImpl implements WriteContext {
} catch (Throwable t) {
throwCanNotCloseIo(t);
}
if (!isOutputStreamEncrypt) {
try {
if (writeWorkbookHolder.getAutoCloseStream() && writeWorkbookHolder.getTemplateInputStream() != null) {
writeWorkbookHolder.getTemplateInputStream().close();
}
doFileEncrypt07();
} catch (Throwable t) {
throwCanNotCloseIo(t);
}
}
try {
if (!writeWorkbookHolder.getAutoCloseStream() && writeWorkbookHolder.getFile() != null
&& writeWorkbookHolder.getOutputStream() != null) {
writeWorkbookHolder.getOutputStream().close();
if (writeWorkbookHolder.getTempTemplateInputStream() != null) {
writeWorkbookHolder.getTempTemplateInputStream().close();
}
} catch (Throwable t) {
throwCanNotCloseIo(t);
}
clearEncrypt03();
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Finished write.");
}
@ -409,4 +341,95 @@ public class WriteContextImpl implements WriteContext {
public Workbook getWorkbook() {
return writeWorkbookHolder.getWorkbook();
}
private void clearEncrypt03() {
if (StringUtils.isEmpty(writeWorkbookHolder.getPassword())
|| !ExcelTypeEnum.XLS.equals(writeWorkbookHolder.getExcelType())) {
return;
}
Biff8EncryptionKey.setCurrentUserPassword(null);
}
/**
* To encrypt
*/
private boolean doOutputStreamEncrypt07() throws Exception {
if (StringUtils.isEmpty(writeWorkbookHolder.getPassword())
|| !ExcelTypeEnum.XLSX.equals(writeWorkbookHolder.getExcelType())) {
return false;
}
if (writeWorkbookHolder.getFile() != null) {
return false;
}
File tempXlsx = FileUtils.createTmpFile(UUID.randomUUID().toString() + ".xlsx");
FileOutputStream tempFileOutputStream = new FileOutputStream(tempXlsx);
try {
writeWorkbookHolder.getWorkbook().write(tempFileOutputStream);
} finally {
try {
writeWorkbookHolder.getWorkbook().close();
tempFileOutputStream.close();
} catch (Exception e) {
if (!tempXlsx.delete()) {
throw new ExcelGenerateException("Can not delete temp File!");
}
throw e;
}
}
POIFSFileSystem fileSystem = null;
try {
fileSystem = openFileSystemAndEncrypt(tempXlsx);
fileSystem.writeFilesystem(writeWorkbookHolder.getOutputStream());
} finally {
if (fileSystem != null) {
fileSystem.close();
}
if (!tempXlsx.delete()) {
throw new ExcelGenerateException("Can not delete temp File!");
}
}
return true;
}
/**
* To encrypt
*/
private void doFileEncrypt07() throws Exception {
if (StringUtils.isEmpty(writeWorkbookHolder.getPassword())
|| !ExcelTypeEnum.XLSX.equals(writeWorkbookHolder.getExcelType())) {
return;
}
if (writeWorkbookHolder.getFile() == null) {
return;
}
FileOutputStream fileOutputStream = null;
POIFSFileSystem fileSystem = null;
try {
fileSystem = openFileSystemAndEncrypt(writeWorkbookHolder.getFile());
fileOutputStream = new FileOutputStream(writeWorkbookHolder.getFile());
fileSystem.writeFilesystem(fileOutputStream);
} finally {
if (fileOutputStream != null) {
fileOutputStream.close();
}
if (fileSystem != null) {
fileSystem.close();
}
}
}
private POIFSFileSystem openFileSystemAndEncrypt(File file) throws Exception {
POIFSFileSystem fileSystem = new POIFSFileSystem();
Encryptor encryptor = new EncryptionInfo(EncryptionMode.standard).getEncryptor();
encryptor.confirmPassword(writeWorkbookHolder.getPassword());
OPCPackage opcPackage = null;
try {
opcPackage = OPCPackage.open(file, PackageAccess.READ_WRITE);
OutputStream outputStream = encryptor.getDataStream(fileSystem);
opcPackage.save(outputStream);
} finally {
opcPackage.close();
}
return fileSystem;
}
}

17
src/main/java/com/alibaba/excel/enums/WriteDirectionEnum.java

@ -0,0 +1,17 @@
package com.alibaba.excel.enums;
/**
* Direction of writing
*
* @author Jiaju Zhuang
**/
public enum WriteDirectionEnum {
/**
* Vertical write.
*/
VERTICAL,
/**
* Horizontal write.
*/
HORIZONTAL,;
}

2
src/main/java/com/alibaba/excel/enums/WriteLastRowType.java → src/main/java/com/alibaba/excel/enums/WriteLastRowTypeEnum.java

@ -5,7 +5,7 @@ package com.alibaba.excel.enums;
*
* @author Jiaju Zhuang
**/
public enum WriteLastRowType {
public enum WriteLastRowTypeEnum {
/**
* Excel are created without templates ,And any data has been written;
*/

17
src/main/java/com/alibaba/excel/enums/WriteTemplateAnalysisCellTypeEnum.java

@ -0,0 +1,17 @@
package com.alibaba.excel.enums;
/**
* Type of template to read when writing
*
* @author Jiaju Zhuang
**/
public enum WriteTemplateAnalysisCellTypeEnum {
/**
* Common field.
*/
COMMON,
/**
* A collection of fields.
*/
COLLECTION,;
}

17
src/main/java/com/alibaba/excel/enums/WriteTypeEnum.java

@ -0,0 +1,17 @@
package com.alibaba.excel.enums;
/**
* Enumeration of write methods
*
* @author Jiaju Zhuang
**/
public enum WriteTypeEnum {
/**
* Add.
*/
ADD,
/**
* Fill.
*/
FILL,;
}

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

@ -1,16 +1,49 @@
package com.alibaba.excel.exception;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
/**
* Data convert exception
*
* @author Jiaju Zhuang
*/
public class ExcelDataConvertException extends RuntimeException {
/**
* NotNull.
*/
private Integer rowIndex;
/**
* NotNull.
*/
private Integer columnIndex;
/**
* Nullable.Only when the header is configured and when the class header is used is not null.
*
* @see {@link ExcelWriterBuilder#head(Class)}
*/
private ExcelContentProperty excelContentProperty;
public ExcelDataConvertException(String message) {
super(message);
}
public ExcelDataConvertException(Integer rowIndex, Integer columnIndex, ExcelContentProperty excelContentProperty,
String message) {
super(message);
this.rowIndex = rowIndex;
this.columnIndex = columnIndex;
this.excelContentProperty = excelContentProperty;
}
public ExcelDataConvertException(Integer rowIndex, Integer columnIndex, ExcelContentProperty excelContentProperty,
String message, Throwable cause) {
super(message, cause);
this.rowIndex = rowIndex;
this.columnIndex = columnIndex;
this.excelContentProperty = excelContentProperty;
}
public ExcelDataConvertException(String message, Throwable cause) {
super(message, cause);
}
@ -18,4 +51,28 @@ public class ExcelDataConvertException extends RuntimeException {
public ExcelDataConvertException(Throwable cause) {
super(cause);
}
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;
}
}

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

@ -74,4 +74,5 @@ public class BasicParameter {
public void setUse1904windowing(Boolean use1904windowing) {
this.use1904windowing = use1904windowing;
}
}

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

@ -6,11 +6,13 @@ import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.util.StringUtils;
/**
* Excel internal cell data
* Excel internal cell data.
*
* <p>
*
* @author Jiaju Zhuang
*/
public class CellData {
public class CellData<T> {
private CellDataTypeEnum type;
/**
* {@link CellDataTypeEnum#NUMBER}
@ -35,8 +37,12 @@ public class CellData {
* The string of number formatting.Currently only supported when reading
*/
private String dataFormatString;
/**
* The resulting converted data.
*/
private T data;
public CellData(CellData other) {
public CellData(CellData<T> other) {
this.type = other.type;
this.numberValue = other.numberValue;
this.stringValue = other.stringValue;
@ -46,6 +52,19 @@ public class CellData {
this.imageValue = other.imageValue;
this.dataFormat = other.dataFormat;
this.dataFormatString = other.dataFormatString;
this.data = other.data;
}
public CellData() {}
public CellData(T data) {
this.data = data;
}
public CellData(T data, String formulaValue) {
this.data = data;
this.formula = Boolean.TRUE;
this.formulaValue = formulaValue;
}
public CellData(String stringValue) {
@ -171,6 +190,14 @@ public class CellData {
this.dataFormatString = dataFormatString;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
/**
* Ensure that the object does not appear null
*/

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

@ -13,9 +13,11 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import com.alibaba.excel.annotation.format.NumberFormat;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.converters.AutoConverter;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.HeadKindEnum;
@ -53,6 +55,10 @@ public class ExcelHeadProperty {
* Configuration column information
*/
private Map<Integer, ExcelContentProperty> contentPropertyMap;
/**
* Configuration column information
*/
private Map<String, ExcelContentProperty> fieldNameContentPropertyMap;
/**
* Fields ignored
*/
@ -62,6 +68,7 @@ public class ExcelHeadProperty {
this.headClazz = headClazz;
headMap = new TreeMap<Integer, Head>();
contentPropertyMap = new TreeMap<Integer, ExcelContentProperty>();
fieldNameContentPropertyMap = new HashMap<String, ExcelContentProperty>();
ignoreMap = new HashMap<String, Field>(16);
headKind = HeadKindEnum.NONE;
headRowNumber = 0;
@ -79,10 +86,6 @@ public class ExcelHeadProperty {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("The initialization sheet/table 'ExcelHeadProperty' is complete , head kind is {}", headKind);
}
if (!hasHead()) {
LOGGER.warn(
"The table has no header set and all annotations will not be read.If you want to use annotations, please use set head class in ExcelWriterBuilder/ExcelWriterSheetBuilder/ExcelWriterTableBuilder");
}
}
private void initHeadRowNumber() {
@ -119,25 +122,28 @@ public class ExcelHeadProperty {
tempClass = tempClass.getSuperclass();
}
ExcelIgnoreUnannotated excelIgnoreUnannotated =
(ExcelIgnoreUnannotated)headClazz.getAnnotation(ExcelIgnoreUnannotated.class);
// Screening of field
List<Field> defaultFieldList = new ArrayList<Field>();
Map<Integer, Field> customFiledMap = new TreeMap<Integer, Field>();
for (Field field : fieldList) {
ExcelIgnore excelIgnore = field.getAnnotation(ExcelIgnore.class);
if(Modifier.isStatic(field.getModifiers())&&Modifier.isFinal(field.getModifiers())){
ignoreMap.put(field.getName(),field);
continue;
}
if(Modifier.isTransient(field.getModifiers())){
ignoreMap.put(field.getName(),field);
continue;
}
if (excelIgnore != null) {
ignoreMap.put(field.getName(), field);
continue;
}
ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
if (excelProperty == null && convertAllFiled != null && !convertAllFiled) {
boolean noExcelProperty = excelProperty == null
&& ((convertAllFiled != null && !convertAllFiled) || excelIgnoreUnannotated != null);
if (noExcelProperty) {
ignoreMap.put(field.getName(), field);
continue;
}
boolean isStaticFinalOrTransient =
(Modifier.isStatic(field.getModifiers()) && Modifier.isFinal(field.getModifiers()))
|| Modifier.isTransient(field.getModifiers());
if (excelProperty == null && isStaticFinalOrTransient) {
ignoreMap.put(field.getName(), field);
continue;
}
@ -199,6 +205,7 @@ public class ExcelHeadProperty {
.setNumberFormatProperty(NumberFormatProperty.build(field.getAnnotation(NumberFormat.class)));
headMap.put(index, head);
contentPropertyMap.put(index, excelContentProperty);
fieldNameContentPropertyMap.put(field.getName(), excelContentProperty);
}
public Class getHeadClazz() {
@ -245,6 +252,14 @@ public class ExcelHeadProperty {
this.contentPropertyMap = contentPropertyMap;
}
public Map<String, ExcelContentProperty> getFieldNameContentPropertyMap() {
return fieldNameContentPropertyMap;
}
public void setFieldNameContentPropertyMap(Map<String, ExcelContentProperty> fieldNameContentPropertyMap) {
this.fieldNameContentPropertyMap = fieldNameContentPropertyMap;
}
public Map<String, Field> getIgnoreMap() {
return ignoreMap;
}

18
src/main/java/com/alibaba/excel/read/builder/ExcelReaderBuilder.java

@ -222,10 +222,28 @@ public class ExcelReaderBuilder {
return this;
}
/**
* Whether the encryption
*
* @param password
* @return
*/
public ExcelReaderBuilder password(String password) {
readWorkbook.setPassword(password);
return this;
}
public ExcelReader build() {
return new ExcelReader(readWorkbook);
}
public ExcelReader doReadAll() {
ExcelReader excelReader = build();
excelReader.readAll();
excelReader.finish();
return excelReader;
}
public ExcelReaderSheetBuilder sheet() {
return sheet(null, null);
}

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

@ -33,7 +33,8 @@ public class ModelBuildEventListener extends AbstractIgnoreExceptionReadListener
public void invoke(Map<Integer, CellData> cellDataMap, AnalysisContext context) {
ReadHolder currentReadHolder = context.currentReadHolder();
if (HeadKindEnum.CLASS.equals(currentReadHolder.excelReadHeadProperty().getHeadKind())) {
context.readRowHolder().setCurrentRowAnalysisResult(buildUserModel(cellDataMap, currentReadHolder));
context.readRowHolder()
.setCurrentRowAnalysisResult(buildUserModel(cellDataMap, currentReadHolder, context));
return;
}
context.readRowHolder().setCurrentRowAnalysisResult(buildStringList(cellDataMap, currentReadHolder, context));
@ -41,35 +42,51 @@ public class ModelBuildEventListener extends AbstractIgnoreExceptionReadListener
private Object buildStringList(Map<Integer, CellData> cellDataMap, ReadHolder currentReadHolder,
AnalysisContext context) {
int index = 0;
if (context.readWorkbookHolder().getDefaultReturnMap()) {
Map<Integer, String> map = new HashMap<Integer, String>(cellDataMap.size() * 4 / 3 + 1);
for (Map.Entry<Integer, CellData> entry : cellDataMap.entrySet()) {
Integer key = entry.getKey();
CellData cellData = entry.getValue();
while (index < key) {
map.put(index, null);
index++;
}
index++;
if (cellData.getType() == CellDataTypeEnum.EMPTY) {
map.put(entry.getKey(), null);
map.put(key, null);
continue;
}
map.put(entry.getKey(), (String)ConverterUtils.convertToJavaObject(cellData, String.class, null,
currentReadHolder.converterMap(), currentReadHolder.globalConfiguration()));
map.put(key,
(String)ConverterUtils.convertToJavaObject(cellData, null, null, currentReadHolder.converterMap(),
currentReadHolder.globalConfiguration(), context.readRowHolder().getRowIndex(), key));
}
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()) {
Integer key = entry.getKey();
CellData cellData = entry.getValue();
while (index < key) {
list.add(null);
index++;
}
index++;
if (cellData.getType() == CellDataTypeEnum.EMPTY) {
list.add(null);
continue;
}
list.add((String)ConverterUtils.convertToJavaObject(cellData, String.class, null,
currentReadHolder.converterMap(), currentReadHolder.globalConfiguration()));
list.add(
(String)ConverterUtils.convertToJavaObject(cellData, null, null, currentReadHolder.converterMap(),
currentReadHolder.globalConfiguration(), context.readRowHolder().getRowIndex(), key));
}
return list;
}
}
private Object buildUserModel(Map<Integer, CellData> cellDataMap, ReadHolder currentReadHolder) {
private Object buildUserModel(Map<Integer, CellData> cellDataMap, ReadHolder currentReadHolder,
AnalysisContext context) {
ExcelReadHeadProperty excelReadHeadProperty = currentReadHolder.excelReadHeadProperty();
Object resultModel;
try {
@ -91,8 +108,9 @@ public class ModelBuildEventListener extends AbstractIgnoreExceptionReadListener
continue;
}
ExcelContentProperty excelContentProperty = contentPropertyMap.get(index);
Object value = ConverterUtils.convertToJavaObject(cellData, excelContentProperty.getField().getType(),
excelContentProperty, currentReadHolder.converterMap(), currentReadHolder.globalConfiguration());
Object value = ConverterUtils.convertToJavaObject(cellData, excelContentProperty.getField(),
excelContentProperty, currentReadHolder.converterMap(), currentReadHolder.globalConfiguration(),
context.readRowHolder().getRowIndex(), index);
if (value != null) {
map.put(excelContentProperty.getField().getName(), value);
}

13
src/main/java/com/alibaba/excel/read/metadata/ReadSheet.java

@ -42,6 +42,19 @@ public class ReadSheet extends ReadBasicParameter {
this.sheetName = sheetName;
}
public void copyBasicParameter(ReadSheet other) {
if (other == null) {
return;
}
this.setHeadRowNumber(other.getHeadRowNumber());
this.setCustomReadListenerList(other.getCustomReadListenerList());
this.setHead(other.getHead());
this.setClazz(other.getClazz());
this.setCustomConverterList(other.getCustomConverterList());
this.setAutoTrim(other.getAutoTrim());
this.setUse1904windowing(other.getUse1904windowing());
}
@Override
public String toString() {
return "ReadSheet{" + "sheetNo=" + sheetNo + ", sheetName='" + sheetName + '\'' + "} " + super.toString();

12
src/main/java/com/alibaba/excel/read/metadata/ReadWorkbook.java

@ -59,6 +59,10 @@ public class ReadWorkbook extends ReadBasicParameter {
* Select the cache.Default use {@link com.alibaba.excel.cache.selector.SimpleReadCacheSelector}
*/
private ReadCacheSelector readCacheSelector;
/**
* Whether the encryption
*/
private String password;
/**
* The default is all excel objects.Default is true.
* <p>
@ -164,4 +168,12 @@ public class ReadWorkbook extends ReadBasicParameter {
public void setReadCacheSelector(ReadCacheSelector readCacheSelector) {
this.readCacheSelector = readCacheSelector;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}

27
src/main/java/com/alibaba/excel/read/metadata/holder/ReadWorkbookHolder.java

@ -8,8 +8,6 @@ import java.util.Set;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.excel.cache.ReadCache;
import com.alibaba.excel.cache.selector.EternalReadCacheSelector;
@ -28,7 +26,6 @@ import com.alibaba.excel.support.ExcelTypeEnum;
* @author Jiaju Zhuang
*/
public class ReadWorkbookHolder extends AbstractReadHolder {
private static final Logger LOGGER = LoggerFactory.getLogger(ReadWorkbookHolder.class);
/**
* current param
@ -82,7 +79,10 @@ public class ReadWorkbookHolder extends AbstractReadHolder {
* Temporary files when reading excel
*/
private File tempFile;
/**
* Whether the encryption
*/
private String password;
/**
* The default is all excel objects.if true , you can use {@link com.alibaba.excel.annotation.ExcelIgnore} ignore a
* field. if false , you must use {@link com.alibaba.excel.annotation.ExcelProperty} to use a filed.
@ -141,11 +141,11 @@ public class ReadWorkbookHolder extends AbstractReadHolder {
} else {
this.autoCloseStream = readWorkbook.getAutoCloseStream();
}
if (readWorkbook.getExcelType() == null) {
this.excelType = ExcelTypeEnum.valueOf(file, inputStream);
} else {
this.excelType = readWorkbook.getExcelType();
}
// The type of excel is read according to the judgment.Because encrypted XLSX needs to be specified as XLS to
// properly parse.
this.excelType = ExcelTypeEnum.valueOf(file, inputStream, readWorkbook.getExcelType());
if (ExcelTypeEnum.XLS == excelType && getGlobalConfiguration().getUse1904windowing() == null) {
getGlobalConfiguration().setUse1904windowing(Boolean.FALSE);
}
@ -174,6 +174,7 @@ public class ReadWorkbookHolder extends AbstractReadHolder {
}
this.hasReadSheet = new HashSet<Integer>();
this.ignoreRecord03 = Boolean.FALSE;
this.password = readWorkbook.getPassword();
}
public ReadWorkbook getReadWorkbook() {
@ -312,6 +313,14 @@ public class ReadWorkbookHolder extends AbstractReadHolder {
this.ignoreRecord03 = ignoreRecord03;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public HolderEnum holderType() {
return HolderEnum.WORKBOOK;

8
src/main/java/com/alibaba/excel/support/ExcelTypeEnum.java

@ -29,7 +29,7 @@ public enum ExcelTypeEnum {
this.setValue(value);
}
public static ExcelTypeEnum valueOf(File file, InputStream inputStream) {
public static ExcelTypeEnum valueOf(File file, InputStream inputStream, ExcelTypeEnum excelType) {
try {
FileMagic fileMagic;
if (file != null) {
@ -59,9 +59,15 @@ public enum ExcelTypeEnum {
return XLSX;
}
} catch (IOException e) {
if (excelType != null) {
return excelType;
}
throw new ExcelCommonException(
"Convert excel format exception.You can try specifying the 'excelType' yourself", e);
}
if (excelType != null) {
return excelType;
}
throw new ExcelCommonException(
"Convert excel format exception.You can try specifying the 'excelType' yourself");
}

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

@ -1,5 +1,8 @@
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;
@ -56,17 +59,55 @@ public class ConverterUtils {
* Convert it into a Java object
*
* @param cellData
* @param clazz
* @param field
* @param contentProperty
* @param converterMap
* @param globalConfiguration
* @param rowIndex
* @param columnIndex
* @return
*/
public static Object convertToJavaObject(CellData cellData, Class clazz, ExcelContentProperty contentProperty,
Map<String, Converter> converterMap, GlobalConfiguration globalConfiguration) {
public static Object convertToJavaObject(CellData cellData, Field field, ExcelContentProperty contentProperty,
Map<String, Converter> converterMap, GlobalConfiguration globalConfiguration, Integer rowIndex,
Integer columnIndex) {
Class clazz;
if (field == null) {
clazz = String.class;
} else {
clazz = field.getType();
}
if (clazz == CellData.class) {
return new CellData(cellData);
Type type = field.getGenericType();
Class classGeneric;
if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType)type;
classGeneric = (Class)parameterizedType.getActualTypeArguments()[0];
} else {
classGeneric = String.class;
}
CellData cellDataReturn = new CellData(cellData);
cellDataReturn.setData(doConvertToJavaObject(cellData, classGeneric, contentProperty, converterMap,
globalConfiguration, rowIndex, columnIndex));
return cellDataReturn;
}
return doConvertToJavaObject(cellData, clazz, contentProperty, converterMap, globalConfiguration, rowIndex,
columnIndex);
}
/**
*
* @param cellData
* @param clazz
* @param contentProperty
* @param converterMap
* @param globalConfiguration
* @param rowIndex
* @param columnIndex
* @return
*/
private static Object doConvertToJavaObject(CellData cellData, Class clazz, ExcelContentProperty contentProperty,
Map<String, Converter> converterMap, GlobalConfiguration globalConfiguration, Integer rowIndex,
Integer columnIndex) {
Converter converter = null;
if (contentProperty != null) {
converter = contentProperty.getConverter();
@ -75,13 +116,14 @@ public class ConverterUtils {
converter = converterMap.get(ConverterKeyBuild.buildKey(clazz, cellData.getType()));
}
if (converter == null) {
throw new ExcelDataConvertException(
throw new ExcelDataConvertException(rowIndex, columnIndex, contentProperty,
"Converter not found, convert " + cellData.getType() + " to " + clazz.getName());
}
try {
return converter.convertToJavaData(cellData, contentProperty, globalConfiguration);
} catch (Exception e) {
throw new ExcelDataConvertException("Convert data " + cellData + " to " + clazz + " error ", e);
throw new ExcelDataConvertException(rowIndex, columnIndex, contentProperty,
"Convert data " + cellData + " to " + clazz + " error ", e);
}
}
}

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

@ -157,6 +157,15 @@ public class FileUtils {
return directory;
}
public static File createTmpFile(String fileName) {
String tmpDir = System.getProperty(JAVA_IO_TMPDIR);
if (tmpDir == null) {
throw new RuntimeException(
"Systems temporary directory not defined - set the -D" + JAVA_IO_TMPDIR + " jvm property!");
}
return new File(tmpDir, fileName);
}
/**
*
* @param directory

67
src/main/java/com/alibaba/excel/util/SheetUtils.java

@ -0,0 +1,67 @@
package com.alibaba.excel.util;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.read.metadata.ReadSheet;
/**
* Sheet utils
*
* @author Jiaju Zhuang
*/
public class SheetUtils {
private static final Logger LOGGER = LoggerFactory.getLogger(SheetUtils.class);
private SheetUtils() {}
/**
* Match the parameters to the actual sheet
*
* @param readSheet
* actual sheet
* @param parameterReadSheetList
* parameters
* @param readAll
* @return
*/
public static ReadSheet match(ReadSheet readSheet, List<ReadSheet> parameterReadSheetList, Boolean readAll,
GlobalConfiguration globalConfiguration) {
if (readAll) {
return readSheet;
}
for (ReadSheet parameterReadSheet : parameterReadSheetList) {
if (parameterReadSheet == null) {
continue;
}
if (parameterReadSheet.getSheetNo() == null && parameterReadSheet.getSheetName() == null) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("The first is read by default.");
}
parameterReadSheet.setSheetNo(0);
}
boolean match = (parameterReadSheet.getSheetNo() != null
&& parameterReadSheet.getSheetNo().equals(readSheet.getSheetNo()));
if (!match) {
String parameterSheetName = parameterReadSheet.getSheetName();
if (!StringUtils.isEmpty(parameterSheetName)) {
boolean autoTrim = (parameterReadSheet.getAutoTrim() != null && parameterReadSheet.getAutoTrim())
|| (parameterReadSheet.getAutoTrim() == null && globalConfiguration.getAutoTrim());
if (autoTrim) {
parameterSheetName = parameterSheetName.trim();
}
match = parameterSheetName.equals(readSheet.getSheetName());
}
}
if (match) {
readSheet.copyBasicParameter(parameterReadSheet);
return readSheet;
}
}
return null;
}
}

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

@ -6,10 +6,11 @@ package com.alibaba.excel.util;
* @author jipengfei
*/
public class StringUtils {
public static final String EMPTY = "";
private StringUtils() {}
public static boolean isEmpty(Object str) {
return (str == null || "".equals(str));
return (str == null || EMPTY.equals(str));
}
}

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

@ -2,8 +2,8 @@ package com.alibaba.excel.util;
import java.io.IOException;
import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
@ -22,35 +22,35 @@ import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
*/
public class WorkBookUtil {
private static final int ROW_ACCESS_WINDOW_SIZE = 500;
private WorkBookUtil() {}
public static Workbook createWorkBook(WriteWorkbookHolder writeWorkbookHolder)
throws IOException, InvalidFormatException {
public static void createWorkBook(WriteWorkbookHolder writeWorkbookHolder) throws IOException {
if (ExcelTypeEnum.XLSX.equals(writeWorkbookHolder.getExcelType())) {
XSSFWorkbook xssfWorkbook = null;
if (writeWorkbookHolder.getTemplateFile() != null) {
xssfWorkbook = new XSSFWorkbook(writeWorkbookHolder.getTemplateFile());
}
if (writeWorkbookHolder.getTemplateInputStream() != null) {
xssfWorkbook = new XSSFWorkbook(writeWorkbookHolder.getTemplateInputStream());
}
// When using SXSSFWorkbook, you can't get the actual last line.But we need to read the last line when we
// are using the template, so we cache it
if (xssfWorkbook != null) {
for (int i = 0; i < xssfWorkbook.getNumberOfSheets(); i++) {
writeWorkbookHolder.getTemplateLastRowMap().put(i, xssfWorkbook.getSheetAt(i).getLastRowNum());
}
return new SXSSFWorkbook(xssfWorkbook);
if (writeWorkbookHolder.getTempTemplateInputStream() != null) {
XSSFWorkbook xssfWorkbook = new XSSFWorkbook(writeWorkbookHolder.getTempTemplateInputStream());
writeWorkbookHolder.setCachedWorkbook(xssfWorkbook);
writeWorkbookHolder.setWorkbook(new SXSSFWorkbook(xssfWorkbook, ROW_ACCESS_WINDOW_SIZE));
return;
}
return new SXSSFWorkbook(500);
SXSSFWorkbook sxssWorkbook = new SXSSFWorkbook(ROW_ACCESS_WINDOW_SIZE);
writeWorkbookHolder.setCachedWorkbook(sxssWorkbook);
writeWorkbookHolder.setWorkbook(sxssWorkbook);
return;
}
if (writeWorkbookHolder.getTemplateFile() != null) {
return new HSSFWorkbook(new POIFSFileSystem(writeWorkbookHolder.getTemplateFile()));
HSSFWorkbook hssfWorkbook;
if (writeWorkbookHolder.getTempTemplateInputStream() != null) {
hssfWorkbook = new HSSFWorkbook(new POIFSFileSystem(writeWorkbookHolder.getTempTemplateInputStream()));
} else {
hssfWorkbook = new HSSFWorkbook();
}
if (writeWorkbookHolder.getTemplateInputStream() != null) {
return new HSSFWorkbook(new POIFSFileSystem(writeWorkbookHolder.getTemplateInputStream()));
writeWorkbookHolder.setCachedWorkbook(hssfWorkbook);
writeWorkbookHolder.setWorkbook(hssfWorkbook);
if (writeWorkbookHolder.getPassword() != null) {
Biff8EncryptionKey.setCurrentUserPassword(writeWorkbookHolder.getPassword());
hssfWorkbook.writeProtectWorkbook(writeWorkbookHolder.getPassword(), StringUtils.EMPTY);
}
return new HSSFWorkbook();
}
public static Sheet createSheet(Workbook workbook, String sheetName) {

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

@ -0,0 +1,196 @@
package com.alibaba.excel.util;
import java.util.ArrayList;
import java.util.List;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import com.alibaba.excel.context.WriteContext;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.handler.RowWriteHandler;
import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.handler.WorkbookWriteHandler;
import com.alibaba.excel.write.handler.WriteHandler;
/**
* Write handler utils
*
* @author Jiaju Zhuang
*/
public class WriteHandlerUtils {
private WriteHandlerUtils() {}
public static void beforeWorkbookCreate(WriteContext writeContext) {
List<WriteHandler> handlerList =
writeContext.writeWorkbookHolder().writeHandlerMap().get(WorkbookWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof WorkbookWriteHandler) {
((WorkbookWriteHandler)writeHandler).beforeWorkbookCreate();
}
}
}
public static void afterWorkbookCreate(WriteContext writeContext) {
List<WriteHandler> handlerList =
writeContext.writeWorkbookHolder().writeHandlerMap().get(WorkbookWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof WorkbookWriteHandler) {
((WorkbookWriteHandler)writeHandler).afterWorkbookCreate(writeContext.writeWorkbookHolder());
}
}
}
public static void afterWorkbookDispose(WriteContext writeContext) {
List<WriteHandler> handlerList =
writeContext.writeWorkbookHolder().writeHandlerMap().get(WorkbookWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof WorkbookWriteHandler) {
((WorkbookWriteHandler)writeHandler).afterWorkbookDispose(writeContext.writeWorkbookHolder());
}
}
}
public static void beforeSheetCreate(WriteContext writeContext) {
List<WriteHandler> handlerList = writeContext.writeSheetHolder().writeHandlerMap().get(SheetWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof SheetWriteHandler) {
((SheetWriteHandler)writeHandler).beforeSheetCreate(writeContext.writeWorkbookHolder(),
writeContext.writeSheetHolder());
}
}
}
public static void afterSheetCreate(WriteContext writeContext) {
List<WriteHandler> handlerList = writeContext.writeSheetHolder().writeHandlerMap().get(SheetWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof SheetWriteHandler) {
((SheetWriteHandler)writeHandler).afterSheetCreate(writeContext.writeWorkbookHolder(),
writeContext.writeSheetHolder());
}
}
if (null != writeContext.writeWorkbookHolder().getWriteWorkbook().getWriteHandler()) {
writeContext.writeWorkbookHolder().getWriteWorkbook().getWriteHandler()
.sheet(writeContext.writeSheetHolder().getSheetNo(), writeContext.writeSheetHolder().getSheet());
}
}
public static void beforeCellCreate(WriteContext writeContext, Row row, Head head, Integer columnIndex,
Integer relativeRowIndex, Boolean isHead) {
List<WriteHandler> handlerList =
writeContext.currentWriteHolder().writeHandlerMap().get(CellWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof CellWriteHandler) {
((CellWriteHandler)writeHandler).beforeCellCreate(writeContext.writeSheetHolder(),
writeContext.writeTableHolder(), row, head, columnIndex, relativeRowIndex, isHead);
}
}
}
public static void afterCellCreate(WriteContext writeContext, Cell cell, Head head, Integer relativeRowIndex,
Boolean isHead) {
List<WriteHandler> handlerList =
writeContext.currentWriteHolder().writeHandlerMap().get(CellWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof CellWriteHandler) {
((CellWriteHandler)writeHandler).afterCellCreate(writeContext.writeSheetHolder(),
writeContext.writeTableHolder(), cell, head, relativeRowIndex, isHead);
}
}
}
public static void afterCellDispose(WriteContext writeContext, CellData cellData, Cell cell, Head head,
Integer relativeRowIndex, Boolean isHead) {
List<CellData> cellDataList = new ArrayList<CellData>();
if (cell != null) {
cellDataList.add(cellData);
}
afterCellDispose(writeContext, cellDataList, cell, head, relativeRowIndex, isHead);
}
public static void afterCellDispose(WriteContext writeContext, List<CellData> cellDataList, Cell cell, Head head,
Integer relativeRowIndex, Boolean isHead) {
List<WriteHandler> handlerList =
writeContext.currentWriteHolder().writeHandlerMap().get(CellWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof CellWriteHandler) {
((CellWriteHandler)writeHandler).afterCellDispose(writeContext.writeSheetHolder(),
writeContext.writeTableHolder(), cellDataList, cell, head, relativeRowIndex, isHead);
}
}
if (null != writeContext.writeWorkbookHolder().getWriteWorkbook().getWriteHandler()) {
writeContext.writeWorkbookHolder().getWriteWorkbook().getWriteHandler().cell(cell.getRowIndex(), cell);
}
}
public static void beforeRowCreate(WriteContext writeContext, Integer rowIndex, Integer relativeRowIndex,
Boolean isHead) {
List<WriteHandler> handlerList = writeContext.currentWriteHolder().writeHandlerMap().get(RowWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof RowWriteHandler) {
((RowWriteHandler)writeHandler).beforeRowCreate(writeContext.writeSheetHolder(),
writeContext.writeTableHolder(), rowIndex, relativeRowIndex, isHead);
}
}
}
public static void afterRowCreate(WriteContext writeContext, Row row, Integer relativeRowIndex, Boolean isHead) {
List<WriteHandler> handlerList = writeContext.currentWriteHolder().writeHandlerMap().get(RowWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof RowWriteHandler) {
((RowWriteHandler)writeHandler).afterRowCreate(writeContext.writeSheetHolder(),
writeContext.writeTableHolder(), row, relativeRowIndex, isHead);
}
}
}
public static void afterRowDispose(WriteContext writeContext, Row row, Integer relativeRowIndex, Boolean isHead) {
List<WriteHandler> handlerList = writeContext.currentWriteHolder().writeHandlerMap().get(RowWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof RowWriteHandler) {
((RowWriteHandler)writeHandler).afterRowDispose(writeContext.writeSheetHolder(),
writeContext.writeTableHolder(), row, relativeRowIndex, isHead);
}
}
if (null != writeContext.writeWorkbookHolder().getWriteWorkbook().getWriteHandler()) {
writeContext.writeWorkbookHolder().getWriteWorkbook().getWriteHandler().row(row.getRowNum(), row);
}
}
}

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

@ -6,6 +6,7 @@ import com.alibaba.excel.context.WriteContext;
import com.alibaba.excel.write.merge.OnceAbsoluteMergeStrategy;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.WriteTable;
import com.alibaba.excel.write.metadata.fill.FillConfig;
/**
* @author jipengfei
@ -36,6 +37,15 @@ public interface ExcelBuilder {
*/
void addContent(List data, WriteSheet writeSheet, WriteTable writeTable);
/**
* WorkBook fill value
*
* @param data
* @param fillConfig
* @param writeSheet
*/
void fill(Object data, FillConfig fillConfig, WriteSheet writeSheet);
/**
* Creates new cell range. Indexes are zero-based.
*
@ -63,4 +73,13 @@ public interface ExcelBuilder {
* Close io
*/
void finish();
/**
* add password
* @param data
* @param writeSheet
* @param writeTable
* @param password
*/
void addContent(List data, WriteSheet writeSheet, WriteTable writeTable, String password);
}

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

@ -1,46 +1,20 @@
package com.alibaba.excel.write;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.ss.usermodel.Drawing;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;
import com.alibaba.excel.context.WriteContext;
import com.alibaba.excel.context.WriteContextImpl;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.converters.ConverterKeyBuild;
import com.alibaba.excel.enums.HeadKindEnum;
import com.alibaba.excel.exception.ExcelDataConvertException;
import com.alibaba.excel.enums.WriteTypeEnum;
import com.alibaba.excel.exception.ExcelGenerateException;
import com.alibaba.excel.metadata.BaseRowModel;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.excel.util.FileUtils;
import com.alibaba.excel.util.WorkBookUtil;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.handler.RowWriteHandler;
import com.alibaba.excel.write.handler.WriteHandler;
import com.alibaba.excel.write.executor.ExcelWriteAddExecutor;
import com.alibaba.excel.write.executor.ExcelWriteFillExecutor;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.WriteTable;
import com.alibaba.excel.write.metadata.WriteWorkbook;
import com.alibaba.excel.write.metadata.holder.WriteHolder;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import net.sf.cglib.beans.BeanMap;
import com.alibaba.excel.write.metadata.fill.FillConfig;
/**
* @author jipengfei
@ -48,6 +22,8 @@ import net.sf.cglib.beans.BeanMap;
public class ExcelBuilderImpl implements ExcelBuilder {
private WriteContext context;
private ExcelWriteFillExecutor excelWriteFillExecutor;
private ExcelWriteAddExecutor excelWriteAddExecutor;
public ExcelBuilderImpl(WriteWorkbook writeWorkbook) {
try {
@ -63,23 +39,6 @@ public class ExcelBuilderImpl implements ExcelBuilder {
}
}
private void doAddContent(List data) {
if (CollectionUtils.isEmpty(data)) {
return;
}
WriteSheetHolder writeSheetHolder = context.writeSheetHolder();
int newRowIndex = writeSheetHolder.getNewRowIndexAndStartDoWrite();
if (writeSheetHolder.isNew() && !writeSheetHolder.getExcelWriteHeadProperty().hasHead()) {
newRowIndex += context.currentWriteHolder().relativeHeadRowIndex();
}
// BeanMap is out of order,so use fieldList
List<Field> fieldList = new ArrayList<Field>();
for (int relativeRowIndex = 0; relativeRowIndex < data.size(); relativeRowIndex++) {
int n = relativeRowIndex + newRowIndex;
addOneRowOfDataToExcel(data.get(relativeRowIndex), n, relativeRowIndex, fieldList);
}
}
@Override
public void addContent(List data, WriteSheet writeSheet) {
addContent(data, writeSheet, null);
@ -88,9 +47,15 @@ public class ExcelBuilderImpl implements ExcelBuilder {
@Override
public void addContent(List data, WriteSheet writeSheet, WriteTable writeTable) {
try {
context.currentSheet(writeSheet);
if (data == null) {
return;
}
context.currentSheet(writeSheet, WriteTypeEnum.ADD);
context.currentTable(writeTable);
doAddContent(data);
if (excelWriteAddExecutor == null) {
excelWriteAddExecutor = new ExcelWriteAddExecutor(context);
}
excelWriteAddExecutor.add(data);
} catch (RuntimeException e) {
finish();
throw e;
@ -101,278 +66,64 @@ public class ExcelBuilderImpl implements ExcelBuilder {
}
@Override
public void finish() {
if (context != null) {
context.finish();
}
}
@Override
public void merge(int firstRow, int lastRow, int firstCol, int lastCol) {
CellRangeAddress cra = new CellRangeAddress(firstRow, lastRow, firstCol, lastCol);
context.writeSheetHolder().getSheet().addMergedRegion(cra);
}
@Override
public WriteContext writeContext() {
return context;
}
private void addOneRowOfDataToExcel(Object oneRowData, int n, int relativeRowIndex, List<Field> fieldList) {
beforeRowCreate(n, relativeRowIndex);
Row row = WorkBookUtil.createRow(context.writeSheetHolder().getSheet(), n);
afterRowCreate(row, relativeRowIndex);
if (oneRowData instanceof List) {
addBasicTypeToExcel((List)oneRowData, row, relativeRowIndex);
} else {
addJavaObjectToExcel(oneRowData, row, relativeRowIndex, fieldList);
}
}
private void beforeRowCreate(int rowIndex, int relativeRowIndex) {
List<WriteHandler> handlerList = context.currentWriteHolder().writeHandlerMap().get(RowWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof RowWriteHandler) {
((RowWriteHandler)writeHandler).beforeRowCreate(context.writeSheetHolder(), context.writeTableHolder(),
rowIndex, relativeRowIndex, false);
}
}
}
private void afterRowCreate(Row row, int relativeRowIndex) {
List<WriteHandler> handlerList = context.currentWriteHolder().writeHandlerMap().get(RowWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof RowWriteHandler) {
((RowWriteHandler)writeHandler).afterRowCreate(context.writeSheetHolder(), context.writeTableHolder(),
row, relativeRowIndex, false);
}
}
if (null != context.writeWorkbookHolder().getWriteWorkbook().getWriteHandler()) {
context.writeWorkbookHolder().getWriteWorkbook().getWriteHandler().row(row.getRowNum(), row);
}
}
private void addBasicTypeToExcel(List<Object> oneRowData, Row row, int relativeRowIndex) {
if (CollectionUtils.isEmpty(oneRowData)) {
return;
}
Map<Integer, Head> headMap = context.currentWriteHolder().excelWriteHeadProperty().getHeadMap();
int dataIndex = 0;
int cellIndex = 0;
for (Map.Entry<Integer, Head> entry : headMap.entrySet()) {
if (dataIndex >= oneRowData.size()) {
return;
}
cellIndex = entry.getKey();
Head head = entry.getValue();
doAddBasicTypeToExcel(oneRowData, head, row, relativeRowIndex, dataIndex++, cellIndex);
}
// Finish
if (dataIndex >= oneRowData.size()) {
return;
}
if (cellIndex != 0) {
cellIndex++;
}
int size = oneRowData.size() - dataIndex;
for (int i = 0; i < size; i++) {
doAddBasicTypeToExcel(oneRowData, null, row, relativeRowIndex, dataIndex++, cellIndex++);
}
}
private void doAddBasicTypeToExcel(List<Object> oneRowData, Head head, Row row, int relativeRowIndex, int dataIndex,
int cellIndex) {
beforeCellCreate(row, head, relativeRowIndex);
Cell cell = WorkBookUtil.createCell(row, cellIndex);
Object value = oneRowData.get(dataIndex);
CellData cellData =
converterAndSet(context.currentWriteHolder(), value == null ? null : value.getClass(), cell, value, null);
afterCellCreate(head, cellData, cell, relativeRowIndex);
}
private void addJavaObjectToExcel(Object oneRowData, Row row, int relativeRowIndex, List<Field> fieldList) {
WriteHolder currentWriteHolder = context.currentWriteHolder();
BeanMap beanMap = BeanMap.create(oneRowData);
Set<String> beanMapHandledSet = new HashSet<String>();
int cellIndex = 0;
// If it's a class it needs to be cast by type
if (HeadKindEnum.CLASS.equals(context.currentWriteHolder().excelWriteHeadProperty().getHeadKind())) {
Map<Integer, Head> headMap = context.currentWriteHolder().excelWriteHeadProperty().getHeadMap();
Map<Integer, ExcelContentProperty> contentPropertyMap =
context.currentWriteHolder().excelWriteHeadProperty().getContentPropertyMap();
for (Map.Entry<Integer, ExcelContentProperty> entry : contentPropertyMap.entrySet()) {
cellIndex = entry.getKey();
ExcelContentProperty excelContentProperty = entry.getValue();
String name = excelContentProperty.getField().getName();
if (!beanMap.containsKey(name)) {
continue;
}
Head head = headMap.get(cellIndex);
beforeCellCreate(row, head, relativeRowIndex);
Cell cell = WorkBookUtil.createCell(row, cellIndex);
Object value = beanMap.get(name);
CellData cellData = converterAndSet(currentWriteHolder, excelContentProperty.getField().getType(), cell,
value, excelContentProperty);
afterCellCreate(head, cellData, cell, relativeRowIndex);
beanMapHandledSet.add(name);
}
}
// Finish
if (beanMapHandledSet.size() == beanMap.size()) {
public void fill(Object data, FillConfig fillConfig, WriteSheet writeSheet) {
try {
if (data == null) {
return;
}
if (cellIndex != 0) {
cellIndex++;
}
Map<String, Field> ignoreMap = context.currentWriteHolder().excelWriteHeadProperty().getIgnoreMap();
initFieldList(oneRowData.getClass(), fieldList);
for (Field field : fieldList) {
String filedName = field.getName();
boolean uselessData = !beanMap.containsKey(filedName) || beanMapHandledSet.contains(filedName)
|| ignoreMap.containsKey(filedName);
if (uselessData) {
continue;
}
Object value = beanMap.get(filedName);
if (value == null) {
continue;
}
beforeCellCreate(row, null, relativeRowIndex);
Cell cell = WorkBookUtil.createCell(row, cellIndex++);
CellData cellData = converterAndSet(currentWriteHolder, value.getClass(), cell, value, null);
afterCellCreate(null, cellData, cell, relativeRowIndex);
if (context.writeWorkbookHolder().getTempTemplateInputStream() == null) {
throw new ExcelGenerateException("Calling the 'fill' method must use a template.");
}
context.currentSheet(writeSheet, WriteTypeEnum.FILL);
if (excelWriteFillExecutor == null) {
excelWriteFillExecutor = new ExcelWriteFillExecutor(context);
}
private void initFieldList(Class clazz, List<Field> fieldList) {
if (!fieldList.isEmpty()) {
return;
}
Class tempClass = clazz;
while (tempClass != null) {
if (tempClass != BaseRowModel.class) {
Collections.addAll(fieldList, tempClass.getDeclaredFields());
}
tempClass = tempClass.getSuperclass();
excelWriteFillExecutor.fill(data, fillConfig);
} catch (RuntimeException e) {
finish();
throw e;
} catch (Throwable e) {
finish();
throw new ExcelGenerateException(e);
}
}
private void beforeCellCreate(Row row, Head head, int relativeRowIndex) {
List<WriteHandler> handlerList = context.currentWriteHolder().writeHandlerMap().get(CellWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof CellWriteHandler) {
((CellWriteHandler)writeHandler).beforeCellCreate(context.writeSheetHolder(),
context.writeTableHolder(), row, head, relativeRowIndex, false);
}
@Override
public void finish() {
if (context != null) {
context.finish();
}
}
private void afterCellCreate(Head head, CellData cellData, Cell cell, int relativeRowIndex) {
List<WriteHandler> handlerList = context.currentWriteHolder().writeHandlerMap().get(CellWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
@Override
public void addContent(List data, WriteSheet writeSheet, WriteTable writeTable, String password) {
try {
if (data == null) {
return;
}
for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof CellWriteHandler) {
((CellWriteHandler)writeHandler).afterCellCreate(context.writeSheetHolder(), context.writeTableHolder(),
cellData, cell, head, relativeRowIndex, false);
}
}
if (null != context.writeWorkbookHolder().getWriteWorkbook().getWriteHandler()) {
context.writeWorkbookHolder().getWriteWorkbook().getWriteHandler().cell(cell.getRowIndex(), cell);
}
}
private CellData converterAndSet(WriteHolder currentWriteHolder, Class clazz, Cell cell, Object value,
ExcelContentProperty excelContentProperty) {
if (value == null) {
return null;
}
if (value instanceof String && currentWriteHolder.globalConfiguration().getAutoTrim()) {
value = ((String)value).trim();
}
CellData cellData = convert(currentWriteHolder, clazz, cell, value, excelContentProperty);
if (cellData == null || cellData.getType() == null) {
throw new ExcelDataConvertException(
"Convert data:" + value + " return null,at row:" + cell.getRow().getRowNum());
}
if (cellData.getFormula() != null && cellData.getFormula()) {
cell.setCellFormula(cellData.getFormulaValue());
context.currentSheet(writeSheet, WriteTypeEnum.ADD);
context.currentTable(writeTable);
if (excelWriteAddExecutor == null) {
excelWriteAddExecutor = new ExcelWriteAddExecutor(context);
}
switch (cellData.getType()) {
case STRING:
cell.setCellValue(cellData.getStringValue());
return cellData;
case BOOLEAN:
cell.setCellValue(cellData.getBooleanValue());
return cellData;
case NUMBER:
cell.setCellValue(cellData.getNumberValue().doubleValue());
return cellData;
case IMAGE:
setImageValue(cellData, cell);
return cellData;
default:
throw new ExcelDataConvertException("Not supported data:" + value + " return type:" + cell.getCellType()
+ "at row:" + cell.getRow().getRowNum());
excelWriteAddExecutor.add(data);
} catch (RuntimeException e) {
finish();
throw e;
} catch (Throwable e) {
finish();
throw new ExcelGenerateException(e);
}
}
private void setImageValue(CellData cellData, Cell cell) {
Sheet sheet = cell.getSheet();
int index = sheet.getWorkbook().addPicture(cellData.getImageValue(), HSSFWorkbook.PICTURE_TYPE_PNG);
Drawing drawing = sheet.getDrawingPatriarch();
if (drawing == null) {
drawing = sheet.createDrawingPatriarch();
}
CreationHelper helper = sheet.getWorkbook().getCreationHelper();
ClientAnchor anchor = helper.createClientAnchor();
anchor.setDx1(0);
anchor.setDx2(0);
anchor.setDy1(0);
anchor.setDy2(0);
anchor.setCol1(cell.getColumnIndex());
anchor.setCol2(cell.getColumnIndex() + 1);
anchor.setRow1(cell.getRowIndex());
anchor.setRow2(cell.getRowIndex() + 1);
anchor.setAnchorType(ClientAnchor.AnchorType.DONT_MOVE_AND_RESIZE);
drawing.createPicture(anchor, index);
@Override
public void merge(int firstRow, int lastRow, int firstCol, int lastCol) {
CellRangeAddress cra = new CellRangeAddress(firstRow, lastRow, firstCol, lastCol);
context.writeSheetHolder().getSheet().addMergedRegion(cra);
}
private CellData convert(WriteHolder currentWriteHolder, Class clazz, Cell cell, Object value,
ExcelContentProperty excelContentProperty) {
if (value instanceof CellData) {
return (CellData)value;
}
Converter converter = null;
if (excelContentProperty != null) {
converter = excelContentProperty.getConverter();
}
if (converter == null) {
converter = currentWriteHolder.converterMap().get(ConverterKeyBuild.buildKey(clazz));
}
if (converter == null) {
throw new ExcelDataConvertException(
"Can not find 'Converter' support class " + clazz.getSimpleName() + ".");
}
CellData cellData;
try {
cellData =
converter.convertToExcelData(value, excelContentProperty, currentWriteHolder.globalConfiguration());
} catch (Exception e) {
throw new ExcelDataConvertException("Convert data:" + value + " error,at row:" + cell.getRow().getRowNum(),
e);
}
return cellData;
@Override
public WriteContext writeContext() {
return context;
}
}

24
src/main/java/com/alibaba/excel/write/builder/ExcelWriterBuilder.java

@ -79,6 +79,30 @@ public class ExcelWriterBuilder {
return this;
}
/**
* Use the default style.Default is true.
*
* @param useDefaultStyle
* @return
*/
public ExcelWriterBuilder useDefaultStyle(Boolean useDefaultStyle) {
writeWorkbook.setUseDefaultStyle(useDefaultStyle);
return this;
}
/**
* Whether the encryption.
* <p>
* WARRING:Encryption is when the entire file is read into memory, so it is very memory intensive.
*
* @param password
* @return
*/
public ExcelWriterBuilder password(String password) {
writeWorkbook.setPassword(password);
return this;
}
/**
* The default is all excel objects.if true , you can use {@link com.alibaba.excel.annotation.ExcelIgnore} ignore a
* field. if false , you must use {@link com.alibaba.excel.annotation.ExcelProperty} to use a filed.

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

@ -8,6 +8,7 @@ import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.exception.ExcelGenerateException;
import com.alibaba.excel.write.handler.WriteHandler;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
/**
* Build sheet
@ -73,6 +74,17 @@ public class ExcelWriterSheetBuilder {
return this;
}
/**
* Use the default style.Default is true.
*
* @param useDefaultStyle
* @return
*/
public ExcelWriterSheetBuilder useDefaultStyle(Boolean useDefaultStyle) {
writeSheet.setUseDefaultStyle(useDefaultStyle);
return this;
}
/**
* Custom type conversions override the default.
*
@ -135,6 +147,18 @@ public class ExcelWriterSheetBuilder {
excelWriter.finish();
}
public void doFill(Object data) {
doFill(data, null);
}
public void doFill(Object data, FillConfig fillConfig) {
if (excelWriter == null) {
throw new ExcelGenerateException("Must use 'EasyExcelFactory.write().sheet()' to call this method");
}
excelWriter.fill(data, fillConfig, build());
excelWriter.finish();
}
public ExcelWriterTableBuilder table() {
return table(null);
}

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

@ -78,6 +78,17 @@ public class ExcelWriterTableBuilder {
return this;
}
/**
* Use the default style.Default is true.
*
* @param useDefaultStyle
* @return
*/
public ExcelWriterTableBuilder useDefaultStyle(Boolean useDefaultStyle) {
writeTable.setUseDefaultStyle(useDefaultStyle);
return this;
}
/**
* Custom type conversions override the default.
*

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

@ -0,0 +1,140 @@
package com.alibaba.excel.write.executor;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.ss.usermodel.Drawing;
import org.apache.poi.ss.usermodel.Sheet;
import com.alibaba.excel.context.WriteContext;
import com.alibaba.excel.converters.Converter;
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.property.ExcelContentProperty;
import com.alibaba.excel.write.metadata.holder.WriteHolder;
/**
* Excel write Executor
*
* @author Jiaju Zhuang
*/
public abstract class AbstractExcelWriteExecutor implements ExcelWriteExecutor {
protected WriteContext writeContext;
public AbstractExcelWriteExecutor(WriteContext writeContext) {
this.writeContext = writeContext;
}
protected CellData converterAndSet(WriteHolder currentWriteHolder, Class clazz, Cell cell, Object value,
ExcelContentProperty excelContentProperty) {
if (value == null) {
return new CellData();
}
if (value instanceof String && currentWriteHolder.globalConfiguration().getAutoTrim()) {
value = ((String)value).trim();
}
CellData cellData = convert(currentWriteHolder, clazz, cell, value, excelContentProperty);
if (cellData.getFormula() != null && cellData.getFormula()) {
cell.setCellFormula(cellData.getFormulaValue());
}
switch (cellData.getType()) {
case STRING:
cell.setCellValue(cellData.getStringValue());
return cellData;
case BOOLEAN:
cell.setCellValue(cellData.getBooleanValue());
return cellData;
case NUMBER:
cell.setCellValue(cellData.getNumberValue().doubleValue());
return cellData;
case IMAGE:
setImageValue(cellData, cell);
return cellData;
case EMPTY:
return cellData;
default:
throw new ExcelDataConvertException("Not supported data:" + value + " return type:" + cell.getCellType()
+ "at row:" + cell.getRow().getRowNum());
}
}
protected CellData convert(WriteHolder currentWriteHolder, Class clazz, Cell cell, Object value,
ExcelContentProperty excelContentProperty) {
if (value == null) {
return new CellData();
}
// This means that the user has defined the data.
if (value instanceof CellData) {
CellData cellDataValue = (CellData)value;
if (cellDataValue.getType() != null) {
return cellDataValue;
} else {
if (cellDataValue.getData() == null) {
cellDataValue.setType(CellDataTypeEnum.EMPTY);
return cellDataValue;
}
}
CellData cellDataReturn = doConvert(currentWriteHolder, cellDataValue.getData().getClass(), cell,
cellDataValue.getData(), excelContentProperty);
// The formula information is subject to user input
if (cellDataValue.getFormula() != null) {
cellDataReturn.setFormula(cellDataValue.getFormula());
cellDataReturn.setFormulaValue(cellDataValue.getFormulaValue());
}
return cellDataReturn;
}
return doConvert(currentWriteHolder, clazz, cell, value, excelContentProperty);
}
private CellData doConvert(WriteHolder currentWriteHolder, Class clazz, Cell cell, Object value,
ExcelContentProperty excelContentProperty) {
Converter converter = null;
if (excelContentProperty != null) {
converter = excelContentProperty.getConverter();
}
if (converter == null) {
converter = currentWriteHolder.converterMap().get(ConverterKeyBuild.buildKey(clazz));
}
if (converter == null) {
throw new ExcelDataConvertException(
"Can not find 'Converter' support class " + clazz.getSimpleName() + ".");
}
CellData cellData;
try {
cellData =
converter.convertToExcelData(value, excelContentProperty, currentWriteHolder.globalConfiguration());
} catch (Exception e) {
throw new ExcelDataConvertException("Convert data:" + value + " error,at row:" + cell.getRow().getRowNum(),
e);
}
if (cellData == null || cellData.getType() == null) {
throw new ExcelDataConvertException(
"Convert data:" + value + " return null,at row:" + cell.getRow().getRowNum());
}
return cellData;
}
private void setImageValue(CellData cellData, Cell cell) {
Sheet sheet = cell.getSheet();
int index = sheet.getWorkbook().addPicture(cellData.getImageValue(), HSSFWorkbook.PICTURE_TYPE_PNG);
Drawing drawing = sheet.getDrawingPatriarch();
if (drawing == null) {
drawing = sheet.createDrawingPatriarch();
}
CreationHelper helper = sheet.getWorkbook().getCreationHelper();
ClientAnchor anchor = helper.createClientAnchor();
anchor.setDx1(0);
anchor.setDx2(0);
anchor.setDy1(0);
anchor.setDy2(0);
anchor.setCol1(cell.getColumnIndex());
anchor.setCol2(cell.getColumnIndex() + 1);
anchor.setRow1(cell.getRowIndex());
anchor.setRow2(cell.getRowIndex() + 1);
anchor.setAnchorType(ClientAnchor.AnchorType.DONT_MOVE_AND_RESIZE);
drawing.createPicture(anchor, index);
}
}

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

@ -0,0 +1,179 @@
package com.alibaba.excel.write.executor;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import com.alibaba.excel.context.WriteContext;
import com.alibaba.excel.enums.HeadKindEnum;
import com.alibaba.excel.metadata.BaseRowModel;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.excel.util.WorkBookUtil;
import com.alibaba.excel.util.WriteHandlerUtils;
import com.alibaba.excel.write.metadata.holder.WriteHolder;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import net.sf.cglib.beans.BeanMap;
/**
* Add the data into excel
*
* @author Jiaju Zhuang
*/
public class ExcelWriteAddExecutor extends AbstractExcelWriteExecutor {
public ExcelWriteAddExecutor(WriteContext writeContext) {
super(writeContext);
}
public void add(List data) {
if (CollectionUtils.isEmpty(data)) {
return;
}
WriteSheetHolder writeSheetHolder = writeContext.writeSheetHolder();
int newRowIndex = writeSheetHolder.getNewRowIndexAndStartDoWrite();
if (writeSheetHolder.isNew() && !writeSheetHolder.getExcelWriteHeadProperty().hasHead()) {
newRowIndex += writeContext.currentWriteHolder().relativeHeadRowIndex();
}
// BeanMap is out of order,so use fieldList
List<Field> fieldList = new ArrayList<Field>();
for (int relativeRowIndex = 0; relativeRowIndex < data.size(); relativeRowIndex++) {
int n = relativeRowIndex + newRowIndex;
addOneRowOfDataToExcel(data.get(relativeRowIndex), n, relativeRowIndex, fieldList);
}
}
private void addOneRowOfDataToExcel(Object oneRowData, int n, int relativeRowIndex, List<Field> fieldList) {
if (oneRowData == null) {
return;
}
WriteHandlerUtils.beforeRowCreate(writeContext, n, relativeRowIndex, Boolean.FALSE);
Row row = WorkBookUtil.createRow(writeContext.writeSheetHolder().getSheet(), n);
WriteHandlerUtils.afterRowCreate(writeContext, row, relativeRowIndex, Boolean.FALSE);
if (oneRowData instanceof List) {
addBasicTypeToExcel((List)oneRowData, row, relativeRowIndex);
} else {
addJavaObjectToExcel(oneRowData, row, relativeRowIndex, fieldList);
}
WriteHandlerUtils.afterRowDispose(writeContext, row, relativeRowIndex, Boolean.FALSE);
}
private void addBasicTypeToExcel(List<Object> oneRowData, Row row, int relativeRowIndex) {
if (CollectionUtils.isEmpty(oneRowData)) {
return;
}
Map<Integer, Head> headMap = writeContext.currentWriteHolder().excelWriteHeadProperty().getHeadMap();
int dataIndex = 0;
int cellIndex = 0;
for (Map.Entry<Integer, Head> entry : headMap.entrySet()) {
if (dataIndex >= oneRowData.size()) {
return;
}
cellIndex = entry.getKey();
Head head = entry.getValue();
doAddBasicTypeToExcel(oneRowData, head, row, relativeRowIndex, dataIndex++, cellIndex);
}
// Finish
if (dataIndex >= oneRowData.size()) {
return;
}
if (cellIndex != 0) {
cellIndex++;
}
int size = oneRowData.size() - dataIndex;
for (int i = 0; i < size; i++) {
doAddBasicTypeToExcel(oneRowData, null, row, relativeRowIndex, dataIndex++, cellIndex++);
}
}
private void doAddBasicTypeToExcel(List<Object> oneRowData, Head head, Row row, int relativeRowIndex, int dataIndex,
int cellIndex) {
WriteHandlerUtils.beforeCellCreate(writeContext, row, head, cellIndex, relativeRowIndex, Boolean.FALSE);
Cell cell = WorkBookUtil.createCell(row, cellIndex);
WriteHandlerUtils.afterCellCreate(writeContext, cell, head, relativeRowIndex, Boolean.FALSE);
Object value = oneRowData.get(dataIndex);
CellData cellData = converterAndSet(writeContext.currentWriteHolder(), value == null ? null : value.getClass(),
cell, value, null);
WriteHandlerUtils.afterCellDispose(writeContext, cellData, cell, head, relativeRowIndex, Boolean.FALSE);
}
private void addJavaObjectToExcel(Object oneRowData, Row row, int relativeRowIndex, List<Field> fieldList) {
WriteHolder currentWriteHolder = writeContext.currentWriteHolder();
BeanMap beanMap = BeanMap.create(oneRowData);
Set<String> beanMapHandledSet = new HashSet<String>();
int cellIndex = 0;
// If it's a class it needs to be cast by type
if (HeadKindEnum.CLASS.equals(writeContext.currentWriteHolder().excelWriteHeadProperty().getHeadKind())) {
Map<Integer, Head> headMap = writeContext.currentWriteHolder().excelWriteHeadProperty().getHeadMap();
Map<Integer, ExcelContentProperty> contentPropertyMap =
writeContext.currentWriteHolder().excelWriteHeadProperty().getContentPropertyMap();
for (Map.Entry<Integer, ExcelContentProperty> entry : contentPropertyMap.entrySet()) {
cellIndex = entry.getKey();
ExcelContentProperty excelContentProperty = entry.getValue();
String name = excelContentProperty.getField().getName();
if (!beanMap.containsKey(name)) {
continue;
}
Head head = headMap.get(cellIndex);
WriteHandlerUtils.beforeCellCreate(writeContext, row, head, cellIndex, relativeRowIndex, Boolean.FALSE);
Cell cell = WorkBookUtil.createCell(row, cellIndex);
WriteHandlerUtils.afterCellCreate(writeContext, cell, head, relativeRowIndex, Boolean.FALSE);
Object value = beanMap.get(name);
CellData cellData = converterAndSet(currentWriteHolder, excelContentProperty.getField().getType(), cell,
value, excelContentProperty);
WriteHandlerUtils.afterCellDispose(writeContext, cellData, cell, head, relativeRowIndex, Boolean.FALSE);
beanMapHandledSet.add(name);
}
}
// Finish
if (beanMapHandledSet.size() == beanMap.size()) {
return;
}
if (cellIndex != 0) {
cellIndex++;
}
Map<String, Field> ignoreMap = writeContext.currentWriteHolder().excelWriteHeadProperty().getIgnoreMap();
initFieldList(oneRowData.getClass(), fieldList);
for (Field field : fieldList) {
String filedName = field.getName();
boolean uselessData = !beanMap.containsKey(filedName) || beanMapHandledSet.contains(filedName)
|| ignoreMap.containsKey(filedName);
if (uselessData) {
continue;
}
Object value = beanMap.get(filedName);
if (value == null) {
continue;
}
WriteHandlerUtils.beforeCellCreate(writeContext, row, null, cellIndex, relativeRowIndex, Boolean.FALSE);
Cell cell = WorkBookUtil.createCell(row, cellIndex++);
WriteHandlerUtils.afterCellCreate(writeContext, cell, null, relativeRowIndex, Boolean.FALSE);
CellData cellData = converterAndSet(currentWriteHolder, value.getClass(), cell, value, null);
WriteHandlerUtils.afterCellDispose(writeContext, cellData, cell, null, relativeRowIndex, Boolean.FALSE);
}
}
private void initFieldList(Class clazz, List<Field> fieldList) {
if (!fieldList.isEmpty()) {
return;
}
Class tempClass = clazz;
while (tempClass != null) {
if (tempClass != BaseRowModel.class) {
Collections.addAll(fieldList, tempClass.getDeclaredFields());
}
tempClass = tempClass.getSuperclass();
}
}
}

9
src/main/java/com/alibaba/excel/write/executor/ExcelWriteExecutor.java

@ -0,0 +1,9 @@
package com.alibaba.excel.write.executor;
/**
* Excel write Executor
*
* @author Jiaju Zhuang
*/
public interface ExcelWriteExecutor {
}

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

@ -0,0 +1,377 @@
package com.alibaba.excel.write.executor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import com.alibaba.excel.context.WriteContext;
import com.alibaba.excel.enums.WriteDirectionEnum;
import com.alibaba.excel.enums.WriteTemplateAnalysisCellTypeEnum;
import com.alibaba.excel.exception.ExcelGenerateException;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.excel.util.StringUtils;
import com.alibaba.excel.util.WriteHandlerUtils;
import com.alibaba.excel.write.metadata.fill.AnalysisCell;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import net.sf.cglib.beans.BeanMap;
/**
* Fill the data into excel
*
* @author Jiaju Zhuang
*/
public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor {
private static final String ESCAPE_FILL_PREFIX = "\\\\\\{";
private static final String ESCAPE_FILL_SUFFIX = "\\\\\\}";
private static final String FILL_PREFIX = "{";
private static final String FILL_SUFFIX = "}";
private static final char IGNORE_CHAR = '\\';
private static final String COLLECTION_PREFIX = ".";
/**
* Fields to replace in the template
*/
private Map<Integer, List<AnalysisCell>> templateAnalysisCache = new HashMap<Integer, List<AnalysisCell>>(8);
/**
* Collection fields to replace in the template
*/
private Map<Integer, List<AnalysisCell>> templateCollectionAnalysisCache =
new HashMap<Integer, List<AnalysisCell>>(8);
/**
* Style cache for collection fields
*/
private Map<Integer, Map<AnalysisCell, CellStyle>> collectionFieldStyleCache =
new HashMap<Integer, Map<AnalysisCell, CellStyle>>(8);
/**
* Last index cache for collection fields
*/
private Map<Integer, Map<AnalysisCell, Integer>> collectionLastIndexCache =
new HashMap<Integer, Map<AnalysisCell, Integer>>(8);
public ExcelWriteFillExecutor(WriteContext writeContext) {
super(writeContext);
}
public void fill(Object data, FillConfig fillConfig) {
if (fillConfig == null) {
fillConfig = FillConfig.builder().build(true);
}
fillConfig.init();
if (data instanceof Collection) {
List<AnalysisCell> analysisCellList = readTemplateData(templateCollectionAnalysisCache);
Collection collectionData = (Collection)data;
if (CollectionUtils.isEmpty(collectionData)) {
return;
}
Iterator iterator = collectionData.iterator();
if (WriteDirectionEnum.VERTICAL.equals(fillConfig.getDirection()) && fillConfig.getForceNewRow()) {
shiftRows(collectionData.size(), analysisCellList);
}
while (iterator.hasNext()) {
doFill(analysisCellList, iterator.next(), fillConfig);
}
} else {
doFill(readTemplateData(templateAnalysisCache), data, fillConfig);
}
}
private void shiftRows(int size, List<AnalysisCell> analysisCellList) {
if (CollectionUtils.isEmpty(analysisCellList)) {
return;
}
int maxRowIndex = 0;
Integer sheetNo = writeContext.writeSheetHolder().getSheetNo();
Map<AnalysisCell, Integer> collectionLastIndexMap = collectionLastIndexCache.get(sheetNo);
for (AnalysisCell analysisCell : analysisCellList) {
if (collectionLastIndexMap != null) {
Integer lastRowIndex = collectionLastIndexMap.get(analysisCell);
if (lastRowIndex != null) {
if (lastRowIndex > maxRowIndex) {
maxRowIndex = lastRowIndex;
}
continue;
}
}
if (analysisCell.getRowIndex() > maxRowIndex) {
maxRowIndex = analysisCell.getRowIndex();
}
}
Sheet cachedSheet = writeContext.writeSheetHolder().getCachedSheet();
int lastRowIndex = cachedSheet.getLastRowNum();
if (maxRowIndex >= lastRowIndex) {
return;
}
Sheet sheet = writeContext.writeSheetHolder().getCachedSheet();
int number = size;
if (collectionLastIndexMap == null) {
number--;
}
sheet.shiftRows(maxRowIndex + 1, lastRowIndex, number);
for (AnalysisCell analysisCell : templateAnalysisCache.get(writeContext.writeSheetHolder().getSheetNo())) {
if (analysisCell.getRowIndex() > maxRowIndex) {
analysisCell.setRowIndex(analysisCell.getRowIndex() + number);
}
}
}
private void doFill(List<AnalysisCell> analysisCellList, Object oneRowData, FillConfig fillConfig) {
Map dataMap;
if (oneRowData instanceof Map) {
dataMap = (Map)oneRowData;
} else {
dataMap = BeanMap.create(oneRowData);
}
WriteSheetHolder writeSheetHolder = writeContext.writeSheetHolder();
Map<String, ExcelContentProperty> fieldNameContentPropertyMap =
writeContext.currentWriteHolder().excelWriteHeadProperty().getFieldNameContentPropertyMap();
for (AnalysisCell analysisCell : analysisCellList) {
Cell cell = getOneCell(analysisCell, fillConfig);
if (analysisCell.getOnlyOneVariable()) {
String variable = analysisCell.getVariableList().get(0);
if (!dataMap.containsKey(variable)) {
continue;
}
Object value = dataMap.get(variable);
CellData cellData = converterAndSet(writeSheetHolder, value == null ? null : value.getClass(), cell,
value, fieldNameContentPropertyMap.get(variable));
WriteHandlerUtils.afterCellDispose(writeContext, cellData, cell, null, null, Boolean.FALSE);
} else {
StringBuilder cellValueBuild = new StringBuilder();
int index = 0;
List<CellData> cellDataList = new ArrayList<CellData>();
for (String variable : analysisCell.getVariableList()) {
cellValueBuild.append(analysisCell.getPrepareDataList().get(index++));
if (!dataMap.containsKey(variable)) {
continue;
}
Object value = dataMap.get(variable);
CellData cellData = convert(writeSheetHolder, value == null ? null : value.getClass(), cell, value,
fieldNameContentPropertyMap.get(variable));
cellDataList.add(cellData);
switch (cellData.getType()) {
case STRING:
cellValueBuild.append(cellData.getStringValue());
break;
case BOOLEAN:
cellValueBuild.append(cellData.getBooleanValue());
break;
case NUMBER:
cellValueBuild.append(cellData.getNumberValue());
break;
default:
break;
}
}
cellValueBuild.append(analysisCell.getPrepareDataList().get(index));
cell.setCellValue(cellValueBuild.toString());
WriteHandlerUtils.afterCellDispose(writeContext, cellDataList, cell, null, null, Boolean.FALSE);
}
}
}
private Cell getOneCell(AnalysisCell analysisCell, FillConfig fillConfig) {
Sheet cachedSheet = writeContext.writeSheetHolder().getCachedSheet();
if (WriteTemplateAnalysisCellTypeEnum.COMMON.equals(analysisCell.getCellType())) {
return cachedSheet.getRow(analysisCell.getRowIndex()).getCell(analysisCell.getColumnIndex());
}
Integer sheetNo = writeContext.writeSheetHolder().getSheetNo();
Sheet sheet = writeContext.writeSheetHolder().getSheet();
Map<AnalysisCell, Integer> collectionLastIndexMap = collectionLastIndexCache.get(sheetNo);
if (collectionLastIndexMap == null) {
collectionLastIndexMap = new HashMap<AnalysisCell, Integer>(16);
collectionLastIndexCache.put(sheetNo, collectionLastIndexMap);
}
boolean isOriginalCell = false;
Integer lastRowIndex;
Integer lastColumnIndex;
switch (fillConfig.getDirection()) {
case VERTICAL:
lastRowIndex = collectionLastIndexMap.get(analysisCell);
if (lastRowIndex == null) {
lastRowIndex = analysisCell.getRowIndex();
collectionLastIndexMap.put(analysisCell, lastRowIndex);
isOriginalCell = true;
} else {
collectionLastIndexMap.put(analysisCell, ++lastRowIndex);
}
lastColumnIndex = analysisCell.getColumnIndex();
break;
case HORIZONTAL:
lastRowIndex = analysisCell.getRowIndex();
lastColumnIndex = collectionLastIndexMap.get(analysisCell);
if (lastColumnIndex == null) {
lastColumnIndex = analysisCell.getColumnIndex();
collectionLastIndexMap.put(analysisCell, lastColumnIndex);
isOriginalCell = true;
} else {
collectionLastIndexMap.put(analysisCell, ++lastColumnIndex);
}
break;
default:
throw new ExcelGenerateException("The wrong direction.");
}
Row row = sheet.getRow(lastRowIndex);
if (row == null) {
row = cachedSheet.getRow(lastRowIndex);
if (row == null) {
WriteHandlerUtils.beforeRowCreate(writeContext, lastRowIndex, null, Boolean.FALSE);
if (fillConfig.getForceNewRow()) {
row = cachedSheet.createRow(lastRowIndex);
} else {
row = sheet.createRow(lastRowIndex);
}
WriteHandlerUtils.afterRowCreate(writeContext, row, null, Boolean.FALSE);
}
}
Cell cell = row.getCell(lastColumnIndex);
if (cell == null) {
WriteHandlerUtils.beforeCellCreate(writeContext, row, null, lastColumnIndex, null, Boolean.FALSE);
cell = row.createCell(lastColumnIndex);
WriteHandlerUtils.afterCellCreate(writeContext, cell, null, null, Boolean.FALSE);
}
Map<AnalysisCell, CellStyle> collectionFieldStyleMap = collectionFieldStyleCache.get(sheetNo);
if (collectionFieldStyleMap == null) {
collectionFieldStyleMap = new HashMap<AnalysisCell, CellStyle>(16);
collectionFieldStyleCache.put(sheetNo, collectionFieldStyleMap);
}
if (isOriginalCell) {
collectionFieldStyleMap.put(analysisCell, cell.getCellStyle());
} else {
CellStyle cellStyle = collectionFieldStyleMap.get(analysisCell);
if (cellStyle != null) {
cell.setCellStyle(cellStyle);
}
}
return cell;
}
private List<AnalysisCell> readTemplateData(Map<Integer, List<AnalysisCell>> analysisCache) {
Integer sheetNo = writeContext.writeSheetHolder().getSheetNo();
List<AnalysisCell> analysisCellList = analysisCache.get(sheetNo);
if (analysisCellList != null) {
return analysisCellList;
}
Sheet sheet = writeContext.writeSheetHolder().getCachedSheet();
analysisCellList = new ArrayList<AnalysisCell>();
List<AnalysisCell> collectionAnalysisCellList = new ArrayList<AnalysisCell>();
for (int i = 0; i <= sheet.getLastRowNum(); i++) {
Row row = sheet.getRow(i);
if (row == null) {
continue;
}
for (int j = 0; j < row.getLastCellNum(); j++) {
Cell cell = row.getCell(j);
if (cell == null) {
continue;
}
prepareData(cell.getStringCellValue(), analysisCellList, collectionAnalysisCellList, i, j);
}
}
templateAnalysisCache.put(sheetNo, analysisCellList);
templateCollectionAnalysisCache.put(sheetNo, collectionAnalysisCellList);
return analysisCache.get(sheetNo);
}
private void prepareData(String value, List<AnalysisCell> analysisCellList,
List<AnalysisCell> collectionAnalysisCellList, int rowIndex, int columnIndex) {
if (StringUtils.isEmpty(value)) {
return;
}
AnalysisCell analysisCell = null;
int startIndex = 0;
int length = value.length();
int lastPrepareDataIndex = 0;
out:
while (startIndex < length) {
int prefixIndex = value.indexOf(FILL_PREFIX, startIndex);
if (prefixIndex < 0) {
break out;
}
if (prefixIndex != 0) {
char prefixPrefixChar = value.charAt(prefixIndex - 1);
if (prefixPrefixChar == IGNORE_CHAR) {
startIndex = prefixIndex + 1;
continue;
}
}
int suffixIndex = -1;
while (suffixIndex == -1 && startIndex < length) {
suffixIndex = value.indexOf(FILL_SUFFIX, startIndex + 1);
if (suffixIndex < 0) {
break out;
}
startIndex = suffixIndex + 1;
char prefixSuffixChar = value.charAt(suffixIndex - 1);
if (prefixSuffixChar == IGNORE_CHAR) {
suffixIndex = -1;
}
}
if (analysisCell == null) {
analysisCell = new AnalysisCell();
analysisCell.setRowIndex(rowIndex);
analysisCell.setColumnIndex(columnIndex);
analysisCell.setOnlyOneVariable(Boolean.TRUE);
List<String> variableList = new ArrayList<String>();
analysisCell.setVariableList(variableList);
List<String> prepareDataList = new ArrayList<String>();
analysisCell.setPrepareDataList(prepareDataList);
analysisCell.setCellType(WriteTemplateAnalysisCellTypeEnum.COMMON);
}
String variable = value.substring(prefixIndex + 1, suffixIndex);
if (StringUtils.isEmpty(variable)) {
continue;
}
if (variable.startsWith(COLLECTION_PREFIX)) {
variable = variable.substring(1);
if (StringUtils.isEmpty(variable)) {
continue;
}
analysisCell.setCellType(WriteTemplateAnalysisCellTypeEnum.COLLECTION);
}
analysisCell.getVariableList().add(variable);
if (lastPrepareDataIndex == prefixIndex) {
analysisCell.getPrepareDataList().add(StringUtils.EMPTY);
} else {
analysisCell.getPrepareDataList()
.add(convertPrepareData(value.substring(lastPrepareDataIndex, prefixIndex)));
analysisCell.setOnlyOneVariable(Boolean.FALSE);
}
lastPrepareDataIndex = suffixIndex + 1;
}
if (analysisCell != null) {
if (lastPrepareDataIndex == length) {
analysisCell.getPrepareDataList().add(StringUtils.EMPTY);
} else {
analysisCell.getPrepareDataList().add(convertPrepareData(value.substring(lastPrepareDataIndex)));
analysisCell.setOnlyOneVariable(Boolean.FALSE);
}
if (WriteTemplateAnalysisCellTypeEnum.COMMON.equals(analysisCell.getCellType())) {
analysisCellList.add(analysisCell);
} else {
collectionAnalysisCellList.add(analysisCell);
}
}
}
private String convertPrepareData(String prepareData) {
prepareData = prepareData.replaceAll(ESCAPE_FILL_PREFIX, FILL_PREFIX);
prepareData = prepareData.replaceAll(ESCAPE_FILL_SUFFIX, FILL_SUFFIX);
return prepareData;
}
}

44
src/main/java/com/alibaba/excel/write/handler/CellWriteHandler.java

@ -1,5 +1,7 @@
package com.alibaba.excel.write.handler;
import java.util.List;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
@ -16,32 +18,56 @@ import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
public interface CellWriteHandler extends WriteHandler {
/**
* called before create the cell
* Called before create the cell
*
* @param writeSheetHolder
* @param writeTableHolder
* Nullable
* Nullable.It is null without using table writes.
* @param row
* @param head
* Nullable.It is null in the case of fill data and without head.
* @param columnIndex
* @param relativeRowIndex
* Nullable.It is null in the case of fill data.
* @param isHead
* It will always be false when fill data.
*/
void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head,
int relativeRowIndex, boolean isHead);
Integer columnIndex, Integer relativeRowIndex, Boolean isHead);
/**
* Called after the cell is created
*
* @param writeSheetHolder
* @param writeTableHolder
* Nullable.It is null without using table writes.
* @param cell
* @param head
* Nullable.It is null in the case of fill data and without head.
* @param relativeRowIndex
* Nullable.It is null in the case of fill data.
* @param isHead
* It will always be false when fill data.
*/
void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head,
Integer relativeRowIndex, Boolean isHead);
/**
* called after the cell is created
* Called after all operations on the cell have been completed
*
* @param writeSheetHolder
* @param writeTableHolder
* Nullable
* Nullable.It is null without using table writes.
* @param cell
* @param head
* @param cellData
* Nullable.
* Nullable.It is null in the case of fill data and without head.
* @param cellDataList
* Nullable.It is null in the case of add header.There may be several when fill the data.
* @param relativeRowIndex
* Nullable.It is null in the case of fill data.
* @param isHead
* It will always be false when fill data.
*/
void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData,
Cell cell, Head head, int relativeRowIndex, boolean isHead);
void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead);
}

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

@ -21,8 +21,9 @@ public class DefaultWriteHandlerLoader {
*
* @return
*/
public static List<WriteHandler> loadDefaultHandler() {
public static List<WriteHandler> loadDefaultHandler(Boolean useDefaultStyle) {
List<WriteHandler> handlerList = new ArrayList<WriteHandler>();
if (useDefaultStyle) {
WriteCellStyle headWriteCellStyle = new WriteCellStyle();
headWriteCellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
WriteFont headWriteFont = new WriteFont();
@ -31,6 +32,7 @@ public class DefaultWriteHandlerLoader {
headWriteFont.setBold(true);
headWriteCellStyle.setWriteFont(headWriteFont);
handlerList.add(new HorizontalCellStyleStrategy(headWriteCellStyle, new ArrayList<WriteCellStyle>()));
}
return handlerList;
}

33
src/main/java/com/alibaba/excel/write/handler/RowWriteHandler.java

@ -13,28 +13,47 @@ import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
public interface RowWriteHandler extends WriteHandler {
/**
* called before create the row
* Called before create the row
*
* @param writeSheetHolder
* @param writeTableHolder
* Nullable
* Nullable.It is null without using table writes.
* @param rowIndex
* @param relativeRowIndex
* Nullable.It is null in the case of fill data.
* @param isHead
* Nullable.It is null in the case of fill data.
*/
void beforeRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, int rowIndex,
int relativeRowIndex, boolean isHead);
void beforeRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Integer rowIndex,
Integer relativeRowIndex, Boolean isHead);
/**
* called after the row is created
* Called after the row is created
*
* @param writeSheetHolder
* @param writeTableHolder
* Nullable
* Nullable.It is null without using table writes.
* @param row
* @param relativeRowIndex
* Nullable.It is null in the case of fill data.
* @param isHead
* Nullable.It is null in the case of fill data.
*/
void afterRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,
int relativeRowIndex, boolean isHead);
Integer relativeRowIndex, Boolean isHead);
/**
* Called after all operations on the row have been completed.This method is not called when fill the data.
*
* @param writeSheetHolder
* @param writeTableHolder
* Nullable.It is null without using table writes.
* @param row
* @param relativeRowIndex
* Nullable.It is null in the case of fill data.
* @param isHead
* Nullable.It is null in the case of fill data.
*/
void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,
Integer relativeRowIndex, Boolean isHead);
}

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

@ -11,7 +11,7 @@ import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
public interface SheetWriteHandler extends WriteHandler {
/**
* called before create the sheet
* Called before create the sheet
*
* @param writeWorkbookHolder
* @param writeSheetHolder
@ -19,7 +19,7 @@ public interface SheetWriteHandler extends WriteHandler {
void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder);
/**
* called after the sheet is created
* Called after the sheet is created
*
* @param writeWorkbookHolder
* @param writeSheetHolder

11
src/main/java/com/alibaba/excel/write/handler/WorkbookWriteHandler.java

@ -10,14 +10,21 @@ import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
public interface WorkbookWriteHandler extends WriteHandler {
/**
* called before create the sheet
* Called before create the workbook
*/
void beforeWorkbookCreate();
/**
* called after the sheet is created
* Called after the workbook is created
*
* @param writeWorkbookHolder
*/
void afterWorkbookCreate(WriteWorkbookHolder writeWorkbookHolder);
/**
* Called after all operations on the workbook have been completed
*
* @param writeWorkbookHolder
*/
void afterWorkbookDispose(WriteWorkbookHolder writeWorkbookHolder);
}

12
src/main/java/com/alibaba/excel/write/merge/AbstractMergeStrategy.java

@ -1,5 +1,7 @@
package com.alibaba.excel.write.merge;
import java.util.List;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
@ -18,13 +20,17 @@ import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
public abstract class AbstractMergeStrategy implements CellWriteHandler {
@Override
public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,
Head head, int relativeRowIndex, boolean isHead) {
Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {
}
@Override
public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData,
Cell cell, Head head, int relativeRowIndex, boolean isHead) {
public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell,
Head head, Integer relativeRowIndex, Boolean isHead) {}
@Override
public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
if (isHead) {
return;
}

12
src/main/java/com/alibaba/excel/write/metadata/WriteBasicParameter.java

@ -24,6 +24,10 @@ public class WriteBasicParameter extends BasicParameter {
* Custom type handler override the default
*/
private List<WriteHandler> customWriteHandlerList = new ArrayList<WriteHandler>();
/**
* Use the default style.Default is true.
*/
private Boolean useDefaultStyle;
public Integer getRelativeHeadRowIndex() {
return relativeHeadRowIndex;
@ -48,4 +52,12 @@ public class WriteBasicParameter extends BasicParameter {
public void setCustomWriteHandlerList(List<WriteHandler> customWriteHandlerList) {
this.customWriteHandlerList = customWriteHandlerList;
}
public Boolean getUseDefaultStyle() {
return useDefaultStyle;
}
public void setUseDefaultStyle(Boolean useDefaultStyle) {
this.useDefaultStyle = useDefaultStyle;
}
}

17
src/main/java/com/alibaba/excel/write/metadata/WriteWorkbook.java

@ -43,13 +43,20 @@ public class WriteWorkbook extends WriteBasicParameter {
*/
private File templateFile;
/**
* Default true
* Default trueuseDefaultStyle
*/
private Boolean autoCloseStream;
/**
* Mandatory use 'inputStream' .Default is false
*/
private Boolean mandatoryUseInputStream;
/**
* Whether the encryption
* <p>
* WARRING:Encryption is when the entire file is read into memory, so it is very memory intensive.
*
*/
private String password;
/**
* The default is all excel objects.Default is true.
* <p>
@ -140,4 +147,12 @@ public class WriteWorkbook extends WriteBasicParameter {
public void setWriteHandler(com.alibaba.excel.event.WriteHandler writeHandler) {
this.writeHandler = writeHandler;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}

89
src/main/java/com/alibaba/excel/write/metadata/fill/AnalysisCell.java

@ -0,0 +1,89 @@
package com.alibaba.excel.write.metadata.fill;
import java.util.List;
import com.alibaba.excel.enums.WriteTemplateAnalysisCellTypeEnum;
/**
* Read the cells of the template while populating the data.
*
* @author Jiaju Zhuang
**/
public class AnalysisCell {
private int columnIndex;
private int rowIndex;
private List<String> variableList;
private List<String> prepareDataList;
private Boolean onlyOneVariable;
private WriteTemplateAnalysisCellTypeEnum cellType;
public int getColumnIndex() {
return columnIndex;
}
public void setColumnIndex(int columnIndex) {
this.columnIndex = columnIndex;
}
public int getRowIndex() {
return rowIndex;
}
public void setRowIndex(int rowIndex) {
this.rowIndex = rowIndex;
}
public List<String> getVariableList() {
return variableList;
}
public void setVariableList(List<String> variableList) {
this.variableList = variableList;
}
public List<String> getPrepareDataList() {
return prepareDataList;
}
public void setPrepareDataList(List<String> prepareDataList) {
this.prepareDataList = prepareDataList;
}
public Boolean getOnlyOneVariable() {
return onlyOneVariable;
}
public void setOnlyOneVariable(Boolean onlyOneVariable) {
this.onlyOneVariable = onlyOneVariable;
}
public WriteTemplateAnalysisCellTypeEnum getCellType() {
return cellType;
}
public void setCellType(WriteTemplateAnalysisCellTypeEnum cellType) {
this.cellType = cellType;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
AnalysisCell that = (AnalysisCell)o;
if (columnIndex != that.columnIndex) {
return false;
}
return rowIndex == that.rowIndex;
}
@Override
public int hashCode() {
int result = columnIndex;
result = 31 * result + rowIndex;
return result;
}
}

83
src/main/java/com/alibaba/excel/write/metadata/fill/FillConfig.java

@ -0,0 +1,83 @@
package com.alibaba.excel.write.metadata.fill;
import com.alibaba.excel.enums.WriteDirectionEnum;
/**
* Fill config
*
* @author Jiaju Zhuang
**/
public class FillConfig {
private WriteDirectionEnum direction;
/**
* Create a new row each time you use the list parameter.The default create if necessary.
* <p>
* Warnning:If you use <code>forceNewRow</code> set true, will not be able to use asynchronous write file, simply
* say the whole file will be stored in memory.
*/
private Boolean forceNewRow;
private boolean hasInit;
public WriteDirectionEnum getDirection() {
return direction;
}
public void setDirection(WriteDirectionEnum direction) {
this.direction = direction;
}
public Boolean getForceNewRow() {
return forceNewRow;
}
public void setForceNewRow(Boolean forceNewRow) {
this.forceNewRow = forceNewRow;
}
public void init() {
if (hasInit) {
return;
}
if (direction == null) {
direction = WriteDirectionEnum.VERTICAL;
}
if (forceNewRow == null) {
forceNewRow = Boolean.FALSE;
}
hasInit = true;
}
public static FillConfigBuilder builder() {
return new FillConfigBuilder();
}
public static class FillConfigBuilder {
private FillConfig fillConfig;
FillConfigBuilder() {
this.fillConfig = new FillConfig();
}
public FillConfigBuilder direction(WriteDirectionEnum direction) {
fillConfig.setDirection(direction);
return this;
}
public FillConfigBuilder forceNewRow(Boolean forceNewRow) {
fillConfig.setForceNewRow(forceNewRow);
return this;
}
public FillConfig build() {
return build(true);
}
public FillConfig build(boolean autoInit) {
if (autoInit) {
fillConfig.init();
}
return fillConfig;
}
}
}

26
src/main/java/com/alibaba/excel/write/metadata/holder/AbstractWriteHolder.java

@ -21,7 +21,6 @@ import com.alibaba.excel.metadata.AbstractHolder;
import com.alibaba.excel.metadata.Font;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.TableStyle;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.alibaba.excel.metadata.property.RowHeightProperty;
import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.excel.write.handler.CellWriteHandler;
@ -62,6 +61,10 @@ public abstract class AbstractWriteHolder extends AbstractHolder implements Writ
* Write handler for workbook
*/
private Map<Class<? extends WriteHandler>, List<WriteHandler>> writeHandlerMap;
/**
* Use the default style.Default is true.
*/
private Boolean useDefaultStyle;
public AbstractWriteHolder(WriteBasicParameter writeBasicParameter, AbstractWriteHolder parentAbstractWriteHolder,
Boolean convertAllFiled) {
@ -97,6 +100,16 @@ public abstract class AbstractWriteHolder extends AbstractHolder implements Writ
this.relativeHeadRowIndex = writeBasicParameter.getRelativeHeadRowIndex();
}
if (writeBasicParameter.getUseDefaultStyle() == null) {
if (parentAbstractWriteHolder == null) {
this.useDefaultStyle = Boolean.TRUE;
} else {
this.useDefaultStyle = parentAbstractWriteHolder.getUseDefaultStyle();
}
} else {
this.useDefaultStyle = writeBasicParameter.getUseDefaultStyle();
}
// Initialization property
this.excelWriteHeadProperty = new ExcelWriteHeadProperty(getClazz(), getHead(), convertAllFiled);
@ -118,7 +131,7 @@ public abstract class AbstractWriteHolder extends AbstractHolder implements Writ
if (parentAbstractWriteHolder != null) {
parentWriteHandlerMap = parentAbstractWriteHolder.getWriteHandlerMap();
} else {
handlerList.addAll(DefaultWriteHandlerLoader.loadDefaultHandler());
handlerList.addAll(DefaultWriteHandlerLoader.loadDefaultHandler(useDefaultStyle));
}
this.writeHandlerMap = sortAndClearUpHandler(handlerList, parentWriteHandlerMap);
@ -135,6 +148,7 @@ public abstract class AbstractWriteHolder extends AbstractHolder implements Writ
getConverterMap().put(ConverterKeyBuild.buildKey(converter.supportJavaTypeKey()), converter);
}
}
}
/**
@ -361,6 +375,14 @@ public abstract class AbstractWriteHolder extends AbstractHolder implements Writ
this.relativeHeadRowIndex = relativeHeadRowIndex;
}
public Boolean getUseDefaultStyle() {
return useDefaultStyle;
}
public void setUseDefaultStyle(Boolean useDefaultStyle) {
this.useDefaultStyle = useDefaultStyle;
}
@Override
public ExcelWriteHeadProperty excelWriteHeadProperty() {
return getExcelWriteHeadProperty();

60
src/main/java/com/alibaba/excel/write/metadata/holder/WriteSheetHolder.java

@ -3,11 +3,13 @@ package com.alibaba.excel.write.metadata.holder;
import java.util.HashMap;
import java.util.Map;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import com.alibaba.excel.enums.HolderEnum;
import com.alibaba.excel.enums.WriteLastRowType;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.enums.WriteLastRowTypeEnum;
import com.alibaba.excel.write.metadata.WriteSheet;
/**
@ -21,9 +23,22 @@ public class WriteSheetHolder extends AbstractWriteHolder {
*/
private WriteSheet writeSheet;
/***
* poi sheet
* Current poi Sheet.This is only for writing, and there may be no data in version 07 when template data needs to be
* read.
* <ul>
* <li>03:{@link HSSFSheet}</li>
* <li>07:{@link SXSSFSheet}</li>
* </ul>
*/
private Sheet sheet;
/***
* Current poi Sheet.Be sure to use and this method when reading template data.
* <ul>
* <li>03:{@link HSSFSheet}</li>
* <li>07:{@link XSSFSheet}</li>
* </ul>
*/
private Sheet cachedSheet;
/***
* sheetNo
*/
@ -47,7 +62,7 @@ public class WriteSheetHolder extends AbstractWriteHolder {
* @param writeSheet
* @param writeWorkbookHolder
*/
private WriteLastRowType writeLastRowType;
private WriteLastRowTypeEnum writeLastRowTypeEnum;
public WriteSheetHolder(WriteSheet writeSheet, WriteWorkbookHolder writeWorkbookHolder) {
super(writeSheet, writeWorkbookHolder, writeWorkbookHolder.getWriteWorkbook().getConvertAllFiled());
@ -60,10 +75,10 @@ public class WriteSheetHolder extends AbstractWriteHolder {
}
this.parentWriteWorkbookHolder = writeWorkbookHolder;
this.hasBeenInitializedTable = new HashMap<Integer, WriteTableHolder>();
if (writeWorkbookHolder.getTemplateInputStream() == null && writeWorkbookHolder.getTemplateFile() == null) {
writeLastRowType = WriteLastRowType.COMMON_EMPTY;
if (writeWorkbookHolder.getTempTemplateInputStream() != null) {
writeLastRowTypeEnum = WriteLastRowTypeEnum.TEMPLATE_EMPTY;
} else {
writeLastRowType = WriteLastRowType.TEMPLATE_EMPTY;
writeLastRowTypeEnum = WriteLastRowTypeEnum.COMMON_EMPTY;
}
}
@ -87,6 +102,14 @@ public class WriteSheetHolder extends AbstractWriteHolder {
return sheetNo;
}
public Sheet getCachedSheet() {
return cachedSheet;
}
public void setCachedSheet(Sheet cachedSheet) {
this.cachedSheet = cachedSheet;
}
public void setSheetNo(Integer sheetNo) {
this.sheetNo = sheetNo;
}
@ -115,12 +138,12 @@ public class WriteSheetHolder extends AbstractWriteHolder {
this.hasBeenInitializedTable = hasBeenInitializedTable;
}
public WriteLastRowType getWriteLastRowType() {
return writeLastRowType;
public WriteLastRowTypeEnum getWriteLastRowTypeEnum() {
return writeLastRowTypeEnum;
}
public void setWriteLastRowType(WriteLastRowType writeLastRowType) {
this.writeLastRowType = writeLastRowType;
public void setWriteLastRowTypeEnum(WriteLastRowTypeEnum writeLastRowTypeEnum) {
this.writeLastRowTypeEnum = writeLastRowTypeEnum;
}
/**
@ -131,25 +154,16 @@ public class WriteSheetHolder extends AbstractWriteHolder {
public int getNewRowIndexAndStartDoWrite() {
// 'getLastRowNum' doesn't matter if it has one or zero,is's zero
int newRowIndex = 0;
switch (writeLastRowType) {
switch (writeLastRowTypeEnum) {
case TEMPLATE_EMPTY:
if (parentWriteWorkbookHolder.getExcelType() == ExcelTypeEnum.XLSX) {
if (parentWriteWorkbookHolder.getTemplateLastRowMap().containsKey(sheetNo)) {
newRowIndex = parentWriteWorkbookHolder.getTemplateLastRowMap().get(sheetNo);
}
} else {
newRowIndex = sheet.getLastRowNum();
}
newRowIndex++;
break;
case HAS_DATA:
newRowIndex = sheet.getLastRowNum();
newRowIndex = Math.max(sheet.getLastRowNum(), cachedSheet.getLastRowNum());
newRowIndex++;
break;
default:
break;
}
writeLastRowType = WriteLastRowType.HAS_DATA;
writeLastRowTypeEnum = WriteLastRowTypeEnum.HAS_DATA;
return newRowIndex;
}

93
src/main/java/com/alibaba/excel/write/metadata/holder/WriteWorkbookHolder.java

@ -1,19 +1,25 @@
package com.alibaba.excel.write.metadata.holder;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import com.alibaba.excel.enums.HolderEnum;
import com.alibaba.excel.exception.ExcelGenerateException;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.util.FileUtils;
import com.alibaba.excel.util.IoUtils;
import com.alibaba.excel.write.metadata.WriteWorkbook;
/**
@ -23,10 +29,22 @@ import com.alibaba.excel.write.metadata.WriteWorkbook;
*/
public class WriteWorkbookHolder extends AbstractWriteHolder {
/***
* poi Workbook
* Current poi Workbook.This is only for writing, and there may be no data in version 07 when template data needs to
* be read.
* <ul>
* <li>03:{@link HSSFWorkbook}</li>
* <li>07:{@link SXSSFWorkbook}</li>
* </ul>
*/
private Workbook workbook;
/***
* Current poi Workbook.Be sure to use and this method when reading template data.
* <ul>
* <li>03:{@link HSSFWorkbook}</li>
* <li>07:{@link XSSFWorkbook}</li>
* </ul>
*/
private Workbook cachedWorkbook;
/**
* current param
*/
@ -53,6 +71,12 @@ public class WriteWorkbookHolder extends AbstractWriteHolder {
* If 'inputStream' and 'file' all not empty,file first
*/
private File templateFile;
/**
* Temporary template file stream.
* <p>
* A temporary file stream needs to be created in order not to modify the original template file.
*/
private InputStream tempTemplateInputStream;
/**
* Default true
*/
@ -70,10 +94,9 @@ public class WriteWorkbookHolder extends AbstractWriteHolder {
*/
private Map<Integer, WriteSheetHolder> hasBeenInitializedSheet;
/**
* When using SXSSFWorkbook, you can't get the actual last line.But we need to read the last line when we are using
* the template, so we cache it
* Whether the encryption
*/
private Map<Integer, Integer> templateLastRowMap;
private String password;
public WriteWorkbookHolder(WriteWorkbook writeWorkbook) {
super(writeWorkbook, null, writeWorkbook.getConvertAllFiled());
@ -88,19 +111,16 @@ public class WriteWorkbookHolder extends AbstractWriteHolder {
} else {
this.outputStream = writeWorkbook.getOutputStream();
}
if (writeWorkbook.getTemplateInputStream() != null) {
if (writeWorkbook.getTemplateInputStream().markSupported()) {
this.templateInputStream = writeWorkbook.getTemplateInputStream();
} else {
this.templateInputStream = new BufferedInputStream(writeWorkbook.getTemplateInputStream());
}
}
this.templateFile = writeWorkbook.getTemplateFile();
if (writeWorkbook.getAutoCloseStream() == null) {
this.autoCloseStream = Boolean.TRUE;
} else {
this.autoCloseStream = writeWorkbook.getAutoCloseStream();
}
try {
copyTemplate();
} catch (IOException e) {
throw new ExcelGenerateException("Copy template failure.", e);
}
if (writeWorkbook.getExcelType() == null) {
if (file != null && file.getName().endsWith(ExcelTypeEnum.XLS.getValue())) {
this.excelType = ExcelTypeEnum.XLS;
@ -116,7 +136,26 @@ public class WriteWorkbookHolder extends AbstractWriteHolder {
this.mandatoryUseInputStream = writeWorkbook.getMandatoryUseInputStream();
}
this.hasBeenInitializedSheet = new HashMap<Integer, WriteSheetHolder>();
this.templateLastRowMap = new HashMap<Integer, Integer>(8);
this.password = writeWorkbook.getPassword();
}
private void copyTemplate() throws IOException {
if (writeWorkbook.getTemplateFile() == null && writeWorkbook.getTemplateInputStream() == null) {
return;
}
byte[] templateFileByte = null;
if (writeWorkbook.getTemplateFile() != null) {
templateFileByte = FileUtils.readFileToByteArray(writeWorkbook.getTemplateFile());
} else if (writeWorkbook.getTemplateInputStream() == null) {
try {
templateFileByte = IoUtils.toByteArray(writeWorkbook.getTemplateInputStream());
} finally {
if (autoCloseStream) {
writeWorkbook.getTemplateInputStream().close();
}
}
}
this.tempTemplateInputStream = new ByteArrayInputStream(templateFileByte);
}
public Workbook getWorkbook() {
@ -127,6 +166,14 @@ public class WriteWorkbookHolder extends AbstractWriteHolder {
this.workbook = workbook;
}
public Workbook getCachedWorkbook() {
return cachedWorkbook;
}
public void setCachedWorkbook(Workbook cachedWorkbook) {
this.cachedWorkbook = cachedWorkbook;
}
public Map<Integer, WriteSheetHolder> getHasBeenInitializedSheet() {
return hasBeenInitializedSheet;
}
@ -167,6 +214,14 @@ public class WriteWorkbookHolder extends AbstractWriteHolder {
this.templateInputStream = templateInputStream;
}
public InputStream getTempTemplateInputStream() {
return tempTemplateInputStream;
}
public void setTempTemplateInputStream(InputStream tempTemplateInputStream) {
this.tempTemplateInputStream = tempTemplateInputStream;
}
public File getTemplateFile() {
return templateFile;
}
@ -199,12 +254,12 @@ public class WriteWorkbookHolder extends AbstractWriteHolder {
this.mandatoryUseInputStream = mandatoryUseInputStream;
}
public Map<Integer, Integer> getTemplateLastRowMap() {
return templateLastRowMap;
public String getPassword() {
return password;
}
public void setTemplateLastRowMap(Map<Integer, Integer> templateLastRowMap) {
this.templateLastRowMap = templateLastRowMap;
public void setPassword(String password) {
this.password = password;
}
@Override

40
src/main/java/com/alibaba/excel/write/style/AbstractCellStyleStrategy.java

@ -1,5 +1,7 @@
package com.alibaba.excel.write.style;
import java.util.List;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Workbook;
@ -27,28 +29,23 @@ public abstract class AbstractCellStyleStrategy implements CellWriteHandler, She
}
@Override
public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,
Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {
}
@Override
public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
initCellStyle(writeWorkbookHolder.getWorkbook());
hasInitialized = true;
}
public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell,
Head head, Integer relativeRowIndex, Boolean isHead) {
@Override
public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,
Head head, int relativeRowIndex, boolean isHead) {
if (!hasInitialized) {
initCellStyle(writeSheetHolder.getParentWriteWorkbookHolder().getWorkbook());
hasInitialized = true;
}
}
@Override
public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData,
Cell cell, Head head, int relativeRowIndex, boolean isHead) {
public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
if (isHead == null || head == null) {
return;
}
if (isHead) {
setHeadCellStyle(cell, head, relativeRowIndex);
} else {
@ -56,6 +53,17 @@ public abstract class AbstractCellStyleStrategy implements CellWriteHandler, She
}
}
@Override
public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
}
@Override
public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
initCellStyle(writeWorkbookHolder.getWorkbook());
hasInitialized = true;
}
/**
* Initialization cell style
*
@ -70,7 +78,7 @@ public abstract class AbstractCellStyleStrategy implements CellWriteHandler, She
* @param head
* @param relativeRowIndex
*/
protected abstract void setHeadCellStyle(Cell cell, Head head, int relativeRowIndex);
protected abstract void setHeadCellStyle(Cell cell, Head head, Integer relativeRowIndex);
/**
* Sets the cell style of content
@ -79,6 +87,6 @@ public abstract class AbstractCellStyleStrategy implements CellWriteHandler, She
* @param head
* @param relativeRowIndex
*/
protected abstract void setContentCellStyle(Cell cell, Head head, int relativeRowIndex);
protected abstract void setContentCellStyle(Cell cell, Head head, Integer relativeRowIndex);
}

4
src/main/java/com/alibaba/excel/write/style/AbstractVerticalCellStyleStrategy.java

@ -29,7 +29,7 @@ public abstract class AbstractVerticalCellStyleStrategy extends AbstractCellStyl
}
@Override
protected void setHeadCellStyle(Cell cell, Head head, int relativeRowIndex) {
protected void setHeadCellStyle(Cell cell, Head head, Integer relativeRowIndex) {
int columnIndex = head.getColumnIndex();
if (headCellStyleCache.containsKey(columnIndex)) {
CellStyle cellStyle = headCellStyleCache.get(columnIndex);
@ -49,7 +49,7 @@ public abstract class AbstractVerticalCellStyleStrategy extends AbstractCellStyl
}
@Override
protected void setContentCellStyle(Cell cell, Head head, int relativeRowIndex) {
protected void setContentCellStyle(Cell cell, Head head, Integer relativeRowIndex) {
int columnIndex = head.getColumnIndex();
if (contentCellStyleCache.containsKey(columnIndex)) {
CellStyle cellStyle = contentCellStyleCache.get(columnIndex);

4
src/main/java/com/alibaba/excel/write/style/HorizontalCellStyleStrategy.java

@ -51,7 +51,7 @@ public class HorizontalCellStyleStrategy extends AbstractCellStyleStrategy {
}
@Override
protected void setHeadCellStyle(Cell cell, Head head, int relativeRowIndex) {
protected void setHeadCellStyle(Cell cell, Head head, Integer relativeRowIndex) {
if (headCellStyle == null) {
return;
}
@ -59,7 +59,7 @@ public class HorizontalCellStyleStrategy extends AbstractCellStyleStrategy {
}
@Override
protected void setContentCellStyle(Cell cell, Head head, int relativeRowIndex) {
protected void setContentCellStyle(Cell cell, Head head, Integer relativeRowIndex) {
if (contentCellStyleList == null || contentCellStyleList.isEmpty()) {
return;
}

19
src/main/java/com/alibaba/excel/write/style/column/AbstractColumnWidthStyleStrategy.java

@ -1,5 +1,7 @@
package com.alibaba.excel.write.style.column;
import java.util.List;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
@ -24,27 +26,28 @@ public abstract class AbstractColumnWidthStyleStrategy implements CellWriteHandl
@Override
public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,
Head head, int relativeRowIndex, boolean isHead) {
Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {}
}
@Override
public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell,
Head head, Integer relativeRowIndex, Boolean isHead) {}
@Override
public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData,
Cell cell, Head head, int relativeRowIndex, boolean isHead) {
setColumnWidth(writeSheetHolder, cellData, cell, head, relativeRowIndex, isHead);
public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
setColumnWidth(writeSheetHolder, cellDataList, cell, head, relativeRowIndex, isHead);
}
/**
* Sets the column width when head create
*
* @param writeSheetHolder
* @param cellData
* @param cellDataList
* @param cell
* @param head
* @param relativeRowIndex
* @param isHead
*/
protected abstract void setColumnWidth(WriteSheetHolder writeSheetHolder, CellData cellData, Cell cell, Head head,
int relativeRowIndex, boolean isHead);
protected abstract void setColumnWidth(WriteSheetHolder writeSheetHolder, List<CellData> cellDataList, Cell cell, Head head,
Integer relativeRowIndex, Boolean isHead);
}

11
src/main/java/com/alibaba/excel/write/style/column/AbstractHeadColumnWidthStyleStrategy.java

@ -1,5 +1,7 @@
package com.alibaba.excel.write.style.column;
import java.util.List;
import org.apache.poi.ss.usermodel.Cell;
import com.alibaba.excel.metadata.CellData;
@ -12,10 +14,12 @@ import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
* @author Jiaju Zhuang
*/
public abstract class AbstractHeadColumnWidthStyleStrategy extends AbstractColumnWidthStyleStrategy {
@Override
protected void setColumnWidth(WriteSheetHolder writeSheetHolder, CellData cellData, Cell cell, Head head,
int relativeRowIndex, boolean isHead) {
if (!isHead && relativeRowIndex != 0) {
protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<CellData> cellDataList, Cell cell, Head head,
Integer relativeRowIndex, Boolean isHead) {
boolean needSetWidth = relativeRowIndex != null && (isHead || relativeRowIndex == 0);
if (!needSetWidth) {
return;
}
Integer width = columnWidth(head);
@ -36,4 +40,5 @@ public abstract class AbstractHeadColumnWidthStyleStrategy extends AbstractColum
* @return
*/
protected abstract Integer columnWidth(Head head);
}

20
src/main/java/com/alibaba/excel/write/style/column/LongestMatchColumnWidthStyleStrategy.java

@ -1,12 +1,14 @@
package com.alibaba.excel.write.style.column;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.poi.ss.usermodel.Cell;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
/**
@ -24,9 +26,10 @@ public class LongestMatchColumnWidthStyleStrategy extends AbstractColumnWidthSty
private static final Map<Integer, Map<Integer, Integer>> CACHE = new HashMap<Integer, Map<Integer, Integer>>(8);
@Override
protected void setColumnWidth(WriteSheetHolder writeSheetHolder, CellData cellData, Cell cell, Head head,
int relativeRowIndex, boolean isHead) {
if (!isHead && cellData == null) {
protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<CellData> cellDataList, Cell cell, Head head,
Integer relativeRowIndex, Boolean isHead) {
boolean needSetWidth = isHead || !CollectionUtils.isEmpty(cellDataList);
if (!needSetWidth) {
return;
}
Map<Integer, Integer> maxColumnWidthMap = CACHE.get(writeSheetHolder.getSheetNo());
@ -34,24 +37,25 @@ public class LongestMatchColumnWidthStyleStrategy extends AbstractColumnWidthSty
maxColumnWidthMap = new HashMap<Integer, Integer>(16);
CACHE.put(writeSheetHolder.getSheetNo(), maxColumnWidthMap);
}
Integer columnWidth = dataLength(cellData, cell, isHead);
Integer columnWidth = dataLength(cellDataList, cell, isHead);
if (columnWidth < 0) {
return;
}
if (columnWidth > MAX_COLUMN_WIDTH) {
columnWidth = MAX_COLUMN_WIDTH;
}
Integer maxColumnWidth = maxColumnWidthMap.get(head.getColumnIndex());
Integer maxColumnWidth = maxColumnWidthMap.get(cell.getColumnIndex());
if (maxColumnWidth == null || columnWidth > maxColumnWidth) {
maxColumnWidthMap.put(head.getColumnIndex(), columnWidth);
writeSheetHolder.getSheet().setColumnWidth(head.getColumnIndex(), columnWidth * 256);
maxColumnWidthMap.put(cell.getColumnIndex(), columnWidth);
writeSheetHolder.getSheet().setColumnWidth(cell.getColumnIndex(), columnWidth * 256);
}
}
private Integer dataLength(CellData cellData, Cell cell, boolean isHead) {
private Integer dataLength(List<CellData> cellDataList, Cell cell, Boolean isHead) {
if (isHead) {
return cell.getStringCellValue().getBytes().length;
}
CellData cellData = cellDataList.get(0);
switch (cellData.getType()) {
case STRING:
return cellData.getStringValue().getBytes().length;

15
src/main/java/com/alibaba/excel/write/style/row/AbstractRowHeightStyleStrategy.java

@ -20,14 +20,23 @@ public abstract class AbstractRowHeightStyleStrategy implements RowWriteHandler,
}
@Override
public void beforeRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, int rowIndex,
int relativeRowIndex, boolean isHead) {
public void beforeRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Integer rowIndex,
Integer relativeRowIndex, Boolean isHead) {
}
@Override
public void afterRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,
int relativeRowIndex, boolean isHead) {
Integer relativeRowIndex, Boolean isHead) {
}
@Override
public void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,
Integer relativeRowIndex, Boolean isHead) {
if (isHead == null) {
return;
}
if (isHead) {
setHeadColumnHeight(row, relativeRowIndex);
} else {

2
src/test/java/com/alibaba/easyexcel/test/core/annotation/AnnotationData.java

@ -29,4 +29,6 @@ public class AnnotationData {
private Double number;
@ExcelIgnore
private String ignore;
private static final String staticFinal = "test";
private transient String transientString;
}

1
src/test/java/com/alibaba/easyexcel/test/core/annotation/AnnotationDataTest.java

@ -48,6 +48,7 @@ public class AnnotationDataTest {
data.setDate(DateUtils.parseDate("2020-01-01 01:01:01"));
data.setNumber(99.99);
data.setIgnore("忽略");
data.setTransientString("忽略");
list.add(data);
return list;
}

21
src/test/java/com/alibaba/easyexcel/test/core/celldata/CellDataData.java

@ -0,0 +1,21 @@
package com.alibaba.easyexcel.test.core.celldata;
import java.util.Date;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import com.alibaba.excel.metadata.CellData;
import lombok.Data;
/**
* @author Jiaju Zhuang
*/
@Data
public class CellDataData {
@DateTimeFormat("yyyy年MM月dd日")
private CellData<Date> date;
private CellData<Integer> integer1;
private Integer integer2;
private CellData formulaValue;
}

37
src/test/java/com/alibaba/easyexcel/test/core/celldata/CellDataDataListener.java

@ -0,0 +1,37 @@
package com.alibaba.easyexcel.test.core.celldata;
import java.util.ArrayList;
import java.util.List;
import org.junit.Assert;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.fastjson.JSON;
/**
* @author Jiaju Zhuang
*/
public class CellDataDataListener extends AnalysisEventListener<CellDataData> {
private static final Logger LOGGER = LoggerFactory.getLogger(CellDataDataListener.class);
List<CellDataData> list = new ArrayList<CellDataData>();
@Override
public void invoke(CellDataData data, AnalysisContext context) {
list.add(data);
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
Assert.assertEquals(list.size(), 1);
CellDataData cellDataData = list.get(0);
Assert.assertEquals(cellDataData.getDate().getStringValue(), "2020年01月01日");
Assert.assertEquals((long)cellDataData.getInteger1().getData(), 2L);
Assert.assertEquals((long)cellDataData.getInteger2(), 2L);
Assert.assertEquals(cellDataData.getFormulaValue().getFormulaValue(), "B2+C2");
LOGGER.debug("First row:{}", JSON.toJSONString(list.get(0)));
}
}

71
src/test/java/com/alibaba/easyexcel/test/core/celldata/CellDataDataTest.java

@ -0,0 +1,71 @@
package com.alibaba.easyexcel.test.core.celldata;
import java.io.File;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;
import com.alibaba.easyexcel.test.core.simple.SimpleData;
import com.alibaba.easyexcel.test.core.simple.SimpleDataListener;
import com.alibaba.easyexcel.test.core.simple.SimpleDataSheetNameListener;
import com.alibaba.easyexcel.test.util.TestFileUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.util.DateUtils;
/**
*
* @author Jiaju Zhuang
*/
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class CellDataDataTest {
private static File file07;
private static File file03;
@BeforeClass
public static void init() {
file07 = TestFileUtil.createNewFile("cellData07.xlsx");
file03 = TestFileUtil.createNewFile("cellData03.xls");
}
@Test
public void t01ReadAndWrite07() throws Exception {
readAndWrite(file07);
}
@Test
public void t02ReadAndWrite03() throws Exception {
readAndWrite(file03);
}
private void readAndWrite(File file) throws Exception {
EasyExcel.write(file, CellDataData.class).sheet().doWrite(data());
EasyExcel.read(file, CellDataData.class, new CellDataDataListener()).sheet().doRead();
}
private List<CellDataData> data() throws Exception {
List<CellDataData> list = new ArrayList<CellDataData>();
CellDataData cellDataData = new CellDataData();
cellDataData.setDate(new CellData<Date>(DateUtils.parseDate("2020-01-01 01:01:01")));
CellData<Integer> integer1 = new CellData<Integer>();
integer1.setType(CellDataTypeEnum.NUMBER);
integer1.setNumberValue(BigDecimal.valueOf(2L));
cellDataData.setInteger1(integer1);
cellDataData.setInteger2(2);
CellData formulaValue = new CellData();
formulaValue.setFormula(Boolean.TRUE);
formulaValue.setFormulaValue("B2+C2");
cellDataData.setFormulaValue(formulaValue);
list.add(cellDataData);
return list;
}
}

14
src/test/java/com/alibaba/easyexcel/test/core/encrypt/EncryptData.java

@ -0,0 +1,14 @@
package com.alibaba.easyexcel.test.core.encrypt;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
/**
* @author Jiaju Zhuang
*/
@Data
public class EncryptData {
@ExcelProperty("姓名")
private String name;
}

35
src/test/java/com/alibaba/easyexcel/test/core/encrypt/EncryptDataListener.java

@ -0,0 +1,35 @@
package com.alibaba.easyexcel.test.core.encrypt;
import java.util.ArrayList;
import java.util.List;
import org.junit.Assert;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.fastjson.JSON;
/**
* @author Jiaju Zhuang
*/
public class EncryptDataListener extends AnalysisEventListener<EncryptData> {
private static final Logger LOGGER = LoggerFactory.getLogger(EncryptDataListener.class);
List<EncryptData> list = new ArrayList<EncryptData>();
@Override
public void invoke(EncryptData data, AnalysisContext context) {
list.add(data);
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
Assert.assertEquals(list.size(), 10);
Assert.assertEquals(list.get(0).getName(), "姓名0");
Assert.assertEquals((int)(context.readSheetHolder().getSheetNo()), 0);
Assert.assertEquals(
context.readSheetHolder().getExcelReadHeadProperty().getHeadMap().get(0).getHeadNameList().get(0), "姓名");
LOGGER.debug("First row:{}", JSON.toJSONString(list.get(0)));
}
}

88
src/test/java/com/alibaba/easyexcel/test/core/encrypt/EncryptDataTest.java

@ -0,0 +1,88 @@
package com.alibaba.easyexcel.test.core.encrypt;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;
import com.alibaba.easyexcel.test.core.simple.SimpleData;
import com.alibaba.easyexcel.test.core.simple.SimpleDataListener;
import com.alibaba.easyexcel.test.core.simple.SimpleDataSheetNameListener;
import com.alibaba.easyexcel.test.util.TestFileUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.util.FileUtils;
/**
*
* @author Jiaju Zhuang
*/
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class EncryptDataTest {
private static File file07;
private static File file03;
private static File file07OutputStream;
private static File file03OutputStream;
@BeforeClass
public static void init() {
file07 = TestFileUtil.createNewFile("encrypt07.xlsx");
file03 = TestFileUtil.createNewFile("encrypt03.xls");
file07OutputStream = TestFileUtil.createNewFile("encryptOutputStream07.xlsx");
file03OutputStream = TestFileUtil.createNewFile("encryptOutputStream03.xls");
}
@Test
public void t01ReadAndWrite07() {
readAndWrite(file07);
}
@Test
public void t02ReadAndWrite03() {
readAndWrite(file03);
}
@Test
public void t01ReadAndWriteStream07() throws Exception {
readAndWriteStream(file07OutputStream, ExcelTypeEnum.XLSX);
}
@Test
public void t02ReadAndWriteStream03() throws Exception {
readAndWriteStream(file03OutputStream, ExcelTypeEnum.XLS);
}
private void readAndWrite(File file) {
EasyExcel.write(file, EncryptData.class).password("123456").sheet().doWrite(data());
EasyExcel.read(file, EncryptData.class, new EncryptDataListener()).password("123456").sheet().doRead();
}
private void readAndWriteStream(File file, ExcelTypeEnum excelType) throws Exception {
FileOutputStream fileOutputStream = new FileOutputStream(file);
EasyExcel.write(fileOutputStream, EncryptData.class).password("123456").excelType(excelType).sheet()
.doWrite(data());
fileOutputStream.close();
FileInputStream fileInputStream = new FileInputStream(file);
EasyExcel.read(fileInputStream, EncryptData.class, new EncryptDataListener()).password("123456")
.excelType(excelType).sheet().doRead();
}
private List<SimpleData> data() {
List<SimpleData> list = new ArrayList<SimpleData>();
for (int i = 0; i < 10; i++) {
SimpleData simpleData = new SimpleData();
simpleData.setName("姓名" + i);
list.add(simpleData);
}
return list;
}
}

2
src/test/java/com/alibaba/easyexcel/test/core/exception/ExceptionDataListener.java

@ -20,7 +20,7 @@ public class ExceptionDataListener extends AnalysisEventListener<ExceptionData>
@Override
public void onException(Exception exception, AnalysisContext context) {
LOGGER.info("抛出异常,忽略:{}", exception.getMessage());
LOGGER.info("抛出异常,忽略:{}", exception.getMessage(), exception);
}
@Override

18
src/test/java/com/alibaba/easyexcel/test/core/fill/FillData.java

@ -0,0 +1,18 @@
package com.alibaba.easyexcel.test.core.fill;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.NumberFormat;
import com.alibaba.excel.converters.doubleconverter.DoubleStringConverter;
import lombok.Data;
/**
* @author Jiaju Zhuang
*/
@Data
public class FillData {
private String name;
@NumberFormat("#")
@ExcelProperty(converter = DoubleStringConverter.class)
private double number;
}

157
src/test/java/com/alibaba/easyexcel/test/core/fill/FillDataTest.java

@ -0,0 +1,157 @@
package com.alibaba.easyexcel.test.core.fill;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;
import com.alibaba.easyexcel.test.core.style.StyleData;
import com.alibaba.easyexcel.test.core.style.StyleDataListener;
import com.alibaba.easyexcel.test.util.TestFileUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.enums.WriteDirectionEnum;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.merge.LoopMergeStrategy;
import com.alibaba.excel.write.merge.OnceAbsoluteMergeStrategy;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.AbstractVerticalCellStyleStrategy;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.alibaba.excel.write.style.column.SimpleColumnWidthStyleStrategy;
import com.alibaba.excel.write.style.row.SimpleRowHeightStyleStrategy;
/**
*
* @author Jiaju Zhuang
*/
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class FillDataTest {
private static File file07;
private static File file03;
private static File simpleTemplate07;
private static File simpleTemplate03;
private static File fileComplex07;
private static File complexFillTemplate07;
private static File fileComplex03;
private static File complexFillTemplate03;
private static File fileHorizontal07;
private static File horizontalFillTemplate07;
private static File fileHorizontal03;
private static File horizontalFillTemplate03;
@BeforeClass
public static void init() {
file07 = TestFileUtil.createNewFile("fill07.xlsx");
file03 = TestFileUtil.createNewFile("fill03.xls");
simpleTemplate07 = TestFileUtil.readFile("fill" + File.separator + "simple.xlsx");
simpleTemplate03 = TestFileUtil.readFile("fill" + File.separator + "simple.xls");
fileComplex07 = TestFileUtil.createNewFile("fillComplex07.xlsx");
complexFillTemplate07 = TestFileUtil.readFile("fill" + File.separator + "complex.xlsx");
fileComplex03 = TestFileUtil.createNewFile("fillComplex03.xls");
complexFillTemplate03 = TestFileUtil.readFile("fill" + File.separator + "complex.xls");
fileHorizontal07 = TestFileUtil.createNewFile("fillHorizontal07.xlsx");
horizontalFillTemplate07 = TestFileUtil.readFile("fill" + File.separator + "horizontal.xlsx");
fileHorizontal03 = TestFileUtil.createNewFile("fillHorizontal03.xls");
horizontalFillTemplate03 = TestFileUtil.readFile("fill" + File.separator + "horizontal.xls");
}
@Test
public void t01Fill07() {
fill(file07, simpleTemplate07);
}
@Test
public void t02Fill03() {
fill(file03, simpleTemplate03);
}
@Test
public void t03ComplexFill07() {
complexFill(fileComplex07, complexFillTemplate07);
}
@Test
public void t04ComplexFill03() {
complexFill(fileComplex03, complexFillTemplate03);
}
@Test
public void t05HorizontalFill07() {
horizontalFill(fileHorizontal07, horizontalFillTemplate07);
}
@Test
public void t06HorizontalFill03() {
horizontalFill(fileHorizontal03, horizontalFillTemplate03);
}
private void horizontalFill(File file, File template) {
ExcelWriter excelWriter = EasyExcel.write(file).withTemplate(template).build();
WriteSheet writeSheet = EasyExcel.writerSheet().build();
FillConfig fillConfig = FillConfig.builder().direction(WriteDirectionEnum.HORIZONTAL).build();
excelWriter.fill(data(), fillConfig, writeSheet);
excelWriter.fill(data(), fillConfig, writeSheet);
Map<String, Object> map = new HashMap<String, Object>();
map.put("date", "2019年10月9日13:28:28");
excelWriter.fill(map, writeSheet);
excelWriter.finish();
List<Object> list = EasyExcel.read(file).sheet().headRowNumber(0).doReadSync();
Assert.assertEquals(list.size(), 5L);
Map<String, String> map0 = (Map<String, String>)list.get(0);
Assert.assertEquals("张三", map0.get(2));
}
private void complexFill(File file, File template) {
ExcelWriter excelWriter = EasyExcel.write(file).withTemplate(template).build();
WriteSheet writeSheet = EasyExcel.writerSheet().build();
FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
excelWriter.fill(data(), fillConfig, writeSheet);
excelWriter.fill(data(), fillConfig, writeSheet);
Map<String, Object> map = new HashMap<String, Object>();
map.put("date", "2019年10月9日13:28:28");
map.put("total", 1000);
excelWriter.fill(map, writeSheet);
excelWriter.finish();
List<Object> list = EasyExcel.read(file).sheet().headRowNumber(3).doReadSync();
Assert.assertEquals(list.size(), 21L);
Map<String, String> map19 = (Map<String, String>)list.get(19);
Assert.assertEquals("张三", map19.get(0));
}
private void fill(File file, File template) {
FillData fillData = new FillData();
fillData.setName("张三");
fillData.setNumber(5.2);
EasyExcel.write(file, FillData.class).withTemplate(template).sheet().doFill(fillData);
}
private List<FillData> data() {
List<FillData> list = new ArrayList<FillData>();
for (int i = 0; i < 10; i++) {
FillData fillData = new FillData();
list.add(fillData);
fillData.setName("张三");
fillData.setNumber(5.2);
}
return list;
}
}

63
src/test/java/com/alibaba/easyexcel/test/core/large/LargeDataTest.java

@ -1,13 +1,19 @@
package com.alibaba.easyexcel.test.core.large;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.junit.BeforeClass;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.easyexcel.test.demo.write.DemoData;
import com.alibaba.easyexcel.test.util.TestFileUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
/**
*
@ -15,12 +21,67 @@ import com.alibaba.excel.EasyExcel;
*/
public class LargeDataTest {
private static final Logger LOGGER = LoggerFactory.getLogger(LargeDataTest.class);
private static File fileFill07;
private static File template07;
private int i = 0;
@BeforeClass
public static void init() {
fileFill07 = TestFileUtil.createNewFile("largefill07.xlsx");
template07 = TestFileUtil.readFile("large" + File.separator + "fill.xlsx");
}
@Test
public void read() {
public void t01Read() {
long start = System.currentTimeMillis();
EasyExcel.read(TestFileUtil.getPath() + "large" + File.separator + "large07.xlsx", LargeData.class,
new LargeDataListener()).headRowNumber(2).sheet().doRead();
LOGGER.info("Large data total time spent:{}", System.currentTimeMillis() - start);
}
@Test
public void t02Fill() {
ExcelWriter excelWriter = EasyExcel.write(fileFill07).withTemplate(template07).build();
WriteSheet writeSheet = EasyExcel.writerSheet().build();
for (int j = 0; j < 100; j++) {
excelWriter.fill(data(), writeSheet);
LOGGER.info("{} fill success.", j);
}
excelWriter.finish();
}
private List<LargeData> data() {
List<LargeData> list = new ArrayList<LargeData>();
int size = i + 5000;
for (; i < size; i++) {
LargeData largeData = new LargeData();
list.add(largeData);
largeData.setStr1("str1-" + i);
largeData.setStr2("str2-" + i);
largeData.setStr3("str3-" + i);
largeData.setStr4("str4-" + i);
largeData.setStr5("str5-" + i);
largeData.setStr6("str6-" + i);
largeData.setStr7("str7-" + i);
largeData.setStr8("str8-" + i);
largeData.setStr9("str9-" + i);
largeData.setStr10("str10-" + i);
largeData.setStr11("str11-" + i);
largeData.setStr12("str12-" + i);
largeData.setStr13("str13-" + i);
largeData.setStr14("str14-" + i);
largeData.setStr15("str15-" + i);
largeData.setStr16("str16-" + i);
largeData.setStr17("str17-" + i);
largeData.setStr18("str18-" + i);
largeData.setStr19("str19-" + i);
largeData.setStr20("str20-" + i);
largeData.setStr21("str21-" + i);
largeData.setStr22("str22-" + i);
largeData.setStr23("str23-" + i);
largeData.setStr24("str24-" + i);
largeData.setStr25("str25-" + i);
}
return list;
}
}

14
src/test/java/com/alibaba/easyexcel/test/core/multiplesheets/MultipleSheetsDataTest.java

@ -40,6 +40,16 @@ public class MultipleSheetsDataTest {
read(file03);
}
@Test
public void t03Read07All() {
readAll(file07);
}
@Test
public void t04Read03All() {
readAll(file03);
}
private void read(File file) {
MultipleSheetsListener multipleSheetsListener = new MultipleSheetsListener();
ExcelReader excelReader = EasyExcel.read(file, MultipleSheetsData.class, multipleSheetsListener).build();
@ -53,4 +63,8 @@ public class MultipleSheetsDataTest {
excelReader.finish();
}
private void readAll(File file) {
EasyExcel.read(file, MultipleSheetsData.class, new MultipleSheetsListener()).doReadAll();
}
}

1
src/test/java/com/alibaba/easyexcel/test/core/multiplesheets/MultipleSheetsListener.java

@ -27,6 +27,7 @@ public class MultipleSheetsListener extends AnalysisEventListener<MultipleSheets
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
LOGGER.debug("A form is read finished.");
Assert.assertEquals(list.get(0).getTitle(), "表1数据");
LOGGER.debug("All row:{}", JSON.toJSONString(list));
}

12
src/test/java/com/alibaba/easyexcel/test/demo/fill/FillData.java

@ -0,0 +1,12 @@
package com.alibaba.easyexcel.test.demo.fill;
import lombok.Data;
/**
* @author Jiaju Zhuang
*/
@Data
public class FillData {
private String name;
private double number;
}

181
src/test/java/com/alibaba/easyexcel/test/demo/fill/FillTest.java

@ -0,0 +1,181 @@
package com.alibaba.easyexcel.test.demo.fill;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.Ignore;
import org.junit.Test;
import com.alibaba.easyexcel.test.util.TestFileUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.enums.WriteDirectionEnum;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
/**
* 写的填充写法
*
* @author Jiaju Zhuang
*/
@Ignore
public class FillTest {
/**
* 最简单的填充
*/
@Test
public void simpleFill() {
// 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
String templateFileName =
TestFileUtil.getPath() + "demo" + File.separator + "fill" + File.separator + "simple.xlsx";
// 方案1 根据对象填充
String fileName = TestFileUtil.getPath() + "simpleFill" + System.currentTimeMillis() + ".xlsx";
// 这里 会填充到第一个sheet, 然后文件流会自动关闭
FillData fillData = new FillData();
fillData.setName("张三");
fillData.setNumber(5.2);
EasyExcel.write(fileName).withTemplate(templateFileName).sheet().doFill(fillData);
// 方案2 根据Map填充
fileName = TestFileUtil.getPath() + "simpleFill" + System.currentTimeMillis() + ".xlsx";
// 这里 会填充到第一个sheet, 然后文件流会自动关闭
Map<String, Object> map = new HashMap<String, Object>();
map.put("name", "张三");
map.put("number", 5.2);
EasyExcel.write(fileName).withTemplate(templateFileName).sheet().doFill(map);
}
/**
* 填充列表
*/
@Test
public void listFill() {
// 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
// 填充list 的时候还要注意 模板中{.} 多了个点 表示list
String templateFileName =
TestFileUtil.getPath() + "demo" + File.separator + "fill" + File.separator + "list.xlsx";
// 方案1 一下子全部放到内存里面 并填充
String fileName = TestFileUtil.getPath() + "listFill" + System.currentTimeMillis() + ".xlsx";
// 这里 会填充到第一个sheet, 然后文件流会自动关闭
EasyExcel.write(fileName).withTemplate(templateFileName).sheet().doFill(data());
// 方案2 分多次 填充 会使用文件缓存(省内存)
fileName = TestFileUtil.getPath() + "listFill" + System.currentTimeMillis() + ".xlsx";
ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFileName).build();
WriteSheet writeSheet = EasyExcel.writerSheet().build();
excelWriter.fill(data(), writeSheet);
excelWriter.fill(data(), writeSheet);
// 千万别忘记关闭流
excelWriter.finish();
}
/**
* 复杂的填充
*/
@Test
public void complexFill() {
// 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
// {} 代表普通变量 {.} 代表是list的变量
String templateFileName =
TestFileUtil.getPath() + "demo" + File.separator + "fill" + File.separator + "complex.xlsx";
String fileName = TestFileUtil.getPath() + "complexFill" + System.currentTimeMillis() + ".xlsx";
ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFileName).build();
WriteSheet writeSheet = EasyExcel.writerSheet().build();
// 这里注意 入参用了forceNewRow 代表在写入list的时候不管list下面有没有空行 都会创建一行,然后下面的数据往后移动。默认 是false,会直接使用下一行,如果没有则创建。
// forceNewRow 如果设置了true,有个缺点 就是他会把所有的数据都放到内存了,所以慎用
// 简单的说 如果你的模板有list,且list不是最后一行,下面还有数据需要填充 就必须设置 forceNewRow=true 但是这个就会把所有数据放到内存 会很耗内存
// 如果数据量大 list不是最后一行 参照下一个
FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
excelWriter.fill(data(), fillConfig, writeSheet);
excelWriter.fill(data(), fillConfig, writeSheet);
Map<String, Object> map = new HashMap<String, Object>();
map.put("date", "2019年10月9日13:28:28");
map.put("total", 1000);
excelWriter.fill(map, writeSheet);
excelWriter.finish();
}
/**
* 数据量大的复杂填充
* <p>
* 这里的解决方案是 确保模板list为最后一行然后再拼接table.还有03版没救只能刚正面加内存
*/
@Test
public void complexFillWithTable() {
// 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
// {} 代表普通变量 {.} 代表是list的变量
// 这里模板 删除了list以后的数据,也就是统计的这一行
String templateFileName =
TestFileUtil.getPath() + "demo" + File.separator + "fill" + File.separator + "complexFillWithTable.xlsx";
String fileName = TestFileUtil.getPath() + "complexFillWithTable" + System.currentTimeMillis() + ".xlsx";
ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFileName).build();
WriteSheet writeSheet = EasyExcel.writerSheet().build();
// 直接写入数据
excelWriter.fill(data(), writeSheet);
excelWriter.fill(data(), writeSheet);
// 写入list之前的数据
Map<String, Object> map = new HashMap<String, Object>();
map.put("date", "2019年10月9日13:28:28");
excelWriter.fill(map, writeSheet);
// list 后面还有个统计 想办法手动写入
// 这里偷懒直接用list 也可以用对象
List<List<String>> totalListList = new ArrayList<List<String>>();
List<String> totalList = new ArrayList<String>();
totalListList.add(totalList);
totalList.add(null);
totalList.add(null);
totalList.add(null);
// 第四列
totalList.add("统计:1000");
// 这里是write 别和fill 搞错了
excelWriter.write(totalListList, writeSheet);
excelWriter.finish();
// 总体上写法比较复杂 但是也没有想到好的版本 异步的去写入excel 不支持行的删除和移动,也不支持备注这种的写入,所以也排除了可以
// 新建一个 然后一点点复制过来的方案,最后导致list需要新增行的时候,后面的列的数据没法后移,后续会继续想想解决方案
}
/**
* 横向的填充
*/
@Test
public void horizontalFill() {
// 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
// {} 代表普通变量 {.} 代表是list的变量
String templateFileName =
TestFileUtil.getPath() + "demo" + File.separator + "fill" + File.separator + "horizontal.xlsx";
String fileName = TestFileUtil.getPath() + "horizontalFill" + System.currentTimeMillis() + ".xlsx";
ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFileName).build();
WriteSheet writeSheet = EasyExcel.writerSheet().build();
FillConfig fillConfig = FillConfig.builder().direction(WriteDirectionEnum.HORIZONTAL).build();
excelWriter.fill(data(), fillConfig, writeSheet);
excelWriter.fill(data(), fillConfig, writeSheet);
Map<String, Object> map = new HashMap<String, Object>();
map.put("date", "2019年10月9日13:28:28");
excelWriter.fill(map, writeSheet);
// 别忘记关闭流
excelWriter.finish();
}
private List<FillData> data() {
List<FillData> list = new ArrayList<FillData>();
for (int i = 0; i < 10; i++) {
FillData fillData = new FillData();
list.add(fillData);
fillData.setName("张三");
fillData.setNumber(5.2);
}
return list;
}
}

50
src/test/java/com/alibaba/easyexcel/test/demo/read/CellDataDemoHeadDataListener.java

@ -0,0 +1,50 @@
package com.alibaba.easyexcel.test.demo.read;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.fastjson.JSON;
/**
* 读取头
*
* @author Jiaju Zhuang
*/
public class CellDataDemoHeadDataListener extends AnalysisEventListener<CellDataReadDemoData> {
private static final Logger LOGGER = LoggerFactory.getLogger(CellDataDemoHeadDataListener.class);
/**
* 每隔5条存储数据库实际使用中可以3000条然后清理list 方便内存回收
*/
private static final int BATCH_COUNT = 5;
List<CellDataReadDemoData> list = new ArrayList<CellDataReadDemoData>();
@Override
public void invoke(CellDataReadDemoData data, AnalysisContext context) {
LOGGER.info("解析到一条数据:{}", JSON.toJSONString(data));
if (list.size() >= BATCH_COUNT) {
saveData();
list.clear();
}
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
saveData();
LOGGER.info("所有数据解析完成!");
}
/**
* 加上存储数据库
*/
private void saveData() {
LOGGER.info("{}条数据,开始存储数据库!", list.size());
LOGGER.info("存储数据库成功!");
}
}

22
src/test/java/com/alibaba/easyexcel/test/demo/read/CellDataReadDemoData.java

@ -0,0 +1,22 @@
package com.alibaba.easyexcel.test.demo.read;
import java.util.Date;
import com.alibaba.excel.metadata.CellData;
import lombok.Data;
/**
* 基础数据类.这里的排序和excel里面的排序一致
*
* @author Jiaju Zhuang
**/
@Data
public class CellDataReadDemoData {
private CellData<String> string;
// 这里注意 虽然是日期 但是 类型 存储的是number 因为excel 存储的就是number
private CellData<Date> date;
private CellData<Double> doubleData;
// 这里并不一定能完美的获取 有些公式是依赖性的 可能会读不到 这个问题后续会修复
private CellData<String> formulaValue;
}

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

Loading…
Cancel
Save