Browse Source

支持通过模板填充数据

bugfix
Jiaju Zhuang 5 years ago
parent
commit
5ae29e3605
  1. 6
      docs/LARGEREAD.md
  2. BIN
      img/readme/quickstart/fill/complexFill.png
  3. BIN
      img/readme/quickstart/fill/complexFillTemplate.png
  4. BIN
      img/readme/quickstart/fill/complexFillWithTable.png
  5. BIN
      img/readme/quickstart/fill/complexFillWithTableTemplate.png
  6. BIN
      img/readme/quickstart/fill/horizontalFill.png
  7. BIN
      img/readme/quickstart/fill/horizontalFillTemplate.png
  8. BIN
      img/readme/quickstart/fill/listFill.png
  9. BIN
      img/readme/quickstart/fill/listFillTemplate.png
  10. BIN
      img/readme/quickstart/fill/simpleFill.png
  11. BIN
      img/readme/quickstart/fill/simpleFillTemplate.png
  12. 223
      quickstart.md
  13. 10
      src/main/java/com/alibaba/excel/ExcelReader.java
  14. 15
      src/main/java/com/alibaba/excel/ExcelWriter.java
  15. 2
      src/main/java/com/alibaba/excel/analysis/ExcelAnalyser.java
  16. 18
      src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java
  17. 2
      src/main/java/com/alibaba/excel/analysis/ExcelReadExecutor.java
  18. 4
      src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java
  19. 7
      src/main/java/com/alibaba/excel/analysis/v07/XlsxSaxAnalyser.java
  20. 6
      src/main/java/com/alibaba/excel/context/AnalysisContext.java
  21. 20
      src/main/java/com/alibaba/excel/context/AnalysisContextImpl.java
  22. 7
      src/main/java/com/alibaba/excel/context/WriteContext.java
  23. 183
      src/main/java/com/alibaba/excel/context/WriteContextImpl.java
  24. 17
      src/main/java/com/alibaba/excel/enums/WriteDirectionEnum.java
  25. 2
      src/main/java/com/alibaba/excel/enums/WriteLastRowTypeEnum.java
  26. 17
      src/main/java/com/alibaba/excel/enums/WriteTemplateAnalysisCellTypeEnum.java
  27. 17
      src/main/java/com/alibaba/excel/enums/WriteTypeEnum.java
  28. 18
      src/main/java/com/alibaba/excel/metadata/property/ExcelHeadProperty.java
  29. 3
      src/main/java/com/alibaba/excel/util/StringUtils.java
  30. 44
      src/main/java/com/alibaba/excel/util/WorkBookUtil.java
  31. 196
      src/main/java/com/alibaba/excel/util/WriteHandlerUtils.java
  32. 4
      src/main/java/com/alibaba/excel/write/ExcelBuilder.java
  33. 437
      src/main/java/com/alibaba/excel/write/ExcelBuilderImpl.java
  34. 7
      src/main/java/com/alibaba/excel/write/builder/ExcelWriterSheetBuilder.java
  35. 140
      src/main/java/com/alibaba/excel/write/executor/AbstractExcelWriteExecutor.java
  36. 179
      src/main/java/com/alibaba/excel/write/executor/ExcelWriteAddExecutor.java
  37. 9
      src/main/java/com/alibaba/excel/write/executor/ExcelWriteExecutor.java
  38. 377
      src/main/java/com/alibaba/excel/write/executor/ExcelWriteFillExecutor.java
  39. 44
      src/main/java/com/alibaba/excel/write/handler/CellWriteHandler.java
  40. 33
      src/main/java/com/alibaba/excel/write/handler/RowWriteHandler.java
  41. 4
      src/main/java/com/alibaba/excel/write/handler/SheetWriteHandler.java
  42. 11
      src/main/java/com/alibaba/excel/write/handler/WorkbookWriteHandler.java
  43. 12
      src/main/java/com/alibaba/excel/write/merge/AbstractMergeStrategy.java
  44. 52
      src/main/java/com/alibaba/excel/write/metadata/fill/AnalysisCell.java
  45. 83
      src/main/java/com/alibaba/excel/write/metadata/fill/FillConfig.java
  46. 62
      src/main/java/com/alibaba/excel/write/metadata/holder/WriteSheetHolder.java
  47. 80
      src/main/java/com/alibaba/excel/write/metadata/holder/WriteWorkbookHolder.java
  48. 40
      src/main/java/com/alibaba/excel/write/style/AbstractCellStyleStrategy.java
  49. 4
      src/main/java/com/alibaba/excel/write/style/AbstractVerticalCellStyleStrategy.java
  50. 4
      src/main/java/com/alibaba/excel/write/style/HorizontalCellStyleStrategy.java
  51. 19
      src/main/java/com/alibaba/excel/write/style/column/AbstractColumnWidthStyleStrategy.java
  52. 11
      src/main/java/com/alibaba/excel/write/style/column/AbstractHeadColumnWidthStyleStrategy.java
  53. 20
      src/main/java/com/alibaba/excel/write/style/column/LongestMatchColumnWidthStyleStrategy.java
  54. 15
      src/main/java/com/alibaba/excel/write/style/row/AbstractRowHeightStyleStrategy.java
  55. 5
      src/test/java/com/alibaba/easyexcel/test/core/fill/FillData.java
  56. 113
      src/test/java/com/alibaba/easyexcel/test/core/fill/FillDataTest.java
  57. 63
      src/test/java/com/alibaba/easyexcel/test/core/large/LargeDataTest.java
  58. 12
      src/test/java/com/alibaba/easyexcel/test/demo/fill/FillData.java
  59. 181
      src/test/java/com/alibaba/easyexcel/test/demo/fill/FillTest.java
  60. 14
      src/test/java/com/alibaba/easyexcel/test/demo/write/CustomCellWriteHandler.java
  61. 2
      src/test/java/com/alibaba/easyexcel/test/temp/large/LargeData.java
  62. 87
      src/test/java/com/alibaba/easyexcel/test/temp/poi/PoiTest.java
  63. 26
      src/test/java/com/alibaba/easyexcel/test/temp/poi/PoiWriteTest.java
  64. 2
      src/test/java/com/alibaba/easyexcel/test/temp/simple/HgTest.java
  65. BIN
      src/test/resources/demo/fill/complex.xlsx
  66. BIN
      src/test/resources/demo/fill/complexFillWithTable.xlsx
  67. BIN
      src/test/resources/demo/fill/horizontal.xlsx
  68. BIN
      src/test/resources/demo/fill/list.xlsx
  69. BIN
      src/test/resources/demo/fill/simple.xlsx
  70. BIN
      src/test/resources/fill/complex.xls
  71. BIN
      src/test/resources/fill/complex.xlsx
  72. BIN
      src/test/resources/fill/horizontal.xls
  73. BIN
      src/test/resources/fill/horizontal.xlsx
  74. BIN
      src/test/resources/fill/simple.xls
  75. BIN
      src/test/resources/fill/simple.xlsx
  76. BIN
      src/test/resources/large/fill.xlsx

6
docs/LARGEREAD.md

@ -9,6 +9,7 @@
```java ```java
// 强制使用内存存储,这样大概一个20M的excel使用150M(很多临时对象,所以100M会一直GC)的内存 // 强制使用内存存储,这样大概一个20M的excel使用150M(很多临时对象,所以100M会一直GC)的内存
// 这样效率会比上面的复杂的策略高很多 // 这样效率会比上面的复杂的策略高很多
// 这里再说明下 就是加了个readCache(new MapCache()) 参数而已,其他的参照其他demo写 这里没有写全
EasyExcel.read().readCache(new MapCache()); EasyExcel.read().readCache(new MapCache());
``` ```
### 对并发要求较高,而且都是经常有超级大文件 ### 对并发要求较高,而且都是经常有超级大文件
@ -16,7 +17,10 @@
// 第一个参数的意思是 多少M共享字符串以后 采用文件存储 单位MB 默认5M // 第一个参数的意思是 多少M共享字符串以后 采用文件存储 单位MB 默认5M
// 第二个参数 文件存储时,内存存放多少M缓存数据 默认20M // 第二个参数 文件存储时,内存存放多少M缓存数据 默认20M
// 比如 你希望用100M内存(这里说的是解析过程中的永久占用,临时对象不算)来解析excel,前面算过了 大概是 20M+90M 所以设置参数为:20 和 90 // 比如 你希望用100M内存(这里说的是解析过程中的永久占用,临时对象不算)来解析excel,前面算过了 大概是 20M+90M 所以设置参数为:20 和 90
// 这里再说明下 就是加了个readCacheSelector(new SimpleReadCacheSelector(5, 20))参数而已,其他的参照其他demo写 这里没有写全
EasyExcel.read().readCacheSelector(new SimpleReadCacheSelector(5, 20)); EasyExcel.read().readCacheSelector(new SimpleReadCacheSelector(5, 20));
``` ```
### 关于maxCacheActivateSize 也就是前面第二个参数的详细说明 ### 关于maxCacheActivateSize 也就是前面第二个参数的详细说明
easyexcel在使用文件存储的时候,会把共享字符串拆分成1000条一批,然后放到文件存储。然后excel来读取共享字符串大概率是按照顺序的,所以默认20M的1000条的数据放在内存,命中后直接返回,没命中去读文件。所以不能设置太小,太小了,很难命中,一直去读取文件,太大了的话会占用过多的内存。 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/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

223
quickstart.md

@ -47,6 +47,14 @@ DEMO代码地址:[https://github.com/alibaba/easyexcel/blob/master/src/test/ja
* [自定义拦截器(下拉,超链接等上面几点都不符合但是要对单元格进行操作的参照这个)](#customHandlerWrite) * [自定义拦截器(下拉,超链接等上面几点都不符合但是要对单元格进行操作的参照这个)](#customHandlerWrite)
* [web中的写](#webWrite) * [web中的写](#webWrite)
### 填充
DEMO代码地址:[https://github.com/alibaba/easyexcel/blob/master/src/test/java/com/alibaba/easyexcel/test/demo/fill/FillTest.java](/src/test/java/com/alibaba/easyexcel/test/demo/fill/FillTest.java)
* [最简单的填充](#simpleFill)
* [填充列表](#listFill)
* [复杂的填充](#complexFill)
* [数据量大的复杂填充](#complexFillWithTable)
* [横向的填充](#horizontalFill)
## 读excel样例 ## 读excel样例
### <span id="simpleRead" />最简单的读 ### <span id="simpleRead" />最简单的读
##### <span id="simpleReadExcel" />excel示例 ##### <span id="simpleReadExcel" />excel示例
@ -1021,13 +1029,19 @@ public class CustomCellWriteHandler implements CellWriteHandler {
@Override @Override
public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, 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 @Override
public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
Cell cell, Head head, int relativeRowIndex, boolean isHead) { List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
// 这里可以对cell进行任何操作 // 这里可以对cell进行任何操作
LOGGER.info("第{}行,第{}列写入完成。", cell.getRowIndex(), cell.getColumnIndex()); LOGGER.info("第{}行,第{}列写入完成。", cell.getRowIndex(), cell.getColumnIndex());
if (isHead && cell.getColumnIndex() == 0) { if (isHead && cell.getColumnIndex() == 0) {
@ -1118,6 +1132,209 @@ DEMO代码地址:[https://github.com/alibaba/easyexcel/blob/master/src/test/ja
EasyExcel.write(response.getOutputStream(), DownloadData.class).sheet("模板").doWrite(data()); EasyExcel.write(response.getOutputStream(), DownloadData.class).sheet("模板").doWrite(data());
} }
``` ```
## 填充excel样例
### <span id="simpleFill" />最简单的填充
##### 模板
![img](img/readme/quickstart/fill/simpleFillTemplate.png)
##### 最终效果
![img](img/readme/quickstart/fill/simpleFill.png)
##### <span id="simpleFillObject" />对象
```java
@Data
public class FillData {
private String name;
private double number;
}
```
##### 代码
```java
/**
* 最简单的填充
*/
@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);
}
```
### <span id="listFill" />填充列表
##### 模板
![img](img/readme/quickstart/fill/listFillTemplate.png)
##### 最终效果
![img](img/readme/quickstart/fill/listFill.png)
##### <span id="simpleFillObject" />对象
参照:[对象](#simpleFillObject)
##### 代码
```java
/**
* 填充列表
*/
@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();
}
```
### <span id="complexFill" />复杂的填充
##### 模板
![img](img/readme/quickstart/fill/complexFillTemplate.png)
##### 最终效果
![img](img/readme/quickstart/fill/complexFill.png)
##### <span id="simpleFillObject" />对象
参照:[对象](#simpleFillObject)
##### 代码
```java
/**
* 复杂的填充
*/
@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();
}
```
### <span id="complexFillWithTable" />数据量大的复杂填充
##### 模板
![img](img/readme/quickstart/fill/complexFillWithTableTemplate.png)
##### 最终效果
![img](img/readme/quickstart/fill/complexFillWithTable.png)
##### <span id="simpleFillObject" />对象
参照:[对象](#simpleFillObject)
##### 代码
```java
/**
* 数据量大的复杂填充
* <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需要新增行的时候,后面的列的数据没法后移,后续会继续想想解决方案
}
```
### <span id="horizontalFill" />横向的填充
##### 模板
![img](img/readme/quickstart/fill/horizontalFillTemplate.png)
##### 最终效果
![img](img/readme/quickstart/fill/horizontalFill.png)
##### <span id="simpleFillObject" />对象
参照:[对象](#simpleFillObject)
##### 代码
```java
/**
* 横向的填充
*/
@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();
}
```
## 测试数据分析 ## 测试数据分析
![POI usermodel PK easyexcel(Excel 2003).png](http://ata2-img.cn-hangzhou.img-pub.aliyun-inc.com/02c4bfbbab99a649788523d04f84a42f.png) ![POI usermodel PK easyexcel(Excel 2003).png](http://ata2-img.cn-hangzhou.img-pub.aliyun-inc.com/02c4bfbbab99a649788523d04f84a42f.png)
![POI usermodel PK easyexcel(Excel 2007).png](http://ata2-img.cn-hangzhou.img-pub.aliyun-inc.com/f6a8a19ec959f0eb564e652de523fc9e.png) ![POI usermodel PK easyexcel(Excel 2007).png](http://ata2-img.cn-hangzhou.img-pub.aliyun-inc.com/f6a8a19ec959f0eb564e652de523fc9e.png)

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

@ -9,7 +9,7 @@ import org.slf4j.LoggerFactory;
import com.alibaba.excel.analysis.ExcelAnalyser; import com.alibaba.excel.analysis.ExcelAnalyser;
import com.alibaba.excel.analysis.ExcelAnalyserImpl; 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.cache.MapCache;
import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener; import com.alibaba.excel.event.AnalysisEventListener;
@ -149,12 +149,12 @@ public class ExcelReader {
* Parse all sheet content by default * Parse all sheet content by default
*/ */
public void read() { public void read() {
ExcelExecutor excelExecutor = excelAnalyser.excelExecutor(); ExcelReadExecutor excelReadExecutor = excelAnalyser.excelExecutor();
if (excelExecutor.sheetList().isEmpty()) { if (excelReadExecutor.sheetList().isEmpty()) {
LOGGER.warn("Excel doesn't have any sheets."); LOGGER.warn("Excel doesn't have any sheets.");
return; return;
} }
for (ReadSheet readSheet : excelExecutor.sheetList()) { for (ReadSheet readSheet : excelReadExecutor.sheetList()) {
read(readSheet); read(readSheet);
} }
} }
@ -225,7 +225,7 @@ public class ExcelReader {
* *
* @return * @return
*/ */
public ExcelExecutor excelExecutor() { public ExcelReadExecutor excelExecutor() {
checkFinished(); checkFinished();
return excelAnalyser.excelExecutor(); return excelAnalyser.excelExecutor();
} }

15
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.WriteSheet;
import com.alibaba.excel.write.metadata.WriteTable; import com.alibaba.excel.write.metadata.WriteTable;
import com.alibaba.excel.write.metadata.WriteWorkbook; 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 * Excel Writer This tool is used to write value out to Excel via POI. This object can perform the following two
@ -164,7 +165,19 @@ public class ExcelWriter {
* @return * @return
*/ */
public ExcelWriter fill(Object data, WriteSheet writeSheet) { public ExcelWriter fill(Object data, WriteSheet writeSheet) {
excelBuilder.fill(data, 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; return this;
} }

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

@ -27,7 +27,7 @@ public interface ExcelAnalyser {
* *
* @return Excel file Executor * @return Excel file Executor
*/ */
ExcelExecutor excelExecutor(); ExcelReadExecutor excelExecutor();
/** /**
* get the analysis context. * get the analysis context.

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

@ -29,7 +29,7 @@ public class ExcelAnalyserImpl implements ExcelAnalyser {
private AnalysisContext analysisContext; private AnalysisContext analysisContext;
private ExcelExecutor excelExecutor; private ExcelReadExecutor excelReadExecutor;
public ExcelAnalyserImpl(ReadWorkbook readWorkbook) { public ExcelAnalyserImpl(ReadWorkbook readWorkbook) {
try { try {
@ -48,7 +48,7 @@ public class ExcelAnalyserImpl implements ExcelAnalyser {
ReadWorkbookHolder readWorkbookHolder = analysisContext.readWorkbookHolder(); ReadWorkbookHolder readWorkbookHolder = analysisContext.readWorkbookHolder();
ExcelTypeEnum excelType = readWorkbookHolder.getExcelType(); ExcelTypeEnum excelType = readWorkbookHolder.getExcelType();
if (excelType == null) { if (excelType == null) {
excelExecutor = new XlsxSaxAnalyser(analysisContext, null); excelReadExecutor = new XlsxSaxAnalyser(analysisContext, null);
return; return;
} }
switch (excelType) { switch (excelType) {
@ -65,7 +65,7 @@ public class ExcelAnalyserImpl implements ExcelAnalyser {
try { try {
decryptedStream = decryptedStream =
DocumentFactoryHelper.getDecryptedStream(poifsFileSystem.getRoot().getFileSystem(), null); DocumentFactoryHelper.getDecryptedStream(poifsFileSystem.getRoot().getFileSystem(), null);
excelExecutor = new XlsxSaxAnalyser(analysisContext, decryptedStream); excelReadExecutor = new XlsxSaxAnalyser(analysisContext, decryptedStream);
return; return;
} finally { } finally {
IOUtils.closeQuietly(decryptedStream); IOUtils.closeQuietly(decryptedStream);
@ -74,10 +74,10 @@ public class ExcelAnalyserImpl implements ExcelAnalyser {
poifsFileSystem.close(); poifsFileSystem.close();
} }
} }
excelExecutor = new XlsSaxAnalyser(analysisContext, poifsFileSystem); excelReadExecutor = new XlsSaxAnalyser(analysisContext, poifsFileSystem);
break; break;
case XLSX: case XLSX:
excelExecutor = new XlsxSaxAnalyser(analysisContext, null); excelReadExecutor = new XlsxSaxAnalyser(analysisContext, null);
break; break;
default: default:
} }
@ -86,9 +86,9 @@ public class ExcelAnalyserImpl implements ExcelAnalyser {
@Override @Override
public void analysis(ReadSheet readSheet) { public void analysis(ReadSheet readSheet) {
try { try {
analysisContext.currentSheet(excelExecutor, readSheet); analysisContext.currentSheet(excelReadExecutor, readSheet);
try { try {
excelExecutor.execute(); excelReadExecutor.execute();
} catch (ExcelAnalysisStopException e) { } catch (ExcelAnalysisStopException e) {
if (LOGGER.isDebugEnabled()) { if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Custom stop!"); LOGGER.debug("Custom stop!");
@ -153,8 +153,8 @@ public class ExcelAnalyserImpl implements ExcelAnalyser {
} }
@Override @Override
public com.alibaba.excel.analysis.ExcelExecutor excelExecutor() { public ExcelReadExecutor excelExecutor() {
return excelExecutor; return excelReadExecutor;
} }
@Override @Override

2
src/main/java/com/alibaba/excel/analysis/ExcelExecutor.java → src/main/java/com/alibaba/excel/analysis/ExcelReadExecutor.java

@ -9,7 +9,7 @@ import com.alibaba.excel.read.metadata.ReadSheet;
* *
* @author Jiaju Zhuang * @author Jiaju Zhuang
*/ */
public interface ExcelExecutor { public interface ExcelReadExecutor {
/** /**
* Returns the actual sheet in excel * Returns the actual sheet in excel

4
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.Logger;
import org.slf4j.LoggerFactory; 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.BlankOrErrorRecordHandler;
import com.alibaba.excel.analysis.v03.handlers.BofRecordHandler; import com.alibaba.excel.analysis.v03.handlers.BofRecordHandler;
import com.alibaba.excel.analysis.v03.handlers.FormulaRecordHandler; import com.alibaba.excel.analysis.v03.handlers.FormulaRecordHandler;
@ -56,7 +56,7 @@ import com.alibaba.excel.util.CollectionUtils;
* *
* @author jipengfei * @author jipengfei
*/ */
public class XlsSaxAnalyser implements HSSFListener, ExcelExecutor { public class XlsSaxAnalyser implements HSSFListener, ExcelReadExecutor {
private static final Logger LOGGER = LoggerFactory.getLogger(XlsSaxAnalyser.class); private static final Logger LOGGER = LoggerFactory.getLogger(XlsSaxAnalyser.class);
private POIFSFileSystem poifsFileSystem; private POIFSFileSystem poifsFileSystem;

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

@ -13,6 +13,7 @@ import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory; import javax.xml.parsers.SAXParserFactory;
import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackageAccess;
import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.xssf.eventusermodel.XSSFReader; import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.model.StylesTable; import org.apache.poi.xssf.model.StylesTable;
@ -24,7 +25,7 @@ import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource; import org.xml.sax.InputSource;
import org.xml.sax.XMLReader; 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.cache.ReadCache;
import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.exception.ExcelAnalysisException; import com.alibaba.excel.exception.ExcelAnalysisException;
@ -37,7 +38,7 @@ import com.alibaba.excel.util.FileUtils;
* *
* @author jipengfei * @author jipengfei
*/ */
public class XlsxSaxAnalyser implements ExcelExecutor { public class XlsxSaxAnalyser implements ExcelReadExecutor {
private AnalysisContext analysisContext; private AnalysisContext analysisContext;
private List<ReadSheet> sheetList; private List<ReadSheet> sheetList;
@ -135,7 +136,7 @@ public class XlsxSaxAnalyser implements ExcelExecutor {
} else { } else {
FileUtils.writeToFile(tempFile, readWorkbookHolder.getInputStream()); FileUtils.writeToFile(tempFile, readWorkbookHolder.getInputStream());
} }
return OPCPackage.open(tempFile); return OPCPackage.open(tempFile, PackageAccess.READ);
} }
@Override @Override

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

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

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

@ -5,7 +5,7 @@ import java.io.InputStream;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.alibaba.excel.analysis.ExcelExecutor; import com.alibaba.excel.analysis.ExcelReadExecutor;
import com.alibaba.excel.analysis.v07.XlsxSaxAnalyser; import com.alibaba.excel.analysis.v07.XlsxSaxAnalyser;
import com.alibaba.excel.exception.ExcelAnalysisException; import com.alibaba.excel.exception.ExcelAnalysisException;
import com.alibaba.excel.metadata.Sheet; import com.alibaba.excel.metadata.Sheet;
@ -53,13 +53,13 @@ public class AnalysisContextImpl implements AnalysisContext {
} }
@Override @Override
public void currentSheet(ExcelExecutor excelExecutor, ReadSheet readSheet) { public void currentSheet(ExcelReadExecutor excelReadExecutor, ReadSheet readSheet) {
if (readSheet == null) { if (readSheet == null) {
throw new IllegalArgumentException("Sheet argument cannot be null."); throw new IllegalArgumentException("Sheet argument cannot be null.");
} }
readSheetHolder = new ReadSheetHolder(readSheet, readWorkbookHolder); readSheetHolder = new ReadSheetHolder(readSheet, readWorkbookHolder);
currentReadHolder = readSheetHolder; currentReadHolder = readSheetHolder;
selectSheet(excelExecutor); selectSheet(excelReadExecutor);
if (readWorkbookHolder.getHasReadSheet().contains(readSheetHolder.getSheetNo())) { if (readWorkbookHolder.getHasReadSheet().contains(readSheetHolder.getSheetNo())) {
throw new ExcelAnalysisException("Cannot read sheet repeatedly."); throw new ExcelAnalysisException("Cannot read sheet repeatedly.");
} }
@ -69,9 +69,9 @@ public class AnalysisContextImpl implements AnalysisContext {
} }
} }
private void selectSheet(ExcelExecutor excelExecutor) { private void selectSheet(ExcelReadExecutor excelReadExecutor) {
if (excelExecutor instanceof XlsxSaxAnalyser) { if (excelReadExecutor instanceof XlsxSaxAnalyser) {
selectSheet07(excelExecutor); selectSheet07(excelReadExecutor);
} else { } else {
selectSheet03(); selectSheet03();
} }
@ -87,9 +87,9 @@ public class AnalysisContextImpl implements AnalysisContext {
readSheetHolder.setSheetNo(0); readSheetHolder.setSheetNo(0);
} }
private void selectSheet07(ExcelExecutor excelExecutor) { private void selectSheet07(ExcelReadExecutor excelReadExecutor) {
if (readSheetHolder.getSheetNo() != null && readSheetHolder.getSheetNo() >= 0) { if (readSheetHolder.getSheetNo() != null && readSheetHolder.getSheetNo() >= 0) {
for (ReadSheet readSheetExcel : excelExecutor.sheetList()) { for (ReadSheet readSheetExcel : excelReadExecutor.sheetList()) {
if (readSheetExcel.getSheetNo().equals(readSheetHolder.getSheetNo())) { if (readSheetExcel.getSheetNo().equals(readSheetHolder.getSheetNo())) {
readSheetHolder.setSheetName(readSheetExcel.getSheetName()); readSheetHolder.setSheetName(readSheetExcel.getSheetName());
return; return;
@ -98,7 +98,7 @@ public class AnalysisContextImpl implements AnalysisContext {
throw new ExcelAnalysisException("Can not find sheet:" + readSheetHolder.getSheetNo()); throw new ExcelAnalysisException("Can not find sheet:" + readSheetHolder.getSheetNo());
} }
if (!StringUtils.isEmpty(readSheetHolder.getSheetName())) { if (!StringUtils.isEmpty(readSheetHolder.getSheetName())) {
for (ReadSheet readSheetExcel : excelExecutor.sheetList()) { for (ReadSheet readSheetExcel : excelReadExecutor.sheetList()) {
String sheetName = readSheetExcel.getSheetName(); String sheetName = readSheetExcel.getSheetName();
if (sheetName == null) { if (sheetName == null) {
continue; continue;
@ -112,7 +112,7 @@ public class AnalysisContextImpl implements AnalysisContext {
} }
} }
} }
ReadSheet readSheetExcel = excelExecutor.sheetList().get(0); ReadSheet readSheetExcel = excelReadExecutor.sheetList().get(0);
readSheetHolder.setSheetNo(readSheetExcel.getSheetNo()); readSheetHolder.setSheetNo(readSheetExcel.getSheetNo());
readSheetHolder.setSheetName(readSheetExcel.getSheetName()); readSheetHolder.setSheetName(readSheetExcel.getSheetName());
} }

7
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.Sheet;
import org.apache.poi.ss.usermodel.Workbook; 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.WriteSheet;
import com.alibaba.excel.write.metadata.WriteTable; import com.alibaba.excel.write.metadata.WriteTable;
import com.alibaba.excel.write.metadata.holder.WriteHolder; 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 * 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 * If the current table already exists, select it; if not, create it

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

@ -1,7 +1,6 @@
package com.alibaba.excel.context; package com.alibaba.excel.context;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.List;
import java.util.Map; import java.util.Map;
import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Cell;
@ -10,18 +9,15 @@ import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.streaming.SXSSFWorkbook; import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.alibaba.excel.enums.WriteTypeEnum;
import com.alibaba.excel.exception.ExcelGenerateException; import com.alibaba.excel.exception.ExcelGenerateException;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head; import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.util.WorkBookUtil; import com.alibaba.excel.util.WorkBookUtil;
import com.alibaba.excel.write.handler.CellWriteHandler; import com.alibaba.excel.util.WriteHandlerUtils;
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.write.metadata.WriteSheet; import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.WriteTable; import com.alibaba.excel.write.metadata.WriteTable;
import com.alibaba.excel.write.metadata.WriteWorkbook; import com.alibaba.excel.write.metadata.WriteWorkbook;
@ -65,42 +61,18 @@ public class WriteContextImpl implements WriteContext {
LOGGER.debug("Begin to Initialization 'WriteContextImpl'"); LOGGER.debug("Begin to Initialization 'WriteContextImpl'");
} }
initCurrentWorkbookHolder(writeWorkbook); initCurrentWorkbookHolder(writeWorkbook);
beforeWorkbookCreate(); WriteHandlerUtils.beforeWorkbookCreate(this);
try { try {
writeWorkbookHolder.setWorkbook(WorkBookUtil.createWorkBook(writeWorkbookHolder)); WorkBookUtil.createWorkBook(writeWorkbookHolder);
} catch (Exception e) { } catch (Exception e) {
throw new ExcelGenerateException("Create workbook failure", e); throw new ExcelGenerateException("Create workbook failure", e);
} }
afterWorkbookCreate(); WriteHandlerUtils.afterWorkbookCreate(this);
if (LOGGER.isDebugEnabled()) { if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Initialization 'WriteContextImpl' complete"); 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) { private void initCurrentWorkbookHolder(WriteWorkbook writeWorkbook) {
writeWorkbookHolder = new WriteWorkbookHolder(writeWorkbook); writeWorkbookHolder = new WriteWorkbookHolder(writeWorkbook);
currentWriteHolder = writeWorkbookHolder; currentWriteHolder = writeWorkbookHolder;
@ -113,7 +85,7 @@ public class WriteContextImpl implements WriteContext {
* @param writeSheet * @param writeSheet
*/ */
@Override @Override
public void currentSheet(WriteSheet writeSheet) { public void currentSheet(WriteSheet writeSheet, WriteTypeEnum writeType) {
if (writeSheet == null) { if (writeSheet == null) {
throw new IllegalArgumentException("Sheet argument cannot be null"); throw new IllegalArgumentException("Sheet argument cannot be null");
} }
@ -137,38 +109,10 @@ public class WriteContextImpl implements WriteContext {
return; return;
} }
initCurrentSheetHolder(writeSheet); initCurrentSheetHolder(writeSheet);
beforeSheetCreate(); WriteHandlerUtils.beforeSheetCreate(this);
// Initialization current sheet // Initialization current sheet
initSheet(); initSheet(writeType);
afterSheetCreate(); WriteHandlerUtils.afterSheetCreate(this);
}
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());
}
} }
private void initCurrentSheetHolder(WriteSheet writeSheet) { private void initCurrentSheetHolder(WriteSheet writeSheet) {
@ -181,29 +125,24 @@ public class WriteContextImpl implements WriteContext {
} }
} }
private void initSheet() { private void initSheet(WriteTypeEnum writeType) {
try {
if (writeWorkbookHolder.getXssfWorkbook() != null) {
writeSheetHolder
.setXssfSheet(writeWorkbookHolder.getXssfWorkbook().getSheetAt(writeSheetHolder.getSheetNo()));
}
} catch (Exception e) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Can not find XSSFSheet:{}.", writeSheetHolder.getSheetNo());
}
}
Sheet currentSheet; Sheet currentSheet;
try { try {
currentSheet = writeWorkbookHolder.getWorkbook().getSheetAt(writeSheetHolder.getSheetNo()); currentSheet = writeWorkbookHolder.getWorkbook().getSheetAt(writeSheetHolder.getSheetNo());
writeSheetHolder
.setCachedSheet(writeWorkbookHolder.getCachedWorkbook().getSheetAt(writeSheetHolder.getSheetNo()));
} catch (Exception e) { } catch (Exception e) {
if (LOGGER.isDebugEnabled()) { if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Can not find sheet:{} ,now create it", writeSheetHolder.getSheetNo()); LOGGER.debug("Can not find sheet:{} ,now create it", writeSheetHolder.getSheetNo());
} }
currentSheet = WorkBookUtil.createSheet(writeWorkbookHolder.getWorkbook(), writeSheetHolder.getSheetName()); currentSheet = WorkBookUtil.createSheet(writeWorkbookHolder.getWorkbook(), writeSheetHolder.getSheetName());
writeSheetHolder.setCachedSheet(currentSheet);
} }
writeSheetHolder.setSheet(currentSheet); writeSheetHolder.setSheet(currentSheet);
// Initialization head if (WriteTypeEnum.ADD.equals(writeType)) {
initHead(writeSheetHolder.excelWriteHeadProperty()); // Initialization head
initHead(writeSheetHolder.excelWriteHeadProperty());
}
} }
public void initHead(ExcelWriteHeadProperty excelWriteHeadProperty) { public void initHead(ExcelWriteHeadProperty excelWriteHeadProperty) {
@ -216,42 +155,13 @@ public class WriteContextImpl implements WriteContext {
addMergedRegionToCurrentSheet(excelWriteHeadProperty, newRowIndex); addMergedRegionToCurrentSheet(excelWriteHeadProperty, newRowIndex);
for (int relativeRowIndex = 0, i = newRowIndex; i < excelWriteHeadProperty.getHeadRowNumber() + newRowIndex; for (int relativeRowIndex = 0, i = newRowIndex; i < excelWriteHeadProperty.getHeadRowNumber() + newRowIndex;
i++, relativeRowIndex++) { i++, relativeRowIndex++) {
beforeRowCreate(newRowIndex, relativeRowIndex); WriteHandlerUtils.beforeRowCreate(this, newRowIndex, relativeRowIndex, Boolean.TRUE);
Row row = WorkBookUtil.createRow(writeSheetHolder.getSheet(), i); Row row = WorkBookUtil.createRow(writeSheetHolder.getSheet(), i);
afterRowCreate(row, relativeRowIndex); WriteHandlerUtils.afterRowCreate(this, row, relativeRowIndex, Boolean.TRUE);
addOneRowOfHeadDataToExcel(row, excelWriteHeadProperty.getHeadMap(), relativeRowIndex); 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) { private void addMergedRegionToCurrentSheet(ExcelWriteHeadProperty excelWriteHeadProperty, int rowIndex) {
for (com.alibaba.excel.metadata.CellRange cellRangeModel : excelWriteHeadProperty.headCellRangeList()) { for (com.alibaba.excel.metadata.CellRange cellRangeModel : excelWriteHeadProperty.headCellRangeList()) {
writeSheetHolder.getSheet().addMergedRegion(new CellRangeAddress(cellRangeModel.getFirstRow() + rowIndex, writeSheetHolder.getSheet().addMergedRegion(new CellRangeAddress(cellRangeModel.getFirstRow() + rowIndex,
@ -262,38 +172,13 @@ public class WriteContextImpl implements WriteContext {
private void addOneRowOfHeadDataToExcel(Row row, Map<Integer, Head> headMap, int relativeRowIndex) { private void addOneRowOfHeadDataToExcel(Row row, Map<Integer, Head> headMap, int relativeRowIndex) {
for (Map.Entry<Integer, Head> entry : headMap.entrySet()) { for (Map.Entry<Integer, Head> entry : headMap.entrySet()) {
Head head = entry.getValue(); Head head = entry.getValue();
beforeCellCreate(row, head, relativeRowIndex); int columnIndex = entry.getKey();
Cell cell = WorkBookUtil.createCell(row, entry.getKey(), head.getHeadNameList().get(relativeRowIndex)); WriteHandlerUtils.beforeCellCreate(this, row, head, columnIndex, relativeRowIndex, Boolean.TRUE);
afterCellCreate(head, cell, relativeRowIndex); Cell cell = row.createCell(columnIndex);
} WriteHandlerUtils.afterCellCreate(this, cell, head, relativeRowIndex, Boolean.TRUE);
} cell.setCellValue(head.getHeadNameList().get(relativeRowIndex));
CellData cellData = null;
private void beforeCellCreate(Row row, Head head, int relativeRowIndex) { WriteHandlerUtils.afterCellDispose(this, cellData, cell, head, relativeRowIndex, Boolean.TRUE);
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);
} }
} }
@ -352,10 +237,10 @@ public class WriteContextImpl implements WriteContext {
@Override @Override
public void finish() { public void finish() {
WriteHandlerUtils.afterWorkbookDispose(this);
if (writeWorkbookHolder == null) { if (writeWorkbookHolder == null) {
return; return;
} }
try { try {
writeWorkbookHolder.getWorkbook().write(writeWorkbookHolder.getOutputStream()); writeWorkbookHolder.getWorkbook().write(writeWorkbookHolder.getOutputStream());
writeWorkbookHolder.getWorkbook().close(); writeWorkbookHolder.getWorkbook().close();
@ -370,13 +255,6 @@ public class WriteContextImpl implements WriteContext {
} catch (Throwable t) { } catch (Throwable t) {
throwCanNotCloseIo(t); throwCanNotCloseIo(t);
} }
try {
if (writeWorkbookHolder.getTempTemplateInputStream() != null) {
writeWorkbookHolder.getTempTemplateInputStream().close();
}
} catch (Throwable t) {
throwCanNotCloseIo(t);
}
try { try {
if (writeWorkbookHolder.getAutoCloseStream() && writeWorkbookHolder.getOutputStream() != null) { if (writeWorkbookHolder.getAutoCloseStream() && writeWorkbookHolder.getOutputStream() != null) {
writeWorkbookHolder.getOutputStream().close(); writeWorkbookHolder.getOutputStream().close();
@ -385,9 +263,8 @@ public class WriteContextImpl implements WriteContext {
throwCanNotCloseIo(t); throwCanNotCloseIo(t);
} }
try { try {
if (!writeWorkbookHolder.getAutoCloseStream() && writeWorkbookHolder.getFile() != null if (writeWorkbookHolder.getTempTemplateInputStream() != null) {
&& writeWorkbookHolder.getOutputStream() != null) { writeWorkbookHolder.getTempTemplateInputStream().close();
writeWorkbookHolder.getOutputStream().close();
} }
} catch (Throwable t) { } catch (Throwable t) {
throwCanNotCloseIo(t); throwCanNotCloseIo(t);

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 * @author Jiaju Zhuang
**/ **/
public enum WriteLastRowType { public enum WriteLastRowTypeEnum {
/** /**
* Excel are created without templates ,And any data has been written; * 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,;
}

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

@ -52,6 +52,10 @@ public class ExcelHeadProperty {
* Configuration column information * Configuration column information
*/ */
private Map<Integer, ExcelContentProperty> contentPropertyMap; private Map<Integer, ExcelContentProperty> contentPropertyMap;
/**
* Configuration column information
*/
private Map<String, ExcelContentProperty> fieldNameContentPropertyMap;
/** /**
* Fields ignored * Fields ignored
*/ */
@ -61,6 +65,7 @@ public class ExcelHeadProperty {
this.headClazz = headClazz; this.headClazz = headClazz;
headMap = new TreeMap<Integer, Head>(); headMap = new TreeMap<Integer, Head>();
contentPropertyMap = new TreeMap<Integer, ExcelContentProperty>(); contentPropertyMap = new TreeMap<Integer, ExcelContentProperty>();
fieldNameContentPropertyMap = new HashMap<String, ExcelContentProperty>();
ignoreMap = new HashMap<String, Field>(16); ignoreMap = new HashMap<String, Field>(16);
headKind = HeadKindEnum.NONE; headKind = HeadKindEnum.NONE;
headRowNumber = 0; headRowNumber = 0;
@ -78,10 +83,6 @@ public class ExcelHeadProperty {
if (LOGGER.isDebugEnabled()) { if (LOGGER.isDebugEnabled()) {
LOGGER.debug("The initialization sheet/table 'ExcelHeadProperty' is complete , head kind is {}", headKind); 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() { private void initHeadRowNumber() {
@ -190,6 +191,7 @@ public class ExcelHeadProperty {
.setNumberFormatProperty(NumberFormatProperty.build(field.getAnnotation(NumberFormat.class))); .setNumberFormatProperty(NumberFormatProperty.build(field.getAnnotation(NumberFormat.class)));
headMap.put(index, head); headMap.put(index, head);
contentPropertyMap.put(index, excelContentProperty); contentPropertyMap.put(index, excelContentProperty);
fieldNameContentPropertyMap.put(field.getName(), excelContentProperty);
} }
public Class getHeadClazz() { public Class getHeadClazz() {
@ -236,6 +238,14 @@ public class ExcelHeadProperty {
this.contentPropertyMap = contentPropertyMap; 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() { public Map<String, Field> getIgnoreMap() {
return ignoreMap; return ignoreMap;
} }

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

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

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

@ -2,6 +2,7 @@ package com.alibaba.excel.util;
import java.io.IOException; import java.io.IOException;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.poifs.filesystem.POIFSFileSystem;
@ -22,36 +23,31 @@ import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
*/ */
public class WorkBookUtil { public class WorkBookUtil {
private static final int ROW_ACCESS_WINDOW_SIZE = 500;
private WorkBookUtil() {} private WorkBookUtil() {}
public static Workbook createWorkBook(WriteWorkbookHolder writeWorkbookHolder) public static void createWorkBook(WriteWorkbookHolder writeWorkbookHolder) throws IOException {
throws IOException, InvalidFormatException {
if (ExcelTypeEnum.XLSX.equals(writeWorkbookHolder.getExcelType())) { if (ExcelTypeEnum.XLSX.equals(writeWorkbookHolder.getExcelType())) {
XSSFWorkbook xssfWorkbook = null; if (writeWorkbookHolder.getTempTemplateInputStream() != null) {
if (writeWorkbookHolder.getTemplateFile() != null) { XSSFWorkbook xssfWorkbook = new XSSFWorkbook(writeWorkbookHolder.getTempTemplateInputStream());
xssfWorkbook = new XSSFWorkbook(writeWorkbookHolder.getTemplateFile()); writeWorkbookHolder.setCachedWorkbook(xssfWorkbook);
} writeWorkbookHolder.setWorkbook(new SXSSFWorkbook(xssfWorkbook, ROW_ACCESS_WINDOW_SIZE));
if (writeWorkbookHolder.getTemplateInputStream() != null) { return;
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 SXSSFWorkbook sxssWorkbook = new SXSSFWorkbook(ROW_ACCESS_WINDOW_SIZE);
// are using the template, so we cache it writeWorkbookHolder.setCachedWorkbook(sxssWorkbook);
if (xssfWorkbook != null) { writeWorkbookHolder.setWorkbook(sxssWorkbook);
writeWorkbookHolder.setXssfWorkbook(xssfWorkbook); return;
for (int i = 0; i < xssfWorkbook.getNumberOfSheets(); i++) {
writeWorkbookHolder.getTemplateLastRowMap().put(i, xssfWorkbook.getSheetAt(i).getLastRowNum());
}
return new SXSSFWorkbook(xssfWorkbook);
}
return new SXSSFWorkbook(500);
}
if (writeWorkbookHolder.getTemplateFile() != null) {
return new HSSFWorkbook(new POIFSFileSystem(writeWorkbookHolder.getTemplateFile()));
} }
if (writeWorkbookHolder.getTemplateInputStream() != null) { HSSFWorkbook hssfWorkbook;
return new HSSFWorkbook(new POIFSFileSystem(writeWorkbookHolder.getTemplateInputStream())); if (writeWorkbookHolder.getTempTemplateInputStream() != null) {
hssfWorkbook = new HSSFWorkbook(new POIFSFileSystem(writeWorkbookHolder.getTempTemplateInputStream()));
} else {
hssfWorkbook = new HSSFWorkbook();
} }
return new HSSFWorkbook(); writeWorkbookHolder.setCachedWorkbook(hssfWorkbook);
writeWorkbookHolder.setWorkbook(hssfWorkbook);
} }
public static Sheet createSheet(Workbook workbook, String sheetName) { 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);
}
}
}

4
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.merge.OnceAbsoluteMergeStrategy;
import com.alibaba.excel.write.metadata.WriteSheet; import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.WriteTable; import com.alibaba.excel.write.metadata.WriteTable;
import com.alibaba.excel.write.metadata.fill.FillConfig;
/** /**
* @author jipengfei * @author jipengfei
@ -40,9 +41,10 @@ public interface ExcelBuilder {
* WorkBook fill value * WorkBook fill value
* *
* @param data * @param data
* @param fillConfig
* @param writeSheet * @param writeSheet
*/ */
void fill(Object data, WriteSheet writeSheet); void fill(Object data, FillConfig fillConfig, WriteSheet writeSheet);
/** /**
* Creates new cell range. Indexes are zero-based. * Creates new cell range. Indexes are zero-based.

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

@ -1,63 +1,29 @@
package com.alibaba.excel.write; package com.alibaba.excel.write;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
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 org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import com.alibaba.excel.context.WriteContext; import com.alibaba.excel.context.WriteContext;
import com.alibaba.excel.context.WriteContextImpl; import com.alibaba.excel.context.WriteContextImpl;
import com.alibaba.excel.converters.Converter; import com.alibaba.excel.enums.WriteTypeEnum;
import com.alibaba.excel.converters.ConverterKeyBuild;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.enums.HeadKindEnum;
import com.alibaba.excel.exception.ExcelDataConvertException;
import com.alibaba.excel.exception.ExcelGenerateException; 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.FileUtils;
import com.alibaba.excel.util.WorkBookUtil; import com.alibaba.excel.write.executor.ExcelWriteAddExecutor;
import com.alibaba.excel.write.handler.CellWriteHandler; import com.alibaba.excel.write.executor.ExcelWriteFillExecutor;
import com.alibaba.excel.write.handler.RowWriteHandler;
import com.alibaba.excel.write.handler.WriteHandler;
import com.alibaba.excel.write.metadata.WriteSheet; import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.WriteTable; import com.alibaba.excel.write.metadata.WriteTable;
import com.alibaba.excel.write.metadata.WriteWorkbook; import com.alibaba.excel.write.metadata.WriteWorkbook;
import com.alibaba.excel.write.metadata.fill.AnalysisCell; import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.excel.write.metadata.holder.WriteHolder;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import net.sf.cglib.beans.BeanMap;
/** /**
* @author jipengfei * @author jipengfei
*/ */
public class ExcelBuilderImpl implements ExcelBuilder { public class ExcelBuilderImpl implements ExcelBuilder {
private static final String FILL_PREFIX = "${";
private static final String FILL_SUFFIX = "}";
private static final Pattern FILL_PATTERN = Pattern.compile("\\$\\{[^}]+}");
private WriteContext context; private WriteContext context;
private ExcelWriteFillExecutor excelWriteFillExecutor;
private ExcelWriteAddExecutor excelWriteAddExecutor;
public ExcelBuilderImpl(WriteWorkbook writeWorkbook) { public ExcelBuilderImpl(WriteWorkbook writeWorkbook) {
try { try {
@ -73,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 @Override
public void addContent(List data, WriteSheet writeSheet) { public void addContent(List data, WriteSheet writeSheet) {
addContent(data, writeSheet, null); addContent(data, writeSheet, null);
@ -98,9 +47,15 @@ public class ExcelBuilderImpl implements ExcelBuilder {
@Override @Override
public void addContent(List data, WriteSheet writeSheet, WriteTable writeTable) { public void addContent(List data, WriteSheet writeSheet, WriteTable writeTable) {
try { try {
context.currentSheet(writeSheet); if (data == null) {
return;
}
context.currentSheet(writeSheet, WriteTypeEnum.ADD);
context.currentTable(writeTable); context.currentTable(writeTable);
doAddContent(data); if (excelWriteAddExecutor == null) {
excelWriteAddExecutor = new ExcelWriteAddExecutor(context);
}
excelWriteAddExecutor.add(data);
} catch (RuntimeException e) { } catch (RuntimeException e) {
finish(); finish();
throw e; throw e;
@ -111,14 +66,19 @@ public class ExcelBuilderImpl implements ExcelBuilder {
} }
@Override @Override
public void fill(Object data, WriteSheet writeSheet) { public void fill(Object data, FillConfig fillConfig, WriteSheet writeSheet) {
try { try {
if (context.writeWorkbookHolder().getTemplateFile() == null if (data == null) {
&& context.writeWorkbookHolder().getTemplateInputStream() == null) { return;
}
if (context.writeWorkbookHolder().getTempTemplateInputStream() == null) {
throw new ExcelGenerateException("Calling the 'fill' method must use a template."); throw new ExcelGenerateException("Calling the 'fill' method must use a template.");
} }
context.currentSheet(writeSheet); context.currentSheet(writeSheet, WriteTypeEnum.FILL);
doFill(data); if (excelWriteFillExecutor == null) {
excelWriteFillExecutor = new ExcelWriteFillExecutor(context);
}
excelWriteFillExecutor.fill(data, fillConfig);
} catch (RuntimeException e) { } catch (RuntimeException e) {
finish(); finish();
throw e; throw e;
@ -128,73 +88,6 @@ public class ExcelBuilderImpl implements ExcelBuilder {
} }
} }
private void doFill(Object data) {
WriteSheetHolder writeSheetHolder = context.writeSheetHolder();
XSSFSheet sheet = writeSheetHolder.getXssfSheet();
Map<Integer, Integer> templateLastRowMap = context.writeWorkbookHolder().getTemplateLastRowMap();
if (sheet == null) {
throw new ExcelGenerateException(
"The corresponding table cannot be found,sheetNo:" + writeSheetHolder.getSheetNo());
}
List<AnalysisCell> analysisCellList = new ArrayList<AnalysisCell>();
for (int i = 0; i <= sheet.getLastRowNum(); i++) {
Row row = sheet.getRow(i);
for (int j = 0; j < row.getLastCellNum(); j++) {
Cell cell = row.getCell(j);
String value = cell.getStringCellValue();
if (FILL_PATTERN.matcher(value).matches()) {
AnalysisCell analysisCell = new AnalysisCell();
analysisCell.setRowIndex(i);
analysisCell.setColumnIndex(j);
List<String> variableList = new ArrayList<String>();
analysisCell.setVariableList(variableList);
boolean matches = true;
int index = 0;
while (matches) {
Matcher matcher = FILL_PATTERN.matcher(value);
String variable = value.substring(matcher.regionStart() + 2, matcher.regionEnd() - 1);
variableList.add(variable);
value = matcher.replaceFirst("{" + index++ + "}");
matches = FILL_PATTERN.matcher(value).matches();
analysisCellList.add(analysisCell);
}
}
}
}
if (data instanceof Collection) {
} else if (data instanceof Map) {
} else {
}
BeanMap beanMap = BeanMap.create(data);
for (AnalysisCell analysisCell : analysisCellList) {
Cell cell = sheet.getRow(analysisCell.getRowIndex()).getCell(analysisCell.getColumnIndex());
if (analysisCell.getVariableList().size() == 1) {
Object value = beanMap.get(analysisCell.getVariableList().get(0));
if (value == null) {
continue;
}
converterAndSet(writeSheetHolder, value.getClass(), cell, value, null);
} else {
List<String> fileDataStringList = new ArrayList<String>();
for (String variable : analysisCell.getVariableList()) {
Object value = beanMap.get(variable);
CellData cellData = convert(writeSheetHolder, String.class, cell, value, null);
String fillDataString = cellData.getStringValue();
if (fillDataString == null) {
fillDataString = "";
}
fileDataStringList.add(fillDataString);
}
cell.setCellValue(String.format(analysisCell.getPrepareData(), fileDataStringList));
}
}
}
@Override @Override
public void finish() { public void finish() {
if (context != null) { if (context != null) {
@ -212,286 +105,4 @@ public class ExcelBuilderImpl implements ExcelBuilder {
public WriteContext writeContext() { public WriteContext writeContext() {
return context; 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()) {
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);
}
}
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();
}
}
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);
}
}
}
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()) {
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 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());
}
}
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);
}
private CellData convert(WriteHolder currentWriteHolder, Class clazz, Cell cell, Object value,
ExcelContentProperty excelContentProperty) {
// 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;
}
} }

7
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.exception.ExcelGenerateException;
import com.alibaba.excel.write.handler.WriteHandler; import com.alibaba.excel.write.handler.WriteHandler;
import com.alibaba.excel.write.metadata.WriteSheet; import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
/** /**
* Build sheet * Build sheet
@ -136,10 +137,14 @@ public class ExcelWriterSheetBuilder {
} }
public void doFill(Object data) { public void doFill(Object data) {
doFill(data, null);
}
public void doFill(Object data, FillConfig fillConfig) {
if (excelWriter == null) { if (excelWriter == null) {
throw new ExcelGenerateException("Must use 'EasyExcelFactory.write().sheet()' to call this method"); throw new ExcelGenerateException("Must use 'EasyExcelFactory.write().sheet()' to call this method");
} }
excelWriter.fill(data, build()); excelWriter.fill(data, fillConfig, build());
excelWriter.finish(); excelWriter.finish();
} }

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

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 { public interface RowWriteHandler extends WriteHandler {
/** /**
* called before create the row * Called before create the row
* *
* @param writeSheetHolder * @param writeSheetHolder
* @param writeTableHolder * @param writeTableHolder
* Nullable * Nullable.It is null without using table writes.
* @param rowIndex * @param rowIndex
* @param relativeRowIndex * @param relativeRowIndex
* Nullable.It is null in the case of fill data.
* @param isHead * @param isHead
* Nullable.It is null in the case of fill data.
*/ */
void beforeRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, int rowIndex, void beforeRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Integer rowIndex,
int relativeRowIndex, boolean isHead); Integer relativeRowIndex, Boolean isHead);
/** /**
* called after the row is created * Called after the row is created
* *
* @param writeSheetHolder * @param writeSheetHolder
* @param writeTableHolder * @param writeTableHolder
* Nullable * Nullable.It is null without using table writes.
* @param row * @param row
* @param relativeRowIndex * @param relativeRowIndex
* Nullable.It is null in the case of fill data.
* @param isHead * @param isHead
* Nullable.It is null in the case of fill data.
*/ */
void afterRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, 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 { public interface SheetWriteHandler extends WriteHandler {
/** /**
* called before create the sheet * Called before create the sheet
* *
* @param writeWorkbookHolder * @param writeWorkbookHolder
* @param writeSheetHolder * @param writeSheetHolder
@ -19,7 +19,7 @@ public interface SheetWriteHandler extends WriteHandler {
void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder); void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder);
/** /**
* called after the sheet is created * Called after the sheet is created
* *
* @param writeWorkbookHolder * @param writeWorkbookHolder
* @param writeSheetHolder * @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 { public interface WorkbookWriteHandler extends WriteHandler {
/** /**
* called before create the sheet * Called before create the workbook
*/ */
void beforeWorkbookCreate(); void beforeWorkbookCreate();
/** /**
* called after the sheet is created * Called after the workbook is created
* *
* @param writeWorkbookHolder * @param writeWorkbookHolder
*/ */
void afterWorkbookCreate(WriteWorkbookHolder 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; package com.alibaba.excel.write.merge;
import java.util.List;
import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet; 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 { public abstract class AbstractMergeStrategy implements CellWriteHandler {
@Override @Override
public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,
Head head, int relativeRowIndex, boolean isHead) { Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {
} }
@Override @Override
public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell,
Cell cell, Head head, int relativeRowIndex, boolean isHead) { 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) { if (isHead) {
return; return;
} }

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

@ -2,6 +2,8 @@ package com.alibaba.excel.write.metadata.fill;
import java.util.List; import java.util.List;
import com.alibaba.excel.enums.WriteTemplateAnalysisCellTypeEnum;
/** /**
* Read the cells of the template while populating the data. * Read the cells of the template while populating the data.
* *
@ -11,7 +13,9 @@ public class AnalysisCell {
private int columnIndex; private int columnIndex;
private int rowIndex; private int rowIndex;
private List<String> variableList; private List<String> variableList;
private String prepareData; private List<String> prepareDataList;
private Boolean onlyOneVariable;
private WriteTemplateAnalysisCellTypeEnum cellType;
public int getColumnIndex() { public int getColumnIndex() {
return columnIndex; return columnIndex;
@ -37,11 +41,49 @@ public class AnalysisCell {
this.variableList = variableList; this.variableList = variableList;
} }
public String getPrepareData() { public List<String> getPrepareDataList() {
return prepareData; 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;
} }
public void setPrepareData(String prepareData) { @Override
this.prepareData = prepareData; 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;
}
}
}

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

@ -3,12 +3,13 @@ package com.alibaba.excel.write.metadata.holder;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFSheet;
import com.alibaba.excel.enums.HolderEnum; import com.alibaba.excel.enums.HolderEnum;
import com.alibaba.excel.enums.WriteLastRowType; import com.alibaba.excel.enums.WriteLastRowTypeEnum;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.metadata.WriteSheet; import com.alibaba.excel.write.metadata.WriteSheet;
/** /**
@ -22,14 +23,22 @@ public class WriteSheetHolder extends AbstractWriteHolder {
*/ */
private WriteSheet writeSheet; 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; private Sheet sheet;
/** /***
* When reading version 07 with the template, the <code>sheet</code> cannot read template data, so need to use * Current poi Sheet.Be sure to use and this method when reading template data.
* <code>xssfSheet</code> to get it. * <ul>
* <li>03:{@link HSSFSheet}</li>
* <li>07:{@link XSSFSheet}</li>
* </ul>
*/ */
private XSSFSheet xssfSheet; private Sheet cachedSheet;
/*** /***
* sheetNo * sheetNo
*/ */
@ -53,7 +62,7 @@ public class WriteSheetHolder extends AbstractWriteHolder {
* @param writeSheet * @param writeSheet
* @param writeWorkbookHolder * @param writeWorkbookHolder
*/ */
private WriteLastRowType writeLastRowType; private WriteLastRowTypeEnum writeLastRowTypeEnum;
public WriteSheetHolder(WriteSheet writeSheet, WriteWorkbookHolder writeWorkbookHolder) { public WriteSheetHolder(WriteSheet writeSheet, WriteWorkbookHolder writeWorkbookHolder) {
super(writeSheet, writeWorkbookHolder, writeWorkbookHolder.getWriteWorkbook().getConvertAllFiled()); super(writeSheet, writeWorkbookHolder, writeWorkbookHolder.getWriteWorkbook().getConvertAllFiled());
@ -66,10 +75,10 @@ public class WriteSheetHolder extends AbstractWriteHolder {
} }
this.parentWriteWorkbookHolder = writeWorkbookHolder; this.parentWriteWorkbookHolder = writeWorkbookHolder;
this.hasBeenInitializedTable = new HashMap<Integer, WriteTableHolder>(); this.hasBeenInitializedTable = new HashMap<Integer, WriteTableHolder>();
if (writeWorkbookHolder.getTemplateInputStream() == null && writeWorkbookHolder.getTemplateFile() == null) { if (writeWorkbookHolder.getTempTemplateInputStream() != null) {
writeLastRowType = WriteLastRowType.COMMON_EMPTY; writeLastRowTypeEnum = WriteLastRowTypeEnum.TEMPLATE_EMPTY;
} else { } else {
writeLastRowType = WriteLastRowType.TEMPLATE_EMPTY; writeLastRowTypeEnum = WriteLastRowTypeEnum.COMMON_EMPTY;
} }
} }
@ -93,12 +102,12 @@ public class WriteSheetHolder extends AbstractWriteHolder {
return sheetNo; return sheetNo;
} }
public XSSFSheet getXssfSheet() { public Sheet getCachedSheet() {
return xssfSheet; return cachedSheet;
} }
public void setXssfSheet(XSSFSheet xssfSheet) { public void setCachedSheet(Sheet cachedSheet) {
this.xssfSheet = xssfSheet; this.cachedSheet = cachedSheet;
} }
public void setSheetNo(Integer sheetNo) { public void setSheetNo(Integer sheetNo) {
@ -129,12 +138,12 @@ public class WriteSheetHolder extends AbstractWriteHolder {
this.hasBeenInitializedTable = hasBeenInitializedTable; this.hasBeenInitializedTable = hasBeenInitializedTable;
} }
public WriteLastRowType getWriteLastRowType() { public WriteLastRowTypeEnum getWriteLastRowTypeEnum() {
return writeLastRowType; return writeLastRowTypeEnum;
} }
public void setWriteLastRowType(WriteLastRowType writeLastRowType) { public void setWriteLastRowTypeEnum(WriteLastRowTypeEnum writeLastRowTypeEnum) {
this.writeLastRowType = writeLastRowType; this.writeLastRowTypeEnum = writeLastRowTypeEnum;
} }
/** /**
@ -145,25 +154,16 @@ public class WriteSheetHolder extends AbstractWriteHolder {
public int getNewRowIndexAndStartDoWrite() { public int getNewRowIndexAndStartDoWrite() {
// 'getLastRowNum' doesn't matter if it has one or zero,is's zero // 'getLastRowNum' doesn't matter if it has one or zero,is's zero
int newRowIndex = 0; int newRowIndex = 0;
switch (writeLastRowType) { switch (writeLastRowTypeEnum) {
case TEMPLATE_EMPTY: 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: case HAS_DATA:
newRowIndex = sheet.getLastRowNum(); newRowIndex = Math.max(sheet.getLastRowNum(), cachedSheet.getLastRowNum());
newRowIndex++; newRowIndex++;
break; break;
default: default:
break; break;
} }
writeLastRowType = WriteLastRowType.HAS_DATA; writeLastRowTypeEnum = WriteLastRowTypeEnum.HAS_DATA;
return newRowIndex; return newRowIndex;
} }

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

@ -1,20 +1,28 @@
package com.alibaba.excel.write.metadata.holder; package com.alibaba.excel.write.metadata.holder;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import com.alibaba.excel.enums.HolderEnum; import com.alibaba.excel.enums.HolderEnum;
import com.alibaba.excel.exception.ExcelGenerateException; import com.alibaba.excel.exception.ExcelGenerateException;
import com.alibaba.excel.support.ExcelTypeEnum; 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; import com.alibaba.excel.write.metadata.WriteWorkbook;
/** /**
@ -24,14 +32,22 @@ import com.alibaba.excel.write.metadata.WriteWorkbook;
*/ */
public class WriteWorkbookHolder extends AbstractWriteHolder { 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; private Workbook workbook;
/** /***
* When reading version 07 with the template, the <code>workbook</code> cannot get the specific line number, so it * Current poi Workbook.Be sure to use and this method when reading template data.
* needs to get the specific line number. * <ul>
* <li>03:{@link HSSFWorkbook}</li>
* <li>07:{@link XSSFWorkbook}</li>
* </ul>
*/ */
private XSSFWorkbook xssfWorkbook; private Workbook cachedWorkbook;
/** /**
* current param * current param
*/ */
@ -80,11 +96,6 @@ public class WriteWorkbookHolder extends AbstractWriteHolder {
* prevent duplicate creation of sheet objects * prevent duplicate creation of sheet objects
*/ */
private Map<Integer, WriteSheetHolder> hasBeenInitializedSheet; 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
*/
private Map<Integer, Integer> templateLastRowMap;
public WriteWorkbookHolder(WriteWorkbook writeWorkbook) { public WriteWorkbookHolder(WriteWorkbook writeWorkbook) {
super(writeWorkbook, null, writeWorkbook.getConvertAllFiled()); super(writeWorkbook, null, writeWorkbook.getConvertAllFiled());
@ -99,19 +110,16 @@ public class WriteWorkbookHolder extends AbstractWriteHolder {
} else { } else {
this.outputStream = writeWorkbook.getOutputStream(); 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) { if (writeWorkbook.getAutoCloseStream() == null) {
this.autoCloseStream = Boolean.TRUE; this.autoCloseStream = Boolean.TRUE;
} else { } else {
this.autoCloseStream = writeWorkbook.getAutoCloseStream(); this.autoCloseStream = writeWorkbook.getAutoCloseStream();
} }
try {
copyTemplate();
} catch (IOException e) {
throw new ExcelGenerateException("Copy template failure.", e);
}
if (writeWorkbook.getExcelType() == null) { if (writeWorkbook.getExcelType() == null) {
if (file != null && file.getName().endsWith(ExcelTypeEnum.XLS.getValue())) { if (file != null && file.getName().endsWith(ExcelTypeEnum.XLS.getValue())) {
this.excelType = ExcelTypeEnum.XLS; this.excelType = ExcelTypeEnum.XLS;
@ -127,7 +135,25 @@ public class WriteWorkbookHolder extends AbstractWriteHolder {
this.mandatoryUseInputStream = writeWorkbook.getMandatoryUseInputStream(); this.mandatoryUseInputStream = writeWorkbook.getMandatoryUseInputStream();
} }
this.hasBeenInitializedSheet = new HashMap<Integer, WriteSheetHolder>(); this.hasBeenInitializedSheet = new HashMap<Integer, WriteSheetHolder>();
this.templateLastRowMap = new HashMap<Integer, Integer>(8); }
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() { public Workbook getWorkbook() {
@ -138,12 +164,12 @@ public class WriteWorkbookHolder extends AbstractWriteHolder {
this.workbook = workbook; this.workbook = workbook;
} }
public XSSFWorkbook getXssfWorkbook() { public Workbook getCachedWorkbook() {
return xssfWorkbook; return cachedWorkbook;
} }
public void setXssfWorkbook(XSSFWorkbook xssfWorkbook) { public void setCachedWorkbook(Workbook cachedWorkbook) {
this.xssfWorkbook = xssfWorkbook; this.cachedWorkbook = cachedWorkbook;
} }
public Map<Integer, WriteSheetHolder> getHasBeenInitializedSheet() { public Map<Integer, WriteSheetHolder> getHasBeenInitializedSheet() {
@ -226,14 +252,6 @@ public class WriteWorkbookHolder extends AbstractWriteHolder {
this.mandatoryUseInputStream = mandatoryUseInputStream; this.mandatoryUseInputStream = mandatoryUseInputStream;
} }
public Map<Integer, Integer> getTemplateLastRowMap() {
return templateLastRowMap;
}
public void setTemplateLastRowMap(Map<Integer, Integer> templateLastRowMap) {
this.templateLastRowMap = templateLastRowMap;
}
@Override @Override
public HolderEnum holderType() { public HolderEnum holderType() {
return HolderEnum.WORKBOOK; return HolderEnum.WORKBOOK;

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

@ -1,5 +1,7 @@
package com.alibaba.excel.write.style; package com.alibaba.excel.write.style;
import java.util.List;
import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.Workbook;
@ -27,28 +29,23 @@ public abstract class AbstractCellStyleStrategy implements CellWriteHandler, She
} }
@Override @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 @Override
public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell,
initCellStyle(writeWorkbookHolder.getWorkbook()); Head head, Integer relativeRowIndex, Boolean isHead) {
hasInitialized = true;
}
@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 @Override
public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
Cell cell, Head head, int relativeRowIndex, boolean isHead) { List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
if (isHead == null || head == null) {
return;
}
if (isHead) { if (isHead) {
setHeadCellStyle(cell, head, relativeRowIndex); setHeadCellStyle(cell, head, relativeRowIndex);
} else { } 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 * Initialization cell style
* *
@ -70,7 +78,7 @@ public abstract class AbstractCellStyleStrategy implements CellWriteHandler, She
* @param head * @param head
* @param relativeRowIndex * @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 * Sets the cell style of content
@ -79,6 +87,6 @@ public abstract class AbstractCellStyleStrategy implements CellWriteHandler, She
* @param head * @param head
* @param relativeRowIndex * @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 @Override
protected void setHeadCellStyle(Cell cell, Head head, int relativeRowIndex) { protected void setHeadCellStyle(Cell cell, Head head, Integer relativeRowIndex) {
int columnIndex = head.getColumnIndex(); int columnIndex = head.getColumnIndex();
if (headCellStyleCache.containsKey(columnIndex)) { if (headCellStyleCache.containsKey(columnIndex)) {
CellStyle cellStyle = headCellStyleCache.get(columnIndex); CellStyle cellStyle = headCellStyleCache.get(columnIndex);
@ -49,7 +49,7 @@ public abstract class AbstractVerticalCellStyleStrategy extends AbstractCellStyl
} }
@Override @Override
protected void setContentCellStyle(Cell cell, Head head, int relativeRowIndex) { protected void setContentCellStyle(Cell cell, Head head, Integer relativeRowIndex) {
int columnIndex = head.getColumnIndex(); int columnIndex = head.getColumnIndex();
if (contentCellStyleCache.containsKey(columnIndex)) { if (contentCellStyleCache.containsKey(columnIndex)) {
CellStyle cellStyle = contentCellStyleCache.get(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 @Override
protected void setHeadCellStyle(Cell cell, Head head, int relativeRowIndex) { protected void setHeadCellStyle(Cell cell, Head head, Integer relativeRowIndex) {
if (headCellStyle == null) { if (headCellStyle == null) {
return; return;
} }
@ -59,7 +59,7 @@ public class HorizontalCellStyleStrategy extends AbstractCellStyleStrategy {
} }
@Override @Override
protected void setContentCellStyle(Cell cell, Head head, int relativeRowIndex) { protected void setContentCellStyle(Cell cell, Head head, Integer relativeRowIndex) {
if (contentCellStyleList == null || contentCellStyleList.isEmpty()) { if (contentCellStyleList == null || contentCellStyleList.isEmpty()) {
return; return;
} }

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

@ -1,5 +1,7 @@
package com.alibaba.excel.write.style.column; package com.alibaba.excel.write.style.column;
import java.util.List;
import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Row;
@ -24,27 +26,28 @@ public abstract class AbstractColumnWidthStyleStrategy implements CellWriteHandl
@Override @Override
public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, 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 @Override
public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
Cell cell, Head head, int relativeRowIndex, boolean isHead) { setColumnWidth(writeSheetHolder, cellDataList, cell, head, relativeRowIndex, isHead);
setColumnWidth(writeSheetHolder, cellData, cell, head, relativeRowIndex, isHead);
} }
/** /**
* Sets the column width when head create * Sets the column width when head create
* *
* @param writeSheetHolder * @param writeSheetHolder
* @param cellData * @param cellDataList
* @param cell * @param cell
* @param head * @param head
* @param relativeRowIndex * @param relativeRowIndex
* @param isHead * @param isHead
*/ */
protected abstract void setColumnWidth(WriteSheetHolder writeSheetHolder, CellData cellData, Cell cell, Head head, protected abstract void setColumnWidth(WriteSheetHolder writeSheetHolder, List<CellData> cellDataList, Cell cell, Head head,
int relativeRowIndex, boolean isHead); 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; package com.alibaba.excel.write.style.column;
import java.util.List;
import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Cell;
import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.CellData;
@ -12,10 +14,12 @@ import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
* @author Jiaju Zhuang * @author Jiaju Zhuang
*/ */
public abstract class AbstractHeadColumnWidthStyleStrategy extends AbstractColumnWidthStyleStrategy { public abstract class AbstractHeadColumnWidthStyleStrategy extends AbstractColumnWidthStyleStrategy {
@Override @Override
protected void setColumnWidth(WriteSheetHolder writeSheetHolder, CellData cellData, Cell cell, Head head, protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<CellData> cellDataList, Cell cell, Head head,
int relativeRowIndex, boolean isHead) { Integer relativeRowIndex, Boolean isHead) {
if (!isHead && relativeRowIndex != 0) { boolean needSetWidth = relativeRowIndex != null && (isHead || relativeRowIndex == 0);
if (!needSetWidth) {
return; return;
} }
Integer width = columnWidth(head); Integer width = columnWidth(head);
@ -36,4 +40,5 @@ public abstract class AbstractHeadColumnWidthStyleStrategy extends AbstractColum
* @return * @return
*/ */
protected abstract Integer columnWidth(Head head); 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; package com.alibaba.excel.write.style.column;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Cell;
import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head; import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; 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); private static final Map<Integer, Map<Integer, Integer>> CACHE = new HashMap<Integer, Map<Integer, Integer>>(8);
@Override @Override
protected void setColumnWidth(WriteSheetHolder writeSheetHolder, CellData cellData, Cell cell, Head head, protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<CellData> cellDataList, Cell cell, Head head,
int relativeRowIndex, boolean isHead) { Integer relativeRowIndex, Boolean isHead) {
if (!isHead && cellData == null) { boolean needSetWidth = isHead || !CollectionUtils.isEmpty(cellDataList);
if (!needSetWidth) {
return; return;
} }
Map<Integer, Integer> maxColumnWidthMap = CACHE.get(writeSheetHolder.getSheetNo()); Map<Integer, Integer> maxColumnWidthMap = CACHE.get(writeSheetHolder.getSheetNo());
@ -34,24 +37,25 @@ public class LongestMatchColumnWidthStyleStrategy extends AbstractColumnWidthSty
maxColumnWidthMap = new HashMap<Integer, Integer>(16); maxColumnWidthMap = new HashMap<Integer, Integer>(16);
CACHE.put(writeSheetHolder.getSheetNo(), maxColumnWidthMap); CACHE.put(writeSheetHolder.getSheetNo(), maxColumnWidthMap);
} }
Integer columnWidth = dataLength(cellData, cell, isHead); Integer columnWidth = dataLength(cellDataList, cell, isHead);
if (columnWidth < 0) { if (columnWidth < 0) {
return; return;
} }
if (columnWidth > MAX_COLUMN_WIDTH) { if (columnWidth > MAX_COLUMN_WIDTH) {
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) { if (maxColumnWidth == null || columnWidth > maxColumnWidth) {
maxColumnWidthMap.put(head.getColumnIndex(), columnWidth); maxColumnWidthMap.put(cell.getColumnIndex(), columnWidth);
writeSheetHolder.getSheet().setColumnWidth(head.getColumnIndex(), columnWidth * 256); 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) { if (isHead) {
return cell.getStringCellValue().getBytes().length; return cell.getStringCellValue().getBytes().length;
} }
CellData cellData = cellDataList.get(0);
switch (cellData.getType()) { switch (cellData.getType()) {
case STRING: case STRING:
return cellData.getStringValue().getBytes().length; 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 @Override
public void beforeRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, int rowIndex, public void beforeRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Integer rowIndex,
int relativeRowIndex, boolean isHead) { Integer relativeRowIndex, Boolean isHead) {
} }
@Override @Override
public void afterRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, 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) { if (isHead) {
setHeadColumnHeight(row, relativeRowIndex); setHeadColumnHeight(row, relativeRowIndex);
} else { } else {

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

@ -1,6 +1,8 @@
package com.alibaba.easyexcel.test.core.fill; package com.alibaba.easyexcel.test.core.fill;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.NumberFormat; import com.alibaba.excel.annotation.format.NumberFormat;
import com.alibaba.excel.converters.doubleconverter.DoubleStringConverter;
import lombok.Data; import lombok.Data;
@ -10,6 +12,7 @@ import lombok.Data;
@Data @Data
public class FillData { public class FillData {
private String name; private String name;
@NumberFormat("0#") @NumberFormat("#")
@ExcelProperty(converter = DoubleStringConverter.class)
private double number; private double number;
} }

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

@ -2,7 +2,9 @@ package com.alibaba.easyexcel.test.core.fill;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import org.apache.poi.ss.usermodel.BorderStyle; import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.FillPatternType; import org.apache.poi.ss.usermodel.FillPatternType;
@ -10,6 +12,7 @@ import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment; import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors; import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.VerticalAlignment; import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.junit.Assert;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.FixMethodOrder; import org.junit.FixMethodOrder;
import org.junit.Test; import org.junit.Test;
@ -19,9 +22,13 @@ import com.alibaba.easyexcel.test.core.style.StyleData;
import com.alibaba.easyexcel.test.core.style.StyleDataListener; import com.alibaba.easyexcel.test.core.style.StyleDataListener;
import com.alibaba.easyexcel.test.util.TestFileUtil; import com.alibaba.easyexcel.test.util.TestFileUtil;
import com.alibaba.excel.EasyExcel; 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.metadata.Head;
import com.alibaba.excel.write.merge.LoopMergeStrategy; import com.alibaba.excel.write.merge.LoopMergeStrategy;
import com.alibaba.excel.write.merge.OnceAbsoluteMergeStrategy; 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.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont; import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.AbstractVerticalCellStyleStrategy; import com.alibaba.excel.write.style.AbstractVerticalCellStyleStrategy;
@ -39,52 +46,112 @@ public class FillDataTest {
private static File file07; private static File file07;
private static File file03; private static File file03;
private static File simpleTemplate07; 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 @BeforeClass
public static void init() { public static void init() {
file07 = TestFileUtil.createNewFile("fill07.xlsx"); file07 = TestFileUtil.createNewFile("fill07.xlsx");
file03 = TestFileUtil.createNewFile("fill03.xls"); file03 = TestFileUtil.createNewFile("fill03.xls");
simpleTemplate07 = TestFileUtil.readFile("fill" + File.separator + "simple.xlsx"); 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 @Test
public void t01Fill07() { public void t01Fill07() {
fill(file07); fill(file07, simpleTemplate07);
} }
@Test @Test
public void t02Fill03() { public void t02Fill03() {
fill(file03); fill(file03, simpleTemplate03);
} }
private void fill(File file) { @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 fillData = new FillData();
fillData.setName("张三"); fillData.setName("张三");
fillData.setNumber(5.2); fillData.setNumber(5.2);
EasyExcel.write(file).withTemplate(simpleTemplate07).sheet().doFill(fillData); EasyExcel.write(file, FillData.class).withTemplate(template).sheet().doFill(fillData);
} }
private List<StyleData> data() { private List<FillData> data() {
List<StyleData> list = new ArrayList<StyleData>(); List<FillData> list = new ArrayList<FillData>();
StyleData data = new StyleData();
data.setString("字符串0");
data.setString1("字符串01");
StyleData data1 = new StyleData();
data1.setString("字符串1");
data1.setString1("字符串11");
list.add(data);
list.add(data1);
return list;
}
private List<StyleData> data10() {
List<StyleData> list = new ArrayList<StyleData>();
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
StyleData data = new StyleData(); FillData fillData = new FillData();
data.setString("字符串0"); list.add(fillData);
data.setString1("字符串01"); fillData.setName("张三");
list.add(data); fillData.setNumber(5.2);
} }
return list; 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; package com.alibaba.easyexcel.test.core.large;
import java.io.File; import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.alibaba.easyexcel.test.demo.write.DemoData;
import com.alibaba.easyexcel.test.util.TestFileUtil; import com.alibaba.easyexcel.test.util.TestFileUtil;
import com.alibaba.excel.EasyExcel; 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 { public class LargeDataTest {
private static final Logger LOGGER = LoggerFactory.getLogger(LargeDataTest.class); 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 @Test
public void read() { public void t01Read() {
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
EasyExcel.read(TestFileUtil.getPath() + "large" + File.separator + "large07.xlsx", LargeData.class, EasyExcel.read(TestFileUtil.getPath() + "large" + File.separator + "large07.xlsx", LargeData.class,
new LargeDataListener()).headRowNumber(2).sheet().doRead(); new LargeDataListener()).headRowNumber(2).sheet().doRead();
LOGGER.info("Large data total time spent:{}", System.currentTimeMillis() - start); 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;
}
} }

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

14
src/test/java/com/alibaba/easyexcel/test/demo/write/CustomCellWriteHandler.java

@ -1,5 +1,7 @@
package com.alibaba.easyexcel.test.demo.write; package com.alibaba.easyexcel.test.demo.write;
import java.util.List;
import org.apache.poi.common.usermodel.HyperlinkType; import org.apache.poi.common.usermodel.HyperlinkType;
import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CreationHelper; import org.apache.poi.ss.usermodel.CreationHelper;
@ -25,13 +27,19 @@ public class CustomCellWriteHandler implements CellWriteHandler {
@Override @Override
public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, 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 @Override
public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
Cell cell, Head head, int relativeRowIndex, boolean isHead) { List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
// 这里可以对cell进行任何操作 // 这里可以对cell进行任何操作
LOGGER.info("第{}行,第{}列写入完成。", cell.getRowIndex(), cell.getColumnIndex()); LOGGER.info("第{}行,第{}列写入完成。", cell.getRowIndex(), cell.getColumnIndex());
if (isHead && cell.getColumnIndex() == 0) { if (isHead && cell.getColumnIndex() == 0) {

2
src/test/java/com/alibaba/easyexcel/test/temp/large/LargeData.java

@ -1,11 +1,13 @@
package com.alibaba.easyexcel.test.temp.large; package com.alibaba.easyexcel.test.temp.large;
import lombok.Builder;
import lombok.Data; import lombok.Data;
/** /**
* @author Jiaju Zhuang * @author Jiaju Zhuang
*/ */
@Data @Data
@Builder
public class LargeData { public class LargeData {
private String str1; private String str1;

87
src/test/java/com/alibaba/easyexcel/test/temp/poi/PoiTest.java

@ -4,7 +4,10 @@ import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellCopyPolicy;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.streaming.SXSSFRow; import org.apache.poi.xssf.streaming.SXSSFRow;
@ -72,29 +75,101 @@ public class PoiTest {
xssfWorkbook.close(); xssfWorkbook.close();
} }
@Test
public void lastRowNum255() throws IOException, InvalidFormatException {
String file = TestFileUtil.getPath() + "fill" + File.separator + "complex.xlsx";
XSSFWorkbook xssfWorkbook = new XSSFWorkbook(new File(file));
SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook(xssfWorkbook);
Sheet xssfSheet = xssfWorkbook.getSheetAt(0);
xssfSheet.shiftRows(2, 4, 10);
FileOutputStream fileout = new FileOutputStream("d://test/r2" + System.currentTimeMillis() + ".xlsx");
sxssfWorkbook.write(fileout);
sxssfWorkbook.dispose();
sxssfWorkbook.close();
xssfWorkbook.close();
}
@Test
public void cp() throws IOException, InvalidFormatException {
String file = "d://test/tt.xlsx";
XSSFWorkbook xssfWorkbook = new XSSFWorkbook(new File(file));
XSSFSheet xssfSheet = xssfWorkbook.getSheetAt(0);
XSSFRow row = xssfSheet.getRow(2);
xssfSheet.removeRow(row);
// Row r2= xssfSheet.createRow(2);
// r2.createCell(1);
SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook(xssfWorkbook);
SXSSFSheet sxssfSheet = sxssfWorkbook.getSheetAt(0);
sxssfSheet.createRow(2);
FileOutputStream fileout = new FileOutputStream("d://test/r2" + System.currentTimeMillis() + ".xlsx");
sxssfWorkbook.write(fileout);
sxssfWorkbook.dispose();
sxssfWorkbook.close();
xssfWorkbook.close();
}
@Test
public void lastRowNum233443() throws IOException, InvalidFormatException {
String file = "d://test/tt.xlsx";
XSSFWorkbook xssfWorkbook = new XSSFWorkbook(new File(file));
SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook(xssfWorkbook);
XSSFSheet xssfSheet = xssfWorkbook.getSheetAt(0);
XSSFRow row = xssfSheet.getRow(2);
xssfSheet.removeRow(row);
new CellCopyPolicy().createBuilder().build();
FileOutputStream fileout = new FileOutputStream("d://test/r2" + System.currentTimeMillis() + ".xlsx");
sxssfWorkbook.write(fileout);
sxssfWorkbook.dispose();
sxssfWorkbook.close();
xssfWorkbook.close();
}
@Test
public void lastRowNum2333() throws IOException, InvalidFormatException {
String file = TestFileUtil.getPath() + "fill" + File.separator + "simple.xlsx";
XSSFWorkbook xssfWorkbook = new XSSFWorkbook(new File(file));
SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook(xssfWorkbook);
Sheet xssfSheet = xssfWorkbook.getSheetAt(0);
Cell cell = xssfSheet.getRow(0).createCell(9);
cell.setCellValue("testssdf是士大夫否t");
FileOutputStream fileout = new FileOutputStream("d://test/r2" + System.currentTimeMillis() + ".xlsx");
sxssfWorkbook.write(fileout);
sxssfWorkbook.dispose();
sxssfWorkbook.close();
xssfWorkbook.close();
}
@Test @Test
public void testread() throws IOException { public void testread() throws IOException {
String file = TestFileUtil.getPath() + "fill" + File.separator + "simple.xlsx"; String file = TestFileUtil.getPath() + "fill" + File.separator + "simple.xlsx";
SXSSFWorkbook xssfWorkbook = new SXSSFWorkbook(new XSSFWorkbook(file)); SXSSFWorkbook xssfWorkbook = new SXSSFWorkbook(new XSSFWorkbook(file));
Sheet xssfSheet = xssfWorkbook.getXSSFWorkbook().getSheetAt(0); Sheet xssfSheet = xssfWorkbook.getXSSFWorkbook().getSheetAt(0);
// //
// Cell cell = xssfSheet.getRow(0).createCell(9); // Cell cell = xssfSheet.getRow(0).createCell(9);
String file1 = TestFileUtil.getPath() + "fill" + File.separator + "simple.xlsx"; String file1 = TestFileUtil.getPath() + "fill" + File.separator + "simple.xlsx";
SXSSFWorkbook xssfWorkbook1 = new SXSSFWorkbook(new XSSFWorkbook(file1)); SXSSFWorkbook xssfWorkbook1 = new SXSSFWorkbook(new XSSFWorkbook(file1));
Sheet xssfSheet1 = xssfWorkbook1.getXSSFWorkbook().getSheetAt(0); Sheet xssfSheet1 = xssfWorkbook1.getXSSFWorkbook().getSheetAt(0);
// Cell cell1 = xssfSheet1.getRow(0).createCell(9); // Cell cell1 = xssfSheet1.getRow(0).createCell(9);
xssfWorkbook.close(); xssfWorkbook.close();
xssfWorkbook1.close(); xssfWorkbook1.close();
} }
@Test @Test
public void testreadRead() throws IOException { public void testreadRead() throws IOException {
String file = TestFileUtil.getPath() + "fill" + File.separator + "simple.xlsx"; String file = TestFileUtil.getPath() + "fill" + File.separator + "simple.xlsx";

26
src/test/java/com/alibaba/easyexcel/test/temp/poi/PoiWriteTest.java

@ -5,6 +5,7 @@ import java.io.IOException;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType; import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.regex.Pattern;
import org.apache.poi.ss.formula.functions.T; import org.apache.poi.ss.formula.functions.T;
import org.apache.poi.xssf.streaming.SXSSFCell; import org.apache.poi.xssf.streaming.SXSSFCell;
@ -44,6 +45,31 @@ public class PoiWriteTest {
sxxsFWorkbook.write(fileOutputStream); sxxsFWorkbook.write(fileOutputStream);
} }
private static final Pattern FILL_PATTERN = Pattern.compile("^.*?\\$\\{[^}]+}.*?$");
@Test
public void part() throws IOException {
LOGGER.info("test:{}", FILL_PATTERN.matcher("${name今年${number}岁了").matches());
LOGGER.info("test:{}", FILL_PATTERN.matcher("${name}今年${number}岁了").matches());
LOGGER.info("test:{}", FILL_PATTERN.matcher("${name}").matches());
LOGGER.info("test:{}", FILL_PATTERN.matcher("${number}").matches());
LOGGER.info("test:{}", FILL_PATTERN.matcher("${name}今年").matches());
LOGGER.info("test:{}", FILL_PATTERN.matcher("今年${number}岁了").matches());
LOGGER.info("test:{}", FILL_PATTERN.matcher("今年${number岁了").matches());
LOGGER.info("test:{}", FILL_PATTERN.matcher("${}").matches());
LOGGER.info("test:{}", FILL_PATTERN.matcher("胜多负少").matches());
}
private static final Pattern FILL_PATTERN2 = Pattern.compile("测试");
@Test
public void part2() throws IOException {
LOGGER.info("test:{}", FILL_PATTERN.matcher("我是测试呀").find());
LOGGER.info("test:{}", FILL_PATTERN.matcher("测试u").matches());
LOGGER.info("test:{}", FILL_PATTERN.matcher("我是测试").matches());
}
@Test @Test
public void test() throws Exception { public void test() throws Exception {
Class<TestCell> clazz = TestCell.class; Class<TestCell> clazz = TestCell.class;

2
src/test/java/com/alibaba/easyexcel/test/temp/simple/HgTest.java

@ -27,7 +27,7 @@ public class HgTest {
@Test @Test
public void hh() throws IOException { public void hh() throws IOException {
List<Object> list = List<Object> list =
EasyExcel.read(new FileInputStream("D:\\test\\MRP生产视图(1).xlsx")).headRowNumber(0).sheet().doReadSync(); EasyExcel.read(new FileInputStream("D:\\test\\201909301017rule.xlsx")).headRowNumber(2).sheet().doReadSync();
for (Object data : list) { for (Object data : list) {
LOGGER.info("返回数据:{}", JSON.toJSONString(data)); LOGGER.info("返回数据:{}", JSON.toJSONString(data));
} }

BIN
src/test/resources/demo/fill/complex.xlsx

Binary file not shown.

BIN
src/test/resources/demo/fill/complexFillWithTable.xlsx

Binary file not shown.

BIN
src/test/resources/demo/fill/horizontal.xlsx

Binary file not shown.

BIN
src/test/resources/demo/fill/list.xlsx

Binary file not shown.

BIN
src/test/resources/demo/fill/simple.xlsx

Binary file not shown.

BIN
src/test/resources/fill/complex.xls

Binary file not shown.

BIN
src/test/resources/fill/complex.xlsx

Binary file not shown.

BIN
src/test/resources/fill/horizontal.xls

Binary file not shown.

BIN
src/test/resources/fill/horizontal.xlsx

Binary file not shown.

BIN
src/test/resources/fill/simple.xls

Binary file not shown.

BIN
src/test/resources/fill/simple.xlsx

Binary file not shown.

BIN
src/test/resources/large/fill.xlsx

Binary file not shown.
Loading…
Cancel
Save