未验证 提交 8a6abd94 编写于 作者: 庄家钜's avatar 庄家钜 提交者: GitHub

Merge pull request #724 from alibaba/2.1.0-beta1

2.1.0 beta1
......@@ -4,16 +4,21 @@ easyexcel
[![Maven central](https://maven-badges.herokuapp.com/maven-central/com.alibaba/easyexcel/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.alibaba/easyexcel)
[![License](http://img.shields.io/:license-apache-brightgreen.svg)](http://www.apache.org/licenses/LICENSE-2.0.html)
[QQ群:662022184](//shang.qq.com/wpa/qunwpa?idkey=53d9d821b0833e3c14670f007488a61e300f00ff4f1b81fd950590d90dd80f80)
[QQ群: 662022184](//shang.qq.com/wpa/qunwpa?idkey=53d9d821b0833e3c14670f007488a61e300f00ff4f1b81fd950590d90dd80f80)
[钉钉群: 21960511](https://qr.dingtalk.com/action/joingroup?code=v1,k1,cchz6k12ci9B08NNqhNRFGXocNVHrZtW0kaOtTKg/Rk=&_dt_no_comment=1&origin=11)
[官方网站: https://alibaba-easyexcel.github.io/](https://alibaba-easyexcel.github.io/)
# JAVA解析Excel工具easyexcel
Java解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定程度的解决一些内存溢出的问题,但POI还是有一些缺陷,比如07版Excel解压缩以及解压后存储都是在内存中完成的,内存消耗依然很大。easyexcel重写了poi对07版Excel的解析,能够原本一个3M的excel用POI sax依然需要100M左右内存降低到几M,并且再大的excel不会出现内存溢出,03版依赖POI的sax模式。在上层做了模型转换的封装,让使用者更加简单方便
## 64M内存1分钟内读取75M(46W行25列)的Excel
当然还有急速模式能更快,但是内存占用会在100M多一点
![img](img/readme/large.png)
## 相关文档
* [快速使用](/quickstart.md)
* [快速使用](https://alibaba-easyexcel.github.io/)
* [关于软件](/abouteasyexcel.md)
* [常见问题](/problem.md)
* [更新记事](/update.md)
* [English-README](/easyexcel_en.md)
## 维护者
玉霄、庄家钜、怀宇
......
......@@ -50,4 +50,4 @@ Caused by: java.io.IOException: Could not create temporary directory '/home/admi
### 3、抛弃不重要的数据
Excel解析时候会包含样式,字体,宽度等数据,但这些数据是我们不关心的,如果将这部分数据抛弃可以大大降低内存使用。Excel中数据如下Style占了相当大的空间。
Excel解析时候会包含样式,字体,宽度等数据,但这些数据是我们不关心的,如果将这部分数据抛弃可以大大降低内存使用。Excel中数据如下Style占了相当大的空间。
\ No newline at end of file
......@@ -12,6 +12,7 @@
* `ExcelIgnore` 默认所有字段都会和excel去匹配,加了这个注解会忽略该字段
* `DateTimeFormat` 日期转换,用`String`去接收excel日期格式的数据会调用这个注解。里面的`value`参照`java.text.SimpleDateFormat`
* `NumberFormat` 数字转换,用`String`去接收excel数字格式的数据会调用这个注解。里面的`value`参照`java.text.DecimalFormat`
* `ExcelIgnoreUnannotated` 默认不加`ExcelProperty` 的注解的都会参与读写,加了不会参与
### 参数
#### 通用参数
`ReadWorkbook`,`ReadSheet` 都会有的参数,如果为空,默认使用上级。
......@@ -21,6 +22,7 @@
* `head``clazz`二选一。读取文件头对应的列表,会根据列表匹配数据,建议使用class。
* `clazz``head`二选一。读取文件的头对应的class,也可以使用注解。如果两个都不指定,则会读取全部数据。
* `autoTrim` 字符串、表头等数据自动trim
* `password` 读的时候是否需要使用密码
#### ReadWorkbook(理解成excel对象)参数
* `excelType` 当前excel的类型 默认会自动判断
* `inputStream``file`二选一。读取文件的流,如果接收到的是流就只用,不用流建议使用`file`参数。因为使用了`inputStream` easyexcel会帮忙创建临时文件,最终还是`file`
......@@ -36,6 +38,7 @@
* `ExcelIgnore` 默认所有字段都会写入excel,这个注解会忽略这个字段
* `DateTimeFormat` 日期转换,将`Date`写到excel会调用这个注解。里面的`value`参照`java.text.SimpleDateFormat`
* `NumberFormat` 数字转换,用`Number`写excel会调用这个注解。里面的`value`参照`java.text.DecimalFormat`
* `ExcelIgnoreUnannotated` 默认不加`ExcelProperty` 的注解的都会参与读写,加了不会参与
### 参数
#### 通用参数
`WriteWorkbook`,`WriteSheet` ,`WriteTable`都会有的参数,如果为空,默认使用上级。
......@@ -53,6 +56,8 @@
* `templateInputStream` 模板的文件流
* `templateFile` 模板文件
* `autoCloseStream` 自动关闭流。
* `password` 写的时候是否需要使用密码
* `useDefaultStyle` 写的时候是否是使用默认头
#### WriteSheet(就是excel的一个Sheet)参数
* `sheetNo` 需要写入的编码。默认0
* `sheetName` 需要些的Sheet名称,默认同`sheetNo`
......
......@@ -9,6 +9,7 @@
```java
// 强制使用内存存储,这样大概一个20M的excel使用150M(很多临时对象,所以100M会一直GC)的内存
// 这样效率会比上面的复杂的策略高很多
// 这里再说明下 就是加了个readCache(new MapCache()) 参数而已,其他的参照其他demo写 这里没有写全
EasyExcel.read().readCache(new MapCache());
```
### 对并发要求较高,而且都是经常有超级大文件
......@@ -16,7 +17,10 @@
// 第一个参数的意思是 多少M共享字符串以后 采用文件存储 单位MB 默认5M
// 第二个参数 文件存储时,内存存放多少M缓存数据 默认20M
// 比如 你希望用100M内存(这里说的是解析过程中的永久占用,临时对象不算)来解析excel,前面算过了 大概是 20M+90M 所以设置参数为:20 和 90
// 这里再说明下 就是加了个readCacheSelector(new SimpleReadCacheSelector(5, 20))参数而已,其他的参照其他demo写 这里没有写全
EasyExcel.read().readCacheSelector(new SimpleReadCacheSelector(5, 20));
```
### 关于maxCacheActivateSize 也就是前面第二个参数的详细说明
easyexcel在使用文件存储的时候,会把共享字符串拆分成1000条一批,然后放到文件存储。然后excel来读取共享字符串大概率是按照顺序的,所以默认20M的1000条的数据放在内存,命中后直接返回,没命中去读文件。所以不能设置太小,太小了,很难命中,一直去读取文件,太大了的话会占用过多的内存。
\ No newline at end of file
easyexcel在使用文件存储的时候,会把共享字符串拆分成1000条一批,然后放到文件存储。然后excel来读取共享字符串大概率是按照顺序的,所以默认20M的1000条的数据放在内存,命中后直接返回,没命中去读文件。所以不能设置太小,太小了,很难命中,一直去读取文件,太大了的话会占用过多的内存。
### 如何判断 maxCacheActivateSize是否需要调整
开启debug日志会输出`Already put :4000000` 最后一次输出,大概可以得出值为400W,然后看`Cache misses count:4001`得到值为4K,400W/4K=1000 这代表已经`maxCacheActivateSize` 已经非常合理了。如果小于500 问题就非常大了,500到1000 应该都还行。
......@@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.0.5</version>
<version>2.1.0-beta1</version>
<packaging>jar</packaging>
<name>easyexcel</name>
......
# 常见问题汇总
## 1、系统环境变量缺失或JDK版本不支持
```
java.lang.NullPointerException
at sun.awt.FontConfiguration.getVersion(FontConfiguration.java:1264)
at sun.awt.FontConfiguration.readFontConfigFile(FontConfiguration.java:219)
at sun.awt.FontConfiguration.init(FontConfiguration.java:107)
at sun.awt.X11FontManager.createFontConfiguration(X11FontManager.java:774)
at sun.font.SunFontManager$2.run(SunFontManager.java:431)
at java.security.AccessController.doPrivileged(Native Method)
at sun.font.SunFontManager.<init>(SunFontManager.java:376)
at sun.awt.FcFontManager.<init>(FcFontManager.java:35)
at sun.awt.X11FontManager.<init>(X11FontManager.java:57)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at java.lang.Class.newInstance(Class.java:442)
at sun.font.FontManagerFactory$1.run(FontManagerFactory.java:83)
at java.security.AccessController.doPrivileged(Native Method)
at sun.font.FontManagerFactory.getInstance(FontManagerFactory.java:74)
at java.awt.Font.getFont2D(Font.java:495)
at java.awt.Font.canDisplayUpTo(Font.java:2080)
at java.awt.font.TextLayout.singleFont(TextLayout.java:470)
at java.awt.font.TextLayout.<init>(TextLayout.java:531)
at org.apache.poi.ss.util.SheetUtil.getDefaultCharWidth(SheetUtil.java:275)
at org.apache.poi.xssf.streaming.AutoSizeColumnTracker.<init>(AutoSizeColumnTracker.java:117)
at org.apache.poi.xssf.streaming.SXSSFSheet.<init>(SXSSFSheet.java:79)
at org.apache.poi.xssf.streaming.SXSSFWorkbook.createAndRegisterSXSSFSheet(SXSSFWorkbook.java:656)
at org.apache.poi.xssf.streaming.SXSSFWorkbook.createSheet(SXSSFWorkbook.java:677)
at org.apache.poi.xssf.streaming.SXSSFWorkbook.createSheet(SXSSFWorkbook.java:83)
at com.alibaba.excel.write.context.GenerateContextImpl.buildCurrentSheet(GenerateContextImpl.java:93)
at com.alibaba.excel.write.ExcelBuilderImpl.addContent(ExcelBuilderImpl.java:53)
at com.alibaba.excel.ExcelWriter.write(ExcelWriter.java:44)
```
### 解决方法
该异常由于自己的环境变量缺少swing需要的字体配置,检查自己应用是否有配置-Djava.awt.headless=true,如果没有请加上该系统参数,可以解决问题。如果仍旧不行,在dockerfile中增加字体安装命令:
![粘贴图片.png](http://ata2-img.cn-hangzhou.img-pub.aliyun-inc.com/a857edfbc8199db7bb35b9e99f1f57d5.png)
参考:
https://lark.alipay.com/aone355606/gfqllg/ulptif
https://stackoverflow.com/questions/30626136/cannot-load-font-in-jre-8 http://www.jianshu.com/p/c05b5fc71bd0
## 2、xls格式错用xlsx方式解析
```
org.apache.poi.openxml4j.exceptions.OLE2NotOfficeXmlFileException: The supplied data appears to be in the OLE2 Format. You are calling the part of POI that deals with OOXML (Office Open XML) Documents. You need to call a different part of POI to process this data (eg HSSF instead of XSSF)
at org.apache.poi.openxml4j.opc.internal.ZipHelper.verifyZipHeader(ZipHelper.java:172)
at org.apache.poi.openxml4j.opc.internal.ZipHelper.openZipStream(ZipHelper.java:229)
at org.apache.poi.openxml4j.opc.ZipPackage.<init>(ZipPackage.java:97)
at org.apache.poi.openxml4j.opc.OPCPackage.open(OPCPackage.java:342)
at com.alibaba.excel.read.v07.XlsxSaxAnalyser.<init>(XlsxSaxAnalyser.java:46)
at com.alibaba.excel.read.ExcelAnalyserImpl.getSaxAnalyser(ExcelAnalyserImpl.java:30)
at com.alibaba.excel.read.ExcelAnalyserImpl.analysis(ExcelAnalyserImpl.java:51)
at com.alibaba.excel.ExcelReader.read(ExcelReader.java:55)
at read.v07.Read2007Xlsx.noModel(Read2007Xlsx.java:42)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at mockit.integration.junit4.internal.BlockJUnit4ClassRunnerDecorator.executeTest(BlockJUnit4ClassRunnerDecorator.java:126)
at mockit.integration.junit4.internal.BlockJUnit4ClassRunnerDecorator.invokeExplosively(BlockJUnit4ClassRunnerDecorator.java:104)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:237)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
```
### 解决方法
该异常时由于03版的xls,文件用07版的方式做解析的报错,请检查excelType是否设置错误。或者是不是手动去修改了excel文件名后缀的xls为xlsx。
## 3、xlsx错用xls解析
```
org.apache.poi.poifs.filesystem.OfficeXmlFileException: The supplied data appears to be in the Office 2007+ XML. You are calling the part of POI that deals with OLE2 Office Documents. You need to call a different part of POI to process this data (eg XSSF instead of HSSF)
at org.apache.poi.poifs.storage.HeaderBlock.<init>(HeaderBlock.java:152)
at org.apache.poi.poifs.storage.HeaderBlock.<init>(HeaderBlock.java:140)
at org.apache.poi.poifs.filesystem.NPOIFSFileSystem.<init>(NPOIFSFileSystem.java:302)
at org.apache.poi.poifs.filesystem.POIFSFileSystem.<init>(POIFSFileSystem.java:87)
at com.alibaba.excel.read.v03.XlsSaxAnalyser.<init>(XlsSaxAnalyser.java:55)
at com.alibaba.excel.read.ExcelAnalyserImpl.getSaxAnalyser(ExcelAnalyserImpl.java:27)
at com.alibaba.excel.read.ExcelAnalyserImpl.analysis(ExcelAnalyserImpl.java:51)
at com.alibaba.excel.ExcelReader.read(ExcelReader.java:55)
at read.v03.XLS2003FunctionTest.testExcel2003NoModel(XLS2003FunctionTest.java:31)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at mockit.integration.junit3.internal.JUnitTestCaseDecorator.runTest(JUnitTestCaseDecorator.java:142)
at mockit.integration.junit3.internal.JUnitTestCaseDecorator.originalRunBare(JUnitTestCaseDecorator.java:102)
at mockit.integration.junit3.internal.JUnitTestCaseDecorator.runBare(JUnitTestCaseDecorator.java:87)
```
原理和原因大致同上
\ No newline at end of file
此差异已折叠。
......@@ -73,7 +73,7 @@ public class EasyExcelFactory {
* read sheet.
* @param listener
* Callback method after each row is parsed.
* @deprecated please use 'EasyExcel.read(in,head,listener).sheet(sheetNo).doRead().finish();'
* @deprecated please use 'EasyExcel.read(in,head,listener).sheet(sheetNo).doRead();'
*/
@Deprecated
public static void readBySax(InputStream in, Sheet sheet, AnalysisEventListener listener) {
......
......@@ -2,6 +2,7 @@ package com.alibaba.excel;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.slf4j.Logger;
......@@ -9,7 +10,7 @@ import org.slf4j.LoggerFactory;
import com.alibaba.excel.analysis.ExcelAnalyser;
import com.alibaba.excel.analysis.ExcelAnalyserImpl;
import com.alibaba.excel.analysis.ExcelExecutor;
import com.alibaba.excel.analysis.ExcelReadExecutor;
import com.alibaba.excel.cache.MapCache;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
......@@ -147,27 +148,41 @@ public class ExcelReader {
/**
* Parse all sheet content by default
*
* @deprecated lease use {@link #readAll()}
*/
@Deprecated
public void read() {
ExcelExecutor excelExecutor = excelAnalyser.excelExecutor();
if (excelExecutor.sheetList().isEmpty()) {
LOGGER.warn("Excel doesn't have any sheets.");
return;
}
for (ReadSheet readSheet : excelExecutor.sheetList()) {
read(readSheet);
}
readAll();
}
/***
* Parse all sheet content by default
*/
public void readAll() {
checkFinished();
excelAnalyser.analysis(null, Boolean.TRUE);
}
/**
* Parse the specified sheet,SheetNo start from 1
* Parse the specified sheet,SheetNo start from 0
*
* @param readSheet
* Read sheet
*/
public ExcelReader read(ReadSheet readSheet) {
public ExcelReader read(ReadSheet... readSheet) {
return read(Arrays.asList(readSheet));
}
/**
* Read multiple sheets.
*
* @param readSheetList
* @return
*/
public ExcelReader read(List<ReadSheet> readSheetList) {
checkFinished();
excelAnalyser.analysis(readSheet);
excelAnalyser.analysis(readSheetList, Boolean.FALSE);
return this;
}
......@@ -225,7 +240,7 @@ public class ExcelReader {
*
* @return
*/
public ExcelExecutor excelExecutor() {
public ExcelReadExecutor excelExecutor() {
checkFinished();
return excelAnalyser.excelExecutor();
}
......
......@@ -17,6 +17,7 @@ import com.alibaba.excel.write.merge.OnceAbsoluteMergeStrategy;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.WriteTable;
import com.alibaba.excel.write.metadata.WriteWorkbook;
import com.alibaba.excel.write.metadata.fill.FillConfig;
/**
* Excel Writer This tool is used to write value out to Excel via POI. This object can perform the following two
......@@ -156,6 +157,30 @@ public class ExcelWriter {
return this;
}
/**
* Fill value to a sheet
*
* @param data
* @param writeSheet
* @return
*/
public ExcelWriter fill(Object data, WriteSheet writeSheet) {
return fill(data, null, writeSheet);
}
/**
* Fill value to a sheet
*
* @param data
* @param fillConfig
* @param writeSheet
* @return
*/
public ExcelWriter fill(Object data, FillConfig fillConfig, WriteSheet writeSheet) {
excelBuilder.fill(data, fillConfig, writeSheet);
return this;
}
/**
* Write data to a sheet
*
......
package com.alibaba.excel.analysis;
import java.util.List;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.metadata.ReadSheet;
......@@ -10,12 +12,14 @@ import com.alibaba.excel.read.metadata.ReadSheet;
*/
public interface ExcelAnalyser {
/**
* parse one sheet
* parse the sheet
*
* @param readSheet
* sheet to read
* @param readSheetList
* Which sheets you need to read.
* @param readAll
* The <code>readSheetList</code> parameter is ignored, and all sheets are read.
*/
void analysis(ReadSheet readSheet);
void analysis(List<ReadSheet> readSheetList, Boolean readAll);
/**
* Complete the entire read file.Release the cache and close stream
......@@ -27,7 +31,7 @@ public interface ExcelAnalyser {
*
* @return Excel file Executor
*/
ExcelExecutor excelExecutor();
ExcelReadExecutor excelExecutor();
/**
* get the analysis context.
......
package com.alibaba.excel.analysis;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.List;
import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.crypt.Decryptor;
import org.apache.poi.poifs.crypt.EncryptionInfo;
import org.apache.poi.poifs.filesystem.DocumentFactoryHelper;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.util.IOUtils;
......@@ -19,7 +24,9 @@ import com.alibaba.excel.read.metadata.ReadSheet;
import com.alibaba.excel.read.metadata.ReadWorkbook;
import com.alibaba.excel.read.metadata.holder.ReadWorkbookHolder;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.excel.util.FileUtils;
import com.alibaba.excel.util.StringUtils;
/**
* @author jipengfei
......@@ -29,7 +36,7 @@ public class ExcelAnalyserImpl implements ExcelAnalyser {
private AnalysisContext analysisContext;
private ExcelExecutor excelExecutor;
private ExcelReadExecutor excelReadExecutor;
public ExcelAnalyserImpl(ReadWorkbook readWorkbook) {
try {
......@@ -48,12 +55,12 @@ public class ExcelAnalyserImpl implements ExcelAnalyser {
ReadWorkbookHolder readWorkbookHolder = analysisContext.readWorkbookHolder();
ExcelTypeEnum excelType = readWorkbookHolder.getExcelType();
if (excelType == null) {
excelExecutor = new XlsxSaxAnalyser(analysisContext, null);
excelReadExecutor = new XlsxSaxAnalyser(analysisContext, null);
return;
}
switch (excelType) {
case XLS:
POIFSFileSystem poifsFileSystem = null;
POIFSFileSystem poifsFileSystem;
if (readWorkbookHolder.getFile() != null) {
poifsFileSystem = new POIFSFileSystem(readWorkbookHolder.getFile());
} else {
......@@ -64,8 +71,9 @@ public class ExcelAnalyserImpl implements ExcelAnalyser {
InputStream decryptedStream = null;
try {
decryptedStream =
DocumentFactoryHelper.getDecryptedStream(poifsFileSystem.getRoot().getFileSystem(), null);
excelExecutor = new XlsxSaxAnalyser(analysisContext, decryptedStream);
DocumentFactoryHelper.getDecryptedStream(poifsFileSystem.getRoot().getFileSystem(),
analysisContext.readWorkbookHolder().getPassword());
excelReadExecutor = new XlsxSaxAnalyser(analysisContext, decryptedStream);
return;
} finally {
IOUtils.closeQuietly(decryptedStream);
......@@ -74,27 +82,37 @@ public class ExcelAnalyserImpl implements ExcelAnalyser {
poifsFileSystem.close();
}
}
excelExecutor = new XlsSaxAnalyser(analysisContext, poifsFileSystem);
if (analysisContext.readWorkbookHolder().getPassword() != null) {
Biff8EncryptionKey.setCurrentUserPassword(analysisContext.readWorkbookHolder().getPassword());
}
excelReadExecutor = new XlsSaxAnalyser(analysisContext, poifsFileSystem);
break;
case XLSX:
excelExecutor = new XlsxSaxAnalyser(analysisContext, null);
excelReadExecutor = new XlsxSaxAnalyser(analysisContext, null);
break;
default:
}
}
@Override
public void analysis(ReadSheet readSheet) {
public void analysis(List<ReadSheet> readSheetList, Boolean readAll) {
try {
analysisContext.currentSheet(excelExecutor, readSheet);
if (!readAll && CollectionUtils.isEmpty(readSheetList)) {
throw new IllegalArgumentException("Specify at least one read sheet.");
}
try {
excelExecutor.execute();
excelReadExecutor.execute(readSheetList, readAll);
} catch (ExcelAnalysisStopException e) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Custom stop!");
}
}
analysisContext.readSheetHolder().notifyAfterAllAnalysed(analysisContext);
// The last sheet is read
if (excelReadExecutor instanceof XlsSaxAnalyser) {
if (analysisContext.readSheetHolder() != null) {
analysisContext.readSheetHolder().notifyAfterAllAnalysed(analysisContext);
}
}
} catch (RuntimeException e) {
finish();
throw e;
......@@ -110,6 +128,7 @@ public class ExcelAnalyserImpl implements ExcelAnalyser {
return;
}
ReadWorkbookHolder readWorkbookHolder = analysisContext.readWorkbookHolder();
try {
if (readWorkbookHolder.getReadCache() != null) {
readWorkbookHolder.getReadCache().destroy();
......@@ -146,6 +165,16 @@ public class ExcelAnalyserImpl implements ExcelAnalyser {
} catch (Throwable t) {
throwCanNotCloseIo(t);
}
clearEncrypt03();
}
private void clearEncrypt03() {
if (StringUtils.isEmpty(analysisContext.readWorkbookHolder().getPassword())
|| !ExcelTypeEnum.XLS.equals(analysisContext.readWorkbookHolder().getExcelType())) {
return;
}
Biff8EncryptionKey.setCurrentUserPassword(null);
}
private void throwCanNotCloseIo(Throwable t) {
......@@ -153,8 +182,8 @@ public class ExcelAnalyserImpl implements ExcelAnalyser {
}
@Override
public com.alibaba.excel.analysis.ExcelExecutor excelExecutor() {
return excelExecutor;
public ExcelReadExecutor excelExecutor() {
return excelReadExecutor;
}
@Override
......
......@@ -9,7 +9,7 @@ import com.alibaba.excel.read.metadata.ReadSheet;
*
* @author Jiaju Zhuang
*/
public interface ExcelExecutor {
public interface ExcelReadExecutor {
/**
* Returns the actual sheet in excel
......@@ -19,8 +19,12 @@ public interface ExcelExecutor {
List<ReadSheet> sheetList();
/**
* Read sheet
* Read the sheet.
*
* @param readSheetList
* Which sheets you need to read.
* @param readAll
* The <code>readSheetList</code> parameter is ignored, and all sheets are read.
*/
void execute();
void execute(List<ReadSheet> readSheetList, Boolean readAll);
}
......@@ -10,7 +10,6 @@ import org.apache.poi.hssf.eventusermodel.HSSFEventFactory;
import org.apache.poi.hssf.eventusermodel.HSSFListener;
import org.apache.poi.hssf.eventusermodel.HSSFRequest;
import org.apache.poi.hssf.eventusermodel.MissingRecordAwareHSSFListener;
import org.apache.poi.hssf.record.BoundSheetRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
......@@ -27,13 +26,14 @@ import com.alibaba.excel.read.metadata.ReadSheet;
public class XlsListSheetListener implements HSSFListener {
private POIFSFileSystem poifsFileSystem;
private List<ReadSheet> sheetList;
private XlsRecordHandler bofRecordHandler;
private BofRecordHandler bofRecordHandler;
public XlsListSheetListener(AnalysisContext analysisContext, POIFSFileSystem poifsFileSystem) {
this.poifsFileSystem = poifsFileSystem;
sheetList = new ArrayList<ReadSheet>();
bofRecordHandler = new BofRecordHandler(analysisContext, sheetList, false);
bofRecordHandler = new BofRecordHandler(analysisContext, sheetList, false, false);
bofRecordHandler.init();
bofRecordHandler.init(null, true);
}
@Override
......
......@@ -22,7 +22,7 @@ import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.excel.analysis.ExcelExecutor;
import com.alibaba.excel.analysis.ExcelReadExecutor;
import com.alibaba.excel.analysis.v03.handlers.BlankOrErrorRecordHandler;
import com.alibaba.excel.analysis.v03.handlers.BofRecordHandler;
import com.alibaba.excel.analysis.v03.handlers.FormulaRecordHandler;
......@@ -56,10 +56,12 @@ import com.alibaba.excel.util.CollectionUtils;
*
* @author jipengfei
*/
public class XlsSaxAnalyser implements HSSFListener, ExcelExecutor {
public class XlsSaxAnalyser implements HSSFListener, ExcelReadExecutor {
private static final Logger LOGGER = LoggerFactory.getLogger(XlsSaxAnalyser.class);
private POIFSFileSystem poifsFileSystem;
private Boolean readAll;
private List<ReadSheet> readSheetList;
private int lastRowNumber;
private int lastColumnNumber;
/**
......@@ -91,8 +93,9 @@ public class XlsSaxAnalyser implements HSSFListener, ExcelExecutor {
}
@Override
public void execute() {
analysisContext.readSheetHolder().getSheetNo();
public void execute(List<ReadSheet> readSheetList, Boolean readAll) {
this.readAll = readAll;
this.readSheetList = readSheetList;
MissingRecordAwareHSSFListener listener = new MissingRecordAwareHSSFListener(this);
formatListener = new FormatTrackingHSSFListener(listener);
workbookBuildingListener = new EventWorkbookBuilder.SheetRecordCollectingListener(formatListener);
......@@ -196,9 +199,9 @@ public class XlsSaxAnalyser implements HSSFListener, ExcelExecutor {
// The table has been counted and there are no duplicate statistics
if (sheets == null) {
sheets = new ArrayList<ReadSheet>();
recordHandlers.add(new BofRecordHandler(analysisContext, sheets, false));
recordHandlers.add(new BofRecordHandler(analysisContext, sheets, false, true));
} else {
recordHandlers.add(new BofRecordHandler(analysisContext, sheets, true));
recordHandlers.add(new BofRecordHandler(analysisContext, sheets, true, true));
}
recordHandlers.add(new FormulaRecordHandler(stubWorkbook, formatListener));
recordHandlers.add(new LabelRecordHandler());
......@@ -212,6 +215,10 @@ public class XlsSaxAnalyser implements HSSFListener, ExcelExecutor {
for (XlsRecordHandler x : recordHandlers) {
x.init();
if (x instanceof BofRecordHandler) {
BofRecordHandler bofRecordHandler = (BofRecordHandler)x;
bofRecordHandler.init(readSheetList, readAll);
}
}
}
}
......@@ -10,6 +10,7 @@ import org.apache.poi.hssf.record.Record;
import com.alibaba.excel.analysis.v03.AbstractXlsRecordHandler;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.alibaba.excel.util.SheetUtils;
/**
* Record handler
......@@ -21,13 +22,18 @@ public class BofRecordHandler extends AbstractXlsRecordHandler {
private BoundSheetRecord[] orderedBsrs;
private int sheetIndex;
private List<ReadSheet> sheets;
private Boolean readAll;
private List<ReadSheet> readSheetList;
private AnalysisContext context;
private boolean alreadyInit;
private boolean needInitSheet;
public BofRecordHandler(AnalysisContext context, List<ReadSheet> sheets, boolean alreadyInit) {
public BofRecordHandler(AnalysisContext context, List<ReadSheet> sheets, boolean alreadyInit,
boolean needInitSheet) {
this.context = context;
this.sheets = sheets;
this.alreadyInit = alreadyInit;
this.needInitSheet = needInitSheet;
}
@Override
......@@ -45,15 +51,34 @@ public class BofRecordHandler extends AbstractXlsRecordHandler {
if (orderedBsrs == null) {
orderedBsrs = BoundSheetRecord.orderByBofPosition(boundSheetRecords);
}
String sheetName = orderedBsrs[sheetIndex].getSheetname();
// Find the currently read sheet
ReadSheet readSheet = null;
if (!alreadyInit) {
ReadSheet readSheet = new ReadSheet(sheetIndex, orderedBsrs[sheetIndex].getSheetname());
readSheet = new ReadSheet(sheetIndex, sheetName);
sheets.add(readSheet);
}
if (context.readSheetHolder() != null) {
if (sheetIndex == context.readSheetHolder().getSheetNo()) {
if (needInitSheet) {
if (readSheet == null) {
for (ReadSheet sheet : sheets) {
if (sheet.getSheetNo() == sheetIndex) {
readSheet = sheet;
break;
}
}
}
assert readSheet != null : "Can't find the sheet.";
context.readWorkbookHolder().setIgnoreRecord03(Boolean.TRUE);
// Copy the parameter to the current sheet
readSheet = SheetUtils.match(readSheet, readSheetList, readAll,
context.readWorkbookHolder().getGlobalConfiguration());
if (readSheet != null) {
if (readSheet.getSheetNo() != 0) {
// Prompt for the end of the previous form read
context.readSheetHolder().notifyAfterAllAnalysed(context);
}
context.currentSheet(readSheet);
context.readWorkbookHolder().setIgnoreRecord03(Boolean.FALSE);
} else {
context.readWorkbookHolder().setIgnoreRecord03(Boolean.TRUE);
}
}
sheetIndex++;
......@@ -71,6 +96,11 @@ public class BofRecordHandler extends AbstractXlsRecordHandler {
}
}
public void init(List<ReadSheet> readSheetList, Boolean readAll) {
this.readSheetList = readSheetList;
this.readAll = readAll;
}
@Override
public int getOrder() {
return 0;
......
......@@ -13,7 +13,9 @@ import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackageAccess;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.model.StylesTable;
import org.apache.poi.xssf.usermodel.XSSFRelation;
......@@ -24,7 +26,7 @@ import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import com.alibaba.excel.analysis.ExcelExecutor;
import com.alibaba.excel.analysis.ExcelReadExecutor;
import com.alibaba.excel.cache.ReadCache;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.exception.ExcelAnalysisException;
......@@ -32,12 +34,14 @@ import com.alibaba.excel.read.metadata.ReadSheet;
import com.alibaba.excel.read.metadata.holder.ReadWorkbookHolder;
import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.excel.util.FileUtils;
import com.alibaba.excel.util.SheetUtils;
import com.alibaba.excel.util.StringUtils;
/**
*
* @author jipengfei
*/
public class XlsxSaxAnalyser implements ExcelExecutor {
public class XlsxSaxAnalyser implements ExcelReadExecutor {
private AnalysisContext analysisContext;
private List<ReadSheet> sheetList;
......@@ -135,7 +139,7 @@ public class XlsxSaxAnalyser implements ExcelExecutor {
} else {
FileUtils.writeToFile(tempFile, readWorkbookHolder.getInputStream());
}
return OPCPackage.open(tempFile);
return OPCPackage.open(tempFile, PackageAccess.READ);
}
@Override
......@@ -171,9 +175,16 @@ public class XlsxSaxAnalyser implements ExcelExecutor {
}
@Override
public void execute() {
parseXmlSource(sheetMap.get(analysisContext.readSheetHolder().getSheetNo()),
new XlsxRowHandler(analysisContext, stylesTable));
public void execute(List<ReadSheet> readSheetList, Boolean readAll) {
for (ReadSheet readSheet : sheetList) {
readSheet = SheetUtils.match(readSheet, readSheetList, readAll,
analysisContext.readWorkbookHolder().getGlobalConfiguration());
if (readSheet != null) {
analysisContext.currentSheet(readSheet);
parseXmlSource(sheetMap.get(readSheet.getSheetNo()), new XlsxRowHandler(analysisContext, stylesTable));
// The last sheet is read
analysisContext.readSheetHolder().notifyAfterAllAnalysed(analysisContext);
}
}
}
}
package com.alibaba.excel.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Ignore all unannotated fields.
*
* @author Jiaju Zhuang
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface ExcelIgnoreUnannotated {
}
......@@ -2,7 +2,7 @@ package com.alibaba.excel.context;
import java.io.InputStream;
import com.alibaba.excel.analysis.ExcelExecutor;
import com.alibaba.excel.analysis.ExcelReadExecutor;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.read.metadata.ReadSheet;
......@@ -22,12 +22,10 @@ public interface AnalysisContext {
/**
* Select the current table
*
* @param excelExecutor
* Excel file Executor
* @param readSheet
* sheet to read
*/
void currentSheet(ExcelExecutor excelExecutor, ReadSheet readSheet);
void currentSheet(ReadSheet readSheet);
/**
* All information about the workbook you are currently working on
......
......@@ -5,8 +5,6 @@ import java.io.InputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.excel.analysis.ExcelExecutor;
import com.alibaba.excel.analysis.v07.XlsxSaxAnalyser;
import com.alibaba.excel.exception.ExcelAnalysisException;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.read.metadata.ReadSheet;
......@@ -16,7 +14,6 @@ import com.alibaba.excel.read.metadata.holder.ReadRowHolder;
import com.alibaba.excel.read.metadata.holder.ReadSheetHolder;
import com.alibaba.excel.read.metadata.holder.ReadWorkbookHolder;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.util.StringUtils;
/**
*
......@@ -53,13 +50,9 @@ public class AnalysisContextImpl implements AnalysisContext {
}
@Override
public void currentSheet(ExcelExecutor excelExecutor, ReadSheet readSheet) {
if (readSheet == null) {
throw new IllegalArgumentException("Sheet argument cannot be null.");
}
public void currentSheet(ReadSheet readSheet) {
readSheetHolder = new ReadSheetHolder(readSheet, readWorkbookHolder);
currentReadHolder = readSheetHolder;
selectSheet(excelExecutor);
if (readWorkbookHolder.getHasReadSheet().contains(readSheetHolder.getSheetNo())) {
throw new ExcelAnalysisException("Cannot read sheet repeatedly.");
}
......@@ -69,54 +62,6 @@ public class AnalysisContextImpl implements AnalysisContext {
}
}
private void selectSheet(ExcelExecutor excelExecutor) {
if (excelExecutor instanceof XlsxSaxAnalyser) {
selectSheet07(excelExecutor);
} else {
selectSheet03();
}
}
private void selectSheet03() {
if (readSheetHolder.getSheetNo() != null && readSheetHolder.getSheetNo() >= 0) {
return;
}
if (!StringUtils.isEmpty(readSheetHolder.getSheetName())) {
LOGGER.warn("Excel 2003 does not support matching sheets by name, defaults to the first one.");
}
readSheetHolder.setSheetNo(0);
}
private void selectSheet07(ExcelExecutor excelExecutor) {
if (readSheetHolder.getSheetNo() != null && readSheetHolder.getSheetNo() >= 0) {
for (ReadSheet readSheetExcel : excelExecutor.sheetList()) {
if (readSheetExcel.getSheetNo().equals(readSheetHolder.getSheetNo())) {
readSheetHolder.setSheetName(readSheetExcel.getSheetName());
return;
}
}
throw new ExcelAnalysisException("Can not find sheet:" + readSheetHolder.getSheetNo());
}
if (!StringUtils.isEmpty(readSheetHolder.getSheetName())) {
for (ReadSheet readSheetExcel : excelExecutor.sheetList()) {
String sheetName = readSheetExcel.getSheetName();
if (sheetName == null) {
continue;
}
if (readSheetHolder.globalConfiguration().getAutoTrim()) {
sheetName = sheetName.trim();
}
if (sheetName.equals(readSheetHolder.getSheetName())) {
readSheetHolder.setSheetNo(readSheetExcel.getSheetNo());
return;
}
}
}
ReadSheet readSheetExcel = excelExecutor.sheetList().get(0);
readSheetHolder.setSheetNo(readSheetExcel.getSheetNo());
readSheetHolder.setSheetName(readSheetExcel.getSheetName());
}
@Override
public ReadWorkbookHolder readWorkbookHolder() {
return readWorkbookHolder;
......
......@@ -5,6 +5,7 @@ import java.io.OutputStream;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import com.alibaba.excel.enums.WriteTypeEnum;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.WriteTable;
import com.alibaba.excel.write.metadata.holder.WriteHolder;
......@@ -21,9 +22,11 @@ public interface WriteContext {
/**
* If the current sheet already exists, select it; if not, create it
*
* @param writeSheet Current sheet
* @param writeSheet
* Current sheet
* @param writeType
*/
void currentSheet(WriteSheet writeSheet);
void currentSheet(WriteSheet writeSheet, WriteTypeEnum writeType);
/**
* If the current table already exists, select it; if not, create it
......@@ -66,6 +69,7 @@ public interface WriteContext {
*/
void finish();
/**
* Current sheet
*
......
package com.alibaba.excel.context;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.util.FileUtils;
import com.alibaba.excel.util.StringUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.security.GeneralSecurityException;
import java.util.Map;
import java.util.UUID;
import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackageAccess;
import org.apache.poi.poifs.crypt.Decryptor;
import org.apache.poi.poifs.crypt.EncryptionInfo;
import org.apache.poi.poifs.crypt.EncryptionMode;
import org.apache.poi.poifs.crypt.Encryptor;
import org.apache.poi.poifs.filesystem.DocumentOutputStream;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
......@@ -13,14 +32,12 @@ import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.excel.enums.WriteTypeEnum;
import com.alibaba.excel.exception.ExcelGenerateException;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.util.WorkBookUtil;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.handler.RowWriteHandler;
import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.handler.WorkbookWriteHandler;
import com.alibaba.excel.write.handler.WriteHandler;
import com.alibaba.excel.util.WriteHandlerUtils;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.WriteTable;
import com.alibaba.excel.write.metadata.WriteWorkbook;
......@@ -64,42 +81,18 @@ public class WriteContextImpl implements WriteContext {
LOGGER.debug("Begin to Initialization 'WriteContextImpl'");
}
initCurrentWorkbookHolder(writeWorkbook);
beforeWorkbookCreate();
WriteHandlerUtils.beforeWorkbookCreate(this);
try {
writeWorkbookHolder.setWorkbook(WorkBookUtil.createWorkBook(writeWorkbookHolder));
WorkBookUtil.createWorkBook(writeWorkbookHolder);
} catch (Exception e) {
throw new ExcelGenerateException("Create workbook failure", e);
}
afterWorkbookCreate();
WriteHandlerUtils.afterWorkbookCreate(this);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Initialization 'WriteContextImpl' complete");
}
}
private void beforeWorkbookCreate() {
List<WriteHandler> handlerList = currentWriteHolder.writeHandlerMap().get(WorkbookWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof WorkbookWriteHandler) {
((WorkbookWriteHandler)writeHandler).beforeWorkbookCreate();
}
}
}
private void afterWorkbookCreate() {
List<WriteHandler> handlerList = currentWriteHolder.writeHandlerMap().get(WorkbookWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof WorkbookWriteHandler) {
((WorkbookWriteHandler)writeHandler).afterWorkbookCreate(writeWorkbookHolder);
}
}
}
private void initCurrentWorkbookHolder(WriteWorkbook writeWorkbook) {
writeWorkbookHolder = new WriteWorkbookHolder(writeWorkbook);
currentWriteHolder = writeWorkbookHolder;
......@@ -112,7 +105,7 @@ public class WriteContextImpl implements WriteContext {
* @param writeSheet
*/
@Override
public void currentSheet(WriteSheet writeSheet) {
public void currentSheet(WriteSheet writeSheet, WriteTypeEnum writeType) {
if (writeSheet == null) {
throw new IllegalArgumentException("Sheet argument cannot be null");
}
......@@ -136,38 +129,9 @@ public class WriteContextImpl implements WriteContext {
return;
}
initCurrentSheetHolder(writeSheet);
beforeSheetCreate();
WriteHandlerUtils.beforeSheetCreate(this);
// Initialization current sheet
initSheet();
afterSheetCreate();
}
private void beforeSheetCreate() {
List<WriteHandler> handlerList = currentWriteHolder.writeHandlerMap().get(SheetWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof SheetWriteHandler) {
((SheetWriteHandler)writeHandler).beforeSheetCreate(writeWorkbookHolder, writeSheetHolder);
}
}
}
private void afterSheetCreate() {
List<WriteHandler> handlerList = currentWriteHolder.writeHandlerMap().get(SheetWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof SheetWriteHandler) {
((SheetWriteHandler)writeHandler).afterSheetCreate(writeWorkbookHolder, writeSheetHolder);
}
}
if (null != writeWorkbookHolder.getWriteWorkbook().getWriteHandler()) {
writeWorkbookHolder.getWriteWorkbook().getWriteHandler().sheet(writeSheetHolder.getSheetNo(),
writeSheetHolder.getSheet());
}
initSheet(writeType);
}
private void initCurrentSheetHolder(WriteSheet writeSheet) {
......@@ -180,19 +144,25 @@ public class WriteContextImpl implements WriteContext {
}
}
private void initSheet() {
private void initSheet(WriteTypeEnum writeType) {
Sheet currentSheet;
try {
currentSheet = writeWorkbookHolder.getWorkbook().getSheetAt(writeSheetHolder.getSheetNo());
writeSheetHolder
.setCachedSheet(writeWorkbookHolder.getCachedWorkbook().getSheetAt(writeSheetHolder.getSheetNo()));
} catch (Exception e) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Can not find sheet:{} ,now create it", writeSheetHolder.getSheetNo());
}
currentSheet = WorkBookUtil.createSheet(writeWorkbookHolder.getWorkbook(), writeSheetHolder.getSheetName());
writeSheetHolder.setCachedSheet(currentSheet);
}
writeSheetHolder.setSheet(currentSheet);
// Initialization head
initHead(writeSheetHolder.excelWriteHeadProperty());
WriteHandlerUtils.afterSheetCreate(this);
if (WriteTypeEnum.ADD.equals(writeType)) {
// Initialization head
initHead(writeSheetHolder.excelWriteHeadProperty());
}
}
public void initHead(ExcelWriteHeadProperty excelWriteHeadProperty) {
......@@ -205,42 +175,13 @@ public class WriteContextImpl implements WriteContext {
addMergedRegionToCurrentSheet(excelWriteHeadProperty, newRowIndex);
for (int relativeRowIndex = 0, i = newRowIndex; i < excelWriteHeadProperty.getHeadRowNumber() + newRowIndex;
i++, relativeRowIndex++) {
beforeRowCreate(newRowIndex, relativeRowIndex);
WriteHandlerUtils.beforeRowCreate(this, newRowIndex, relativeRowIndex, Boolean.TRUE);
Row row = WorkBookUtil.createRow(writeSheetHolder.getSheet(), i);
afterRowCreate(row, relativeRowIndex);
WriteHandlerUtils.afterRowCreate(this, row, relativeRowIndex, Boolean.TRUE);
addOneRowOfHeadDataToExcel(row, excelWriteHeadProperty.getHeadMap(), relativeRowIndex);
}
}
private void beforeRowCreate(int rowIndex, int relativeRowIndex) {
List<WriteHandler> handlerList = currentWriteHolder.writeHandlerMap().get(RowWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof RowWriteHandler) {
((RowWriteHandler)writeHandler).beforeRowCreate(writeSheetHolder, writeTableHolder, rowIndex,
relativeRowIndex, true);
}
}
}
private void afterRowCreate(Row row, int relativeRowIndex) {
List<WriteHandler> handlerList = currentWriteHolder.writeHandlerMap().get(RowWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof RowWriteHandler) {
((RowWriteHandler)writeHandler).afterRowCreate(writeSheetHolder, writeTableHolder, row,
relativeRowIndex, true);
}
}
if (null != writeWorkbookHolder.getWriteWorkbook().getWriteHandler()) {
writeWorkbookHolder.getWriteWorkbook().getWriteHandler().row(row.getRowNum(), row);
}
}
private void addMergedRegionToCurrentSheet(ExcelWriteHeadProperty excelWriteHeadProperty, int rowIndex) {
for (com.alibaba.excel.metadata.CellRange cellRangeModel : excelWriteHeadProperty.headCellRangeList()) {
writeSheetHolder.getSheet().addMergedRegion(new CellRangeAddress(cellRangeModel.getFirstRow() + rowIndex,
......@@ -251,38 +192,13 @@ public class WriteContextImpl implements WriteContext {
private void addOneRowOfHeadDataToExcel(Row row, Map<Integer, Head> headMap, int relativeRowIndex) {
for (Map.Entry<Integer, Head> entry : headMap.entrySet()) {
Head head = entry.getValue();
beforeCellCreate(row, head, relativeRowIndex);
Cell cell = WorkBookUtil.createCell(row, entry.getKey(), head.getHeadNameList().get(relativeRowIndex));
afterCellCreate(head, cell, relativeRowIndex);
}
}
private void beforeCellCreate(Row row, Head head, int relativeRowIndex) {
List<WriteHandler> handlerList = currentWriteHolder.writeHandlerMap().get(CellWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof CellWriteHandler) {
((CellWriteHandler)writeHandler).beforeCellCreate(writeSheetHolder, writeTableHolder, row, head,
relativeRowIndex, true);
}
}
}
private void afterCellCreate(Head head, Cell cell, int relativeRowIndex) {
List<WriteHandler> handlerList = currentWriteHolder.writeHandlerMap().get(CellWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof CellWriteHandler) {
((CellWriteHandler)writeHandler).afterCellCreate(writeSheetHolder, writeTableHolder, null, cell, head,
relativeRowIndex, true);
}
}
if (null != writeWorkbookHolder.getWriteWorkbook().getWriteHandler()) {
writeWorkbookHolder.getWriteWorkbook().getWriteHandler().cell(cell.getRowIndex(), cell);
int columnIndex = entry.getKey();
WriteHandlerUtils.beforeCellCreate(this, row, head, columnIndex, relativeRowIndex, Boolean.TRUE);
Cell cell = row.createCell(columnIndex);
WriteHandlerUtils.afterCellCreate(this, cell, head, relativeRowIndex, Boolean.TRUE);
cell.setCellValue(head.getHeadNameList().get(relativeRowIndex));
CellData cellData = null;
WriteHandlerUtils.afterCellDispose(this, cellData, cell, head, relativeRowIndex, Boolean.TRUE);
}
}
......@@ -341,16 +257,27 @@ public class WriteContextImpl implements WriteContext {
@Override
public void finish() {
WriteHandlerUtils.afterWorkbookDispose(this);
if (writeWorkbookHolder == null) {
return;
}
boolean isOutputStreamEncrypt = false;
try {
writeWorkbookHolder.getWorkbook().write(writeWorkbookHolder.getOutputStream());
writeWorkbookHolder.getWorkbook().close();
isOutputStreamEncrypt = doOutputStreamEncrypt07();
} catch (Throwable t) {
throwCanNotCloseIo(t);
}
if (!isOutputStreamEncrypt) {
try {
writeWorkbookHolder.getWorkbook().write(writeWorkbookHolder.getOutputStream());
writeWorkbookHolder.getWorkbook().close();
} catch (Throwable t) {
throwCanNotCloseIo(t);
}
}
try {
Workbook workbook = writeWorkbookHolder.getWorkbook();
if (workbook instanceof SXSSFWorkbook) {
......@@ -359,6 +286,7 @@ public class WriteContextImpl implements WriteContext {
} catch (Throwable t) {
throwCanNotCloseIo(t);
}
try {
if (writeWorkbookHolder.getAutoCloseStream() && writeWorkbookHolder.getOutputStream() != null) {
writeWorkbookHolder.getOutputStream().close();
......@@ -366,21 +294,25 @@ public class WriteContextImpl implements WriteContext {
} catch (Throwable t) {
throwCanNotCloseIo(t);
}
try {
if (writeWorkbookHolder.getAutoCloseStream() && writeWorkbookHolder.getTemplateInputStream() != null) {
writeWorkbookHolder.getTemplateInputStream().close();
if (!isOutputStreamEncrypt) {
try {
doFileEncrypt07();
} catch (Throwable t) {
throwCanNotCloseIo(t);
}
} catch (Throwable t) {
throwCanNotCloseIo(t);
}
try {
if (!writeWorkbookHolder.getAutoCloseStream() && writeWorkbookHolder.getFile() != null
&& writeWorkbookHolder.getOutputStream() != null) {
writeWorkbookHolder.getOutputStream().close();
if (writeWorkbookHolder.getTempTemplateInputStream() != null) {
writeWorkbookHolder.getTempTemplateInputStream().close();
}
} catch (Throwable t) {
throwCanNotCloseIo(t);
}
clearEncrypt03();
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Finished write.");
}
......@@ -409,4 +341,95 @@ public class WriteContextImpl implements WriteContext {
public Workbook getWorkbook() {
return writeWorkbookHolder.getWorkbook();
}
private void clearEncrypt03() {
if (StringUtils.isEmpty(writeWorkbookHolder.getPassword())
|| !ExcelTypeEnum.XLS.equals(writeWorkbookHolder.getExcelType())) {
return;
}
Biff8EncryptionKey.setCurrentUserPassword(null);
}
/**
* To encrypt
*/
private boolean doOutputStreamEncrypt07() throws Exception {
if (StringUtils.isEmpty(writeWorkbookHolder.getPassword())
|| !ExcelTypeEnum.XLSX.equals(writeWorkbookHolder.getExcelType())) {
return false;
}
if (writeWorkbookHolder.getFile() != null) {
return false;
}
File tempXlsx = FileUtils.createTmpFile(UUID.randomUUID().toString() + ".xlsx");
FileOutputStream tempFileOutputStream = new FileOutputStream(tempXlsx);
try {
writeWorkbookHolder.getWorkbook().write(tempFileOutputStream);
} finally {
try {
writeWorkbookHolder.getWorkbook().close();
tempFileOutputStream.close();
} catch (Exception e) {
if (!tempXlsx.delete()) {
throw new ExcelGenerateException("Can not delete temp File!");
}
throw e;
}
}
POIFSFileSystem fileSystem = null;
try {
fileSystem = openFileSystemAndEncrypt(tempXlsx);
fileSystem.writeFilesystem(writeWorkbookHolder.getOutputStream());
} finally {
if (fileSystem != null) {
fileSystem.close();
}
if (!tempXlsx.delete()) {
throw new ExcelGenerateException("Can not delete temp File!");
}
}
return true;
}
/**
* To encrypt
*/
private void doFileEncrypt07() throws Exception {
if (StringUtils.isEmpty(writeWorkbookHolder.getPassword())
|| !ExcelTypeEnum.XLSX.equals(writeWorkbookHolder.getExcelType())) {
return;
}
if (writeWorkbookHolder.getFile() == null) {
return;
}
FileOutputStream fileOutputStream = null;
POIFSFileSystem fileSystem = null;
try {
fileSystem = openFileSystemAndEncrypt(writeWorkbookHolder.getFile());
fileOutputStream = new FileOutputStream(writeWorkbookHolder.getFile());
fileSystem.writeFilesystem(fileOutputStream);
} finally {
if (fileOutputStream != null) {
fileOutputStream.close();
}
if (fileSystem != null) {
fileSystem.close();
}
}
}
private POIFSFileSystem openFileSystemAndEncrypt(File file) throws Exception {
POIFSFileSystem fileSystem = new POIFSFileSystem();
Encryptor encryptor = new EncryptionInfo(EncryptionMode.standard).getEncryptor();
encryptor.confirmPassword(writeWorkbookHolder.getPassword());
OPCPackage opcPackage = null;
try {
opcPackage = OPCPackage.open(file, PackageAccess.READ_WRITE);
OutputStream outputStream = encryptor.getDataStream(fileSystem);
opcPackage.save(outputStream);
} finally {
opcPackage.close();
}
return fileSystem;
}
}
package com.alibaba.excel.enums;
/**
* Direction of writing
*
* @author Jiaju Zhuang
**/
public enum WriteDirectionEnum {
/**
* Vertical write.
*/
VERTICAL,
/**
* Horizontal write.
*/
HORIZONTAL,;
}
......@@ -5,7 +5,7 @@ package com.alibaba.excel.enums;
*
* @author Jiaju Zhuang
**/
public enum WriteLastRowType {
public enum WriteLastRowTypeEnum {
/**
* Excel are created without templates ,And any data has been written;
*/
......
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,;
}
package com.alibaba.excel.enums;
/**
* Enumeration of write methods
*
* @author Jiaju Zhuang
**/
public enum WriteTypeEnum {
/**
* Add.
*/
ADD,
/**
* Fill.
*/
FILL,;
}
package com.alibaba.excel.exception;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
/**
* Data convert exception
*
* @author Jiaju Zhuang
*/
public class ExcelDataConvertException extends RuntimeException {
/**
* NotNull.
*/
private Integer rowIndex;
/**
* NotNull.
*/
private Integer columnIndex;
/**
* Nullable.Only when the header is configured and when the class header is used is not null.
*
* @see {@link ExcelWriterBuilder#head(Class)}
*/
private ExcelContentProperty excelContentProperty;
public ExcelDataConvertException(String message) {
super(message);
}
public ExcelDataConvertException(Integer rowIndex, Integer columnIndex, ExcelContentProperty excelContentProperty,
String message) {
super(message);
this.rowIndex = rowIndex;
this.columnIndex = columnIndex;
this.excelContentProperty = excelContentProperty;
}
public ExcelDataConvertException(Integer rowIndex, Integer columnIndex, ExcelContentProperty excelContentProperty,
String message, Throwable cause) {
super(message, cause);
this.rowIndex = rowIndex;
this.columnIndex = columnIndex;
this.excelContentProperty = excelContentProperty;
}
public ExcelDataConvertException(String message, Throwable cause) {
super(message, cause);
}
......@@ -18,4 +51,28 @@ public class ExcelDataConvertException extends RuntimeException {
public ExcelDataConvertException(Throwable cause) {
super(cause);
}
public Integer getRowIndex() {
return rowIndex;
}
public void setRowIndex(Integer rowIndex) {
this.rowIndex = rowIndex;
}
public Integer getColumnIndex() {
return columnIndex;
}
public void setColumnIndex(Integer columnIndex) {
this.columnIndex = columnIndex;
}
public ExcelContentProperty getExcelContentProperty() {
return excelContentProperty;
}
public void setExcelContentProperty(ExcelContentProperty excelContentProperty) {
this.excelContentProperty = excelContentProperty;
}
}
......@@ -74,4 +74,5 @@ public class BasicParameter {
public void setUse1904windowing(Boolean use1904windowing) {
this.use1904windowing = use1904windowing;
}
}
......@@ -6,11 +6,13 @@ import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.util.StringUtils;
/**
* Excel internal cell data
* Excel internal cell data.
*
* <p>
*
* @author Jiaju Zhuang
*/
public class CellData {
public class CellData<T> {
private CellDataTypeEnum type;
/**
* {@link CellDataTypeEnum#NUMBER}
......@@ -35,8 +37,12 @@ public class CellData {
* The string of number formatting.Currently only supported when reading
*/
private String dataFormatString;
/**
* The resulting converted data.
*/
private T data;
public CellData(CellData other) {
public CellData(CellData<T> other) {
this.type = other.type;
this.numberValue = other.numberValue;
this.stringValue = other.stringValue;
......@@ -46,6 +52,19 @@ public class CellData {
this.imageValue = other.imageValue;
this.dataFormat = other.dataFormat;
this.dataFormatString = other.dataFormatString;
this.data = other.data;
}
public CellData() {}
public CellData(T data) {
this.data = data;
}
public CellData(T data, String formulaValue) {
this.data = data;
this.formula = Boolean.TRUE;
this.formulaValue = formulaValue;
}
public CellData(String stringValue) {
......@@ -171,6 +190,14 @@ public class CellData {
this.dataFormatString = dataFormatString;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
/**
* Ensure that the object does not appear null
*/
......
......@@ -13,9 +13,11 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import com.alibaba.excel.annotation.format.NumberFormat;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.converters.AutoConverter;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.HeadKindEnum;
......@@ -53,6 +55,10 @@ public class ExcelHeadProperty {
* Configuration column information
*/
private Map<Integer, ExcelContentProperty> contentPropertyMap;
/**
* Configuration column information
*/
private Map<String, ExcelContentProperty> fieldNameContentPropertyMap;
/**
* Fields ignored
*/
......@@ -62,6 +68,7 @@ public class ExcelHeadProperty {
this.headClazz = headClazz;
headMap = new TreeMap<Integer, Head>();
contentPropertyMap = new TreeMap<Integer, ExcelContentProperty>();
fieldNameContentPropertyMap = new HashMap<String, ExcelContentProperty>();
ignoreMap = new HashMap<String, Field>(16);
headKind = HeadKindEnum.NONE;
headRowNumber = 0;
......@@ -79,10 +86,6 @@ public class ExcelHeadProperty {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("The initialization sheet/table 'ExcelHeadProperty' is complete , head kind is {}", headKind);
}
if (!hasHead()) {
LOGGER.warn(
"The table has no header set and all annotations will not be read.If you want to use annotations, please use set head class in ExcelWriterBuilder/ExcelWriterSheetBuilder/ExcelWriterTableBuilder");
}
}
private void initHeadRowNumber() {
......@@ -119,25 +122,28 @@ public class ExcelHeadProperty {
tempClass = tempClass.getSuperclass();
}
ExcelIgnoreUnannotated excelIgnoreUnannotated =
(ExcelIgnoreUnannotated)headClazz.getAnnotation(ExcelIgnoreUnannotated.class);
// Screening of field
List<Field> defaultFieldList = new ArrayList<Field>();
Map<Integer, Field> customFiledMap = new TreeMap<Integer, Field>();
for (Field field : fieldList) {
ExcelIgnore excelIgnore = field.getAnnotation(ExcelIgnore.class);
if(Modifier.isStatic(field.getModifiers())&&Modifier.isFinal(field.getModifiers())){
ignoreMap.put(field.getName(),field);
continue;
}
if(Modifier.isTransient(field.getModifiers())){
ignoreMap.put(field.getName(),field);
continue;
}
if (excelIgnore != null) {
ignoreMap.put(field.getName(), field);
continue;
}
ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
if (excelProperty == null && convertAllFiled != null && !convertAllFiled) {
boolean noExcelProperty = excelProperty == null
&& ((convertAllFiled != null && !convertAllFiled) || excelIgnoreUnannotated != null);
if (noExcelProperty) {
ignoreMap.put(field.getName(), field);
continue;
}
boolean isStaticFinalOrTransient =
(Modifier.isStatic(field.getModifiers()) && Modifier.isFinal(field.getModifiers()))
|| Modifier.isTransient(field.getModifiers());
if (excelProperty == null && isStaticFinalOrTransient) {
ignoreMap.put(field.getName(), field);
continue;
}
......@@ -199,6 +205,7 @@ public class ExcelHeadProperty {
.setNumberFormatProperty(NumberFormatProperty.build(field.getAnnotation(NumberFormat.class)));
headMap.put(index, head);
contentPropertyMap.put(index, excelContentProperty);
fieldNameContentPropertyMap.put(field.getName(), excelContentProperty);
}
public Class getHeadClazz() {
......@@ -245,6 +252,14 @@ public class ExcelHeadProperty {
this.contentPropertyMap = contentPropertyMap;
}
public Map<String, ExcelContentProperty> getFieldNameContentPropertyMap() {
return fieldNameContentPropertyMap;
}
public void setFieldNameContentPropertyMap(Map<String, ExcelContentProperty> fieldNameContentPropertyMap) {
this.fieldNameContentPropertyMap = fieldNameContentPropertyMap;
}
public Map<String, Field> getIgnoreMap() {
return ignoreMap;
}
......
......@@ -222,10 +222,28 @@ public class ExcelReaderBuilder {
return this;
}
/**
* Whether the encryption
*
* @param password
* @return
*/
public ExcelReaderBuilder password(String password) {
readWorkbook.setPassword(password);
return this;
}
public ExcelReader build() {
return new ExcelReader(readWorkbook);
}
public ExcelReader doReadAll() {
ExcelReader excelReader = build();
excelReader.readAll();
excelReader.finish();
return excelReader;
}
public ExcelReaderSheetBuilder sheet() {
return sheet(null, null);
}
......
......@@ -33,7 +33,8 @@ public class ModelBuildEventListener extends AbstractIgnoreExceptionReadListener
public void invoke(Map<Integer, CellData> cellDataMap, AnalysisContext context) {
ReadHolder currentReadHolder = context.currentReadHolder();
if (HeadKindEnum.CLASS.equals(currentReadHolder.excelReadHeadProperty().getHeadKind())) {
context.readRowHolder().setCurrentRowAnalysisResult(buildUserModel(cellDataMap, currentReadHolder));
context.readRowHolder()
.setCurrentRowAnalysisResult(buildUserModel(cellDataMap, currentReadHolder, context));
return;
}
context.readRowHolder().setCurrentRowAnalysisResult(buildStringList(cellDataMap, currentReadHolder, context));
......@@ -41,35 +42,51 @@ public class ModelBuildEventListener extends AbstractIgnoreExceptionReadListener
private Object buildStringList(Map<Integer, CellData> cellDataMap, ReadHolder currentReadHolder,
AnalysisContext context) {
int index = 0;
if (context.readWorkbookHolder().getDefaultReturnMap()) {
Map<Integer, String> map = new HashMap<Integer, String>(cellDataMap.size() * 4 / 3 + 1);
for (Map.Entry<Integer, CellData> entry : cellDataMap.entrySet()) {
Integer key = entry.getKey();
CellData cellData = entry.getValue();
while (index < key) {
map.put(index, null);
index++;
}
index++;
if (cellData.getType() == CellDataTypeEnum.EMPTY) {
map.put(entry.getKey(), null);
map.put(key, null);
continue;
}
map.put(entry.getKey(), (String)ConverterUtils.convertToJavaObject(cellData, String.class, null,
currentReadHolder.converterMap(), currentReadHolder.globalConfiguration()));
map.put(key,
(String)ConverterUtils.convertToJavaObject(cellData, null, null, currentReadHolder.converterMap(),
currentReadHolder.globalConfiguration(), context.readRowHolder().getRowIndex(), key));
}
return map;
} else {
// Compatible with the old code the old code returns a list
List<String> list = new ArrayList<String>();
for (Map.Entry<Integer, CellData> entry : cellDataMap.entrySet()) {
Integer key = entry.getKey();
CellData cellData = entry.getValue();
while (index < key) {
list.add(null);
index++;
}
index++;
if (cellData.getType() == CellDataTypeEnum.EMPTY) {
list.add(null);
continue;
}
list.add((String)ConverterUtils.convertToJavaObject(cellData, String.class, null,
currentReadHolder.converterMap(), currentReadHolder.globalConfiguration()));
list.add(
(String)ConverterUtils.convertToJavaObject(cellData, null, null, currentReadHolder.converterMap(),
currentReadHolder.globalConfiguration(), context.readRowHolder().getRowIndex(), key));
}
return list;
}
}
private Object buildUserModel(Map<Integer, CellData> cellDataMap, ReadHolder currentReadHolder) {
private Object buildUserModel(Map<Integer, CellData> cellDataMap, ReadHolder currentReadHolder,
AnalysisContext context) {
ExcelReadHeadProperty excelReadHeadProperty = currentReadHolder.excelReadHeadProperty();
Object resultModel;
try {
......@@ -91,8 +108,9 @@ public class ModelBuildEventListener extends AbstractIgnoreExceptionReadListener
continue;
}
ExcelContentProperty excelContentProperty = contentPropertyMap.get(index);
Object value = ConverterUtils.convertToJavaObject(cellData, excelContentProperty.getField().getType(),
excelContentProperty, currentReadHolder.converterMap(), currentReadHolder.globalConfiguration());
Object value = ConverterUtils.convertToJavaObject(cellData, excelContentProperty.getField(),
excelContentProperty, currentReadHolder.converterMap(), currentReadHolder.globalConfiguration(),
context.readRowHolder().getRowIndex(), index);
if (value != null) {
map.put(excelContentProperty.getField().getName(), value);
}
......
......@@ -42,6 +42,19 @@ public class ReadSheet extends ReadBasicParameter {
this.sheetName = sheetName;
}
public void copyBasicParameter(ReadSheet other) {
if (other == null) {
return;
}
this.setHeadRowNumber(other.getHeadRowNumber());
this.setCustomReadListenerList(other.getCustomReadListenerList());
this.setHead(other.getHead());
this.setClazz(other.getClazz());
this.setCustomConverterList(other.getCustomConverterList());
this.setAutoTrim(other.getAutoTrim());
this.setUse1904windowing(other.getUse1904windowing());
}
@Override
public String toString() {
return "ReadSheet{" + "sheetNo=" + sheetNo + ", sheetName='" + sheetName + '\'' + "} " + super.toString();
......
......@@ -59,6 +59,10 @@ public class ReadWorkbook extends ReadBasicParameter {
* Select the cache.Default use {@link com.alibaba.excel.cache.selector.SimpleReadCacheSelector}
*/
private ReadCacheSelector readCacheSelector;
/**
* Whether the encryption
*/
private String password;
/**
* The default is all excel objects.Default is true.
* <p>
......@@ -164,4 +168,12 @@ public class ReadWorkbook extends ReadBasicParameter {
public void setReadCacheSelector(ReadCacheSelector readCacheSelector) {
this.readCacheSelector = readCacheSelector;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
......@@ -8,8 +8,6 @@ import java.util.Set;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.excel.cache.ReadCache;
import com.alibaba.excel.cache.selector.EternalReadCacheSelector;
......@@ -28,7 +26,6 @@ import com.alibaba.excel.support.ExcelTypeEnum;
* @author Jiaju Zhuang
*/
public class ReadWorkbookHolder extends AbstractReadHolder {
private static final Logger LOGGER = LoggerFactory.getLogger(ReadWorkbookHolder.class);
/**
* current param
......@@ -82,7 +79,10 @@ public class ReadWorkbookHolder extends AbstractReadHolder {
* Temporary files when reading excel
*/
private File tempFile;
/**
* Whether the encryption
*/
private String password;
/**
* The default is all excel objects.if true , you can use {@link com.alibaba.excel.annotation.ExcelIgnore} ignore a
* field. if false , you must use {@link com.alibaba.excel.annotation.ExcelProperty} to use a filed.
......@@ -141,11 +141,11 @@ public class ReadWorkbookHolder extends AbstractReadHolder {
} else {
this.autoCloseStream = readWorkbook.getAutoCloseStream();
}
if (readWorkbook.getExcelType() == null) {
this.excelType = ExcelTypeEnum.valueOf(file, inputStream);
} else {
this.excelType = readWorkbook.getExcelType();
}
// The type of excel is read according to the judgment.Because encrypted XLSX needs to be specified as XLS to
// properly parse.
this.excelType = ExcelTypeEnum.valueOf(file, inputStream, readWorkbook.getExcelType());
if (ExcelTypeEnum.XLS == excelType && getGlobalConfiguration().getUse1904windowing() == null) {
getGlobalConfiguration().setUse1904windowing(Boolean.FALSE);
}
......@@ -174,6 +174,7 @@ public class ReadWorkbookHolder extends AbstractReadHolder {
}
this.hasReadSheet = new HashSet<Integer>();
this.ignoreRecord03 = Boolean.FALSE;
this.password = readWorkbook.getPassword();
}
public ReadWorkbook getReadWorkbook() {
......@@ -312,6 +313,14 @@ public class ReadWorkbookHolder extends AbstractReadHolder {
this.ignoreRecord03 = ignoreRecord03;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public HolderEnum holderType() {
return HolderEnum.WORKBOOK;
......
......@@ -29,7 +29,7 @@ public enum ExcelTypeEnum {
this.setValue(value);
}
public static ExcelTypeEnum valueOf(File file, InputStream inputStream) {
public static ExcelTypeEnum valueOf(File file, InputStream inputStream, ExcelTypeEnum excelType) {
try {
FileMagic fileMagic;
if (file != null) {
......@@ -59,9 +59,15 @@ public enum ExcelTypeEnum {
return XLSX;
}
} catch (IOException e) {
if (excelType != null) {
return excelType;
}
throw new ExcelCommonException(
"Convert excel format exception.You can try specifying the 'excelType' yourself", e);
}
if (excelType != null) {
return excelType;
}
throw new ExcelCommonException(
"Convert excel format exception.You can try specifying the 'excelType' yourself");
}
......
package com.alibaba.excel.util;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
......@@ -56,17 +59,55 @@ public class ConverterUtils {
* Convert it into a Java object
*
* @param cellData
* @param clazz
* @param field
* @param contentProperty
* @param converterMap
* @param globalConfiguration
* @param rowIndex
* @param columnIndex
* @return
*/
public static Object convertToJavaObject(CellData cellData, Class clazz, ExcelContentProperty contentProperty,
Map<String, Converter> converterMap, GlobalConfiguration globalConfiguration) {
public static Object convertToJavaObject(CellData cellData, Field field, ExcelContentProperty contentProperty,
Map<String, Converter> converterMap, GlobalConfiguration globalConfiguration, Integer rowIndex,
Integer columnIndex) {
Class clazz;
if (field == null) {
clazz = String.class;
} else {
clazz = field.getType();
}
if (clazz == CellData.class) {
return new CellData(cellData);
Type type = field.getGenericType();
Class classGeneric;
if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType)type;
classGeneric = (Class)parameterizedType.getActualTypeArguments()[0];
} else {
classGeneric = String.class;
}
CellData cellDataReturn = new CellData(cellData);
cellDataReturn.setData(doConvertToJavaObject(cellData, classGeneric, contentProperty, converterMap,
globalConfiguration, rowIndex, columnIndex));
return cellDataReturn;
}
return doConvertToJavaObject(cellData, clazz, contentProperty, converterMap, globalConfiguration, rowIndex,
columnIndex);
}
/**
*
* @param cellData
* @param clazz
* @param contentProperty
* @param converterMap
* @param globalConfiguration
* @param rowIndex
* @param columnIndex
* @return
*/
private static Object doConvertToJavaObject(CellData cellData, Class clazz, ExcelContentProperty contentProperty,
Map<String, Converter> converterMap, GlobalConfiguration globalConfiguration, Integer rowIndex,
Integer columnIndex) {
Converter converter = null;
if (contentProperty != null) {
converter = contentProperty.getConverter();
......@@ -75,13 +116,14 @@ public class ConverterUtils {
converter = converterMap.get(ConverterKeyBuild.buildKey(clazz, cellData.getType()));
}
if (converter == null) {
throw new ExcelDataConvertException(
throw new ExcelDataConvertException(rowIndex, columnIndex, contentProperty,
"Converter not found, convert " + cellData.getType() + " to " + clazz.getName());
}
try {
return converter.convertToJavaData(cellData, contentProperty, globalConfiguration);
} catch (Exception e) {
throw new ExcelDataConvertException("Convert data " + cellData + " to " + clazz + " error ", e);
throw new ExcelDataConvertException(rowIndex, columnIndex, contentProperty,
"Convert data " + cellData + " to " + clazz + " error ", e);
}
}
}
......@@ -157,6 +157,15 @@ public class FileUtils {
return directory;
}
public static File createTmpFile(String fileName) {
String tmpDir = System.getProperty(JAVA_IO_TMPDIR);
if (tmpDir == null) {
throw new RuntimeException(
"Systems temporary directory not defined - set the -D" + JAVA_IO_TMPDIR + " jvm property!");
}
return new File(tmpDir, fileName);
}
/**
*
* @param directory
......
package com.alibaba.excel.util;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.read.metadata.ReadSheet;
/**
* Sheet utils
*
* @author Jiaju Zhuang
*/
public class SheetUtils {
private static final Logger LOGGER = LoggerFactory.getLogger(SheetUtils.class);
private SheetUtils() {}
/**
* Match the parameters to the actual sheet
*
* @param readSheet
* actual sheet
* @param parameterReadSheetList
* parameters
* @param readAll
* @return
*/
public static ReadSheet match(ReadSheet readSheet, List<ReadSheet> parameterReadSheetList, Boolean readAll,
GlobalConfiguration globalConfiguration) {
if (readAll) {
return readSheet;
}
for (ReadSheet parameterReadSheet : parameterReadSheetList) {
if (parameterReadSheet == null) {
continue;
}
if (parameterReadSheet.getSheetNo() == null && parameterReadSheet.getSheetName() == null) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("The first is read by default.");
}
parameterReadSheet.setSheetNo(0);
}
boolean match = (parameterReadSheet.getSheetNo() != null
&& parameterReadSheet.getSheetNo().equals(readSheet.getSheetNo()));
if (!match) {
String parameterSheetName = parameterReadSheet.getSheetName();
if (!StringUtils.isEmpty(parameterSheetName)) {
boolean autoTrim = (parameterReadSheet.getAutoTrim() != null && parameterReadSheet.getAutoTrim())
|| (parameterReadSheet.getAutoTrim() == null && globalConfiguration.getAutoTrim());
if (autoTrim) {
parameterSheetName = parameterSheetName.trim();
}
match = parameterSheetName.equals(readSheet.getSheetName());
}
}
if (match) {
readSheet.copyBasicParameter(parameterReadSheet);
return readSheet;
}
}
return null;
}
}
......@@ -6,10 +6,11 @@ package com.alibaba.excel.util;
* @author jipengfei
*/
public class StringUtils {
public static final String EMPTY = "";
private StringUtils() {}
public static boolean isEmpty(Object str) {
return (str == null || "".equals(str));
return (str == null || EMPTY.equals(str));
}
}
......@@ -2,8 +2,8 @@ package com.alibaba.excel.util;
import java.io.IOException;
import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
......@@ -22,35 +22,35 @@ import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
*/
public class WorkBookUtil {
private static final int ROW_ACCESS_WINDOW_SIZE = 500;
private WorkBookUtil() {}
public static Workbook createWorkBook(WriteWorkbookHolder writeWorkbookHolder)
throws IOException, InvalidFormatException {
public static void createWorkBook(WriteWorkbookHolder writeWorkbookHolder) throws IOException {
if (ExcelTypeEnum.XLSX.equals(writeWorkbookHolder.getExcelType())) {
XSSFWorkbook xssfWorkbook = null;
if (writeWorkbookHolder.getTemplateFile() != null) {
xssfWorkbook = new XSSFWorkbook(writeWorkbookHolder.getTemplateFile());
}
if (writeWorkbookHolder.getTemplateInputStream() != null) {
xssfWorkbook = new XSSFWorkbook(writeWorkbookHolder.getTemplateInputStream());
}
// When using SXSSFWorkbook, you can't get the actual last line.But we need to read the last line when we
// are using the template, so we cache it
if (xssfWorkbook != null) {
for (int i = 0; i < xssfWorkbook.getNumberOfSheets(); i++) {
writeWorkbookHolder.getTemplateLastRowMap().put(i, xssfWorkbook.getSheetAt(i).getLastRowNum());
}
return new SXSSFWorkbook(xssfWorkbook);
if (writeWorkbookHolder.getTempTemplateInputStream() != null) {
XSSFWorkbook xssfWorkbook = new XSSFWorkbook(writeWorkbookHolder.getTempTemplateInputStream());
writeWorkbookHolder.setCachedWorkbook(xssfWorkbook);
writeWorkbookHolder.setWorkbook(new SXSSFWorkbook(xssfWorkbook, ROW_ACCESS_WINDOW_SIZE));
return;
}
return new SXSSFWorkbook(500);
SXSSFWorkbook sxssWorkbook = new SXSSFWorkbook(ROW_ACCESS_WINDOW_SIZE);
writeWorkbookHolder.setCachedWorkbook(sxssWorkbook);
writeWorkbookHolder.setWorkbook(sxssWorkbook);
return;
}
if (writeWorkbookHolder.getTemplateFile() != null) {
return new HSSFWorkbook(new POIFSFileSystem(writeWorkbookHolder.getTemplateFile()));
HSSFWorkbook hssfWorkbook;
if (writeWorkbookHolder.getTempTemplateInputStream() != null) {
hssfWorkbook = new HSSFWorkbook(new POIFSFileSystem(writeWorkbookHolder.getTempTemplateInputStream()));
} else {
hssfWorkbook = new HSSFWorkbook();
}
if (writeWorkbookHolder.getTemplateInputStream() != null) {
return new HSSFWorkbook(new POIFSFileSystem(writeWorkbookHolder.getTemplateInputStream()));
writeWorkbookHolder.setCachedWorkbook(hssfWorkbook);
writeWorkbookHolder.setWorkbook(hssfWorkbook);
if (writeWorkbookHolder.getPassword() != null) {
Biff8EncryptionKey.setCurrentUserPassword(writeWorkbookHolder.getPassword());
hssfWorkbook.writeProtectWorkbook(writeWorkbookHolder.getPassword(), StringUtils.EMPTY);
}
return new HSSFWorkbook();
}
public static Sheet createSheet(Workbook workbook, String sheetName) {
......
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);
}
}
}
......@@ -6,6 +6,7 @@ import com.alibaba.excel.context.WriteContext;
import com.alibaba.excel.write.merge.OnceAbsoluteMergeStrategy;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.WriteTable;
import com.alibaba.excel.write.metadata.fill.FillConfig;
/**
* @author jipengfei
......@@ -36,6 +37,15 @@ public interface ExcelBuilder {
*/
void addContent(List data, WriteSheet writeSheet, WriteTable writeTable);
/**
* WorkBook fill value
*
* @param data
* @param fillConfig
* @param writeSheet
*/
void fill(Object data, FillConfig fillConfig, WriteSheet writeSheet);
/**
* Creates new cell range. Indexes are zero-based.
*
......@@ -63,4 +73,13 @@ public interface ExcelBuilder {
* Close io
*/
void finish();
/**
* add password
* @param data
* @param writeSheet
* @param writeTable
* @param password
*/
void addContent(List data, WriteSheet writeSheet, WriteTable writeTable, String password);
}
package com.alibaba.excel.write;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.ss.usermodel.Drawing;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;
import com.alibaba.excel.context.WriteContext;
import com.alibaba.excel.context.WriteContextImpl;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.converters.ConverterKeyBuild;
import com.alibaba.excel.enums.HeadKindEnum;
import com.alibaba.excel.exception.ExcelDataConvertException;
import com.alibaba.excel.enums.WriteTypeEnum;
import com.alibaba.excel.exception.ExcelGenerateException;
import com.alibaba.excel.metadata.BaseRowModel;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.excel.util.FileUtils;
import com.alibaba.excel.util.WorkBookUtil;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.handler.RowWriteHandler;
import com.alibaba.excel.write.handler.WriteHandler;
import com.alibaba.excel.write.executor.ExcelWriteAddExecutor;
import com.alibaba.excel.write.executor.ExcelWriteFillExecutor;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.WriteTable;
import com.alibaba.excel.write.metadata.WriteWorkbook;
import com.alibaba.excel.write.metadata.holder.WriteHolder;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import net.sf.cglib.beans.BeanMap;
import com.alibaba.excel.write.metadata.fill.FillConfig;
/**
* @author jipengfei
......@@ -48,6 +22,8 @@ import net.sf.cglib.beans.BeanMap;
public class ExcelBuilderImpl implements ExcelBuilder {
private WriteContext context;
private ExcelWriteFillExecutor excelWriteFillExecutor;
private ExcelWriteAddExecutor excelWriteAddExecutor;
public ExcelBuilderImpl(WriteWorkbook writeWorkbook) {
try {
......@@ -63,23 +39,6 @@ public class ExcelBuilderImpl implements ExcelBuilder {
}
}
private void doAddContent(List data) {
if (CollectionUtils.isEmpty(data)) {
return;
}
WriteSheetHolder writeSheetHolder = context.writeSheetHolder();
int newRowIndex = writeSheetHolder.getNewRowIndexAndStartDoWrite();
if (writeSheetHolder.isNew() && !writeSheetHolder.getExcelWriteHeadProperty().hasHead()) {
newRowIndex += context.currentWriteHolder().relativeHeadRowIndex();
}
// BeanMap is out of order,so use fieldList
List<Field> fieldList = new ArrayList<Field>();
for (int relativeRowIndex = 0; relativeRowIndex < data.size(); relativeRowIndex++) {
int n = relativeRowIndex + newRowIndex;
addOneRowOfDataToExcel(data.get(relativeRowIndex), n, relativeRowIndex, fieldList);
}
}
@Override
public void addContent(List data, WriteSheet writeSheet) {
addContent(data, writeSheet, null);
......@@ -88,9 +47,15 @@ public class ExcelBuilderImpl implements ExcelBuilder {
@Override
public void addContent(List data, WriteSheet writeSheet, WriteTable writeTable) {
try {
context.currentSheet(writeSheet);
if (data == null) {
return;
}
context.currentSheet(writeSheet, WriteTypeEnum.ADD);
context.currentTable(writeTable);
doAddContent(data);
if (excelWriteAddExecutor == null) {
excelWriteAddExecutor = new ExcelWriteAddExecutor(context);
}
excelWriteAddExecutor.add(data);
} catch (RuntimeException e) {
finish();
throw e;
......@@ -101,278 +66,64 @@ public class ExcelBuilderImpl implements ExcelBuilder {
}
@Override
public void finish() {
if (context != null) {
context.finish();
}
}
@Override
public void merge(int firstRow, int lastRow, int firstCol, int lastCol) {
CellRangeAddress cra = new CellRangeAddress(firstRow, lastRow, firstCol, lastCol);
context.writeSheetHolder().getSheet().addMergedRegion(cra);
}
@Override
public WriteContext writeContext() {
return context;
}
private void addOneRowOfDataToExcel(Object oneRowData, int n, int relativeRowIndex, List<Field> fieldList) {
beforeRowCreate(n, relativeRowIndex);
Row row = WorkBookUtil.createRow(context.writeSheetHolder().getSheet(), n);
afterRowCreate(row, relativeRowIndex);
if (oneRowData instanceof List) {
addBasicTypeToExcel((List)oneRowData, row, relativeRowIndex);
} else {
addJavaObjectToExcel(oneRowData, row, relativeRowIndex, fieldList);
}
}
private void beforeRowCreate(int rowIndex, int relativeRowIndex) {
List<WriteHandler> handlerList = context.currentWriteHolder().writeHandlerMap().get(RowWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof RowWriteHandler) {
((RowWriteHandler)writeHandler).beforeRowCreate(context.writeSheetHolder(), context.writeTableHolder(),
rowIndex, relativeRowIndex, false);
}
}
}
private void afterRowCreate(Row row, int relativeRowIndex) {
List<WriteHandler> handlerList = context.currentWriteHolder().writeHandlerMap().get(RowWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof RowWriteHandler) {
((RowWriteHandler)writeHandler).afterRowCreate(context.writeSheetHolder(), context.writeTableHolder(),
row, relativeRowIndex, false);
}
}
if (null != context.writeWorkbookHolder().getWriteWorkbook().getWriteHandler()) {
context.writeWorkbookHolder().getWriteWorkbook().getWriteHandler().row(row.getRowNum(), row);
}
}
private void addBasicTypeToExcel(List<Object> oneRowData, Row row, int relativeRowIndex) {
if (CollectionUtils.isEmpty(oneRowData)) {
return;
}
Map<Integer, Head> headMap = context.currentWriteHolder().excelWriteHeadProperty().getHeadMap();
int dataIndex = 0;
int cellIndex = 0;
for (Map.Entry<Integer, Head> entry : headMap.entrySet()) {
if (dataIndex >= oneRowData.size()) {
public void fill(Object data, FillConfig fillConfig, WriteSheet writeSheet) {
try {
if (data == null) {
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;
if (context.writeWorkbookHolder().getTempTemplateInputStream() == null) {
throw new ExcelGenerateException("Calling the 'fill' method must use a template.");
}
Object value = beanMap.get(filedName);
if (value == null) {
continue;
context.currentSheet(writeSheet, WriteTypeEnum.FILL);
if (excelWriteFillExecutor == null) {
excelWriteFillExecutor = new ExcelWriteFillExecutor(context);
}
beforeCellCreate(row, null, relativeRowIndex);
Cell cell = WorkBookUtil.createCell(row, cellIndex++);
CellData cellData = converterAndSet(currentWriteHolder, value.getClass(), cell, value, null);
afterCellCreate(null, cellData, cell, relativeRowIndex);
excelWriteFillExecutor.fill(data, fillConfig);
} catch (RuntimeException e) {
finish();
throw e;
} catch (Throwable e) {
finish();
throw new ExcelGenerateException(e);
}
}
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();
@Override
public void finish() {
if (context != null) {
context.finish();
}
}
private void beforeCellCreate(Row row, Head head, int relativeRowIndex) {
List<WriteHandler> handlerList = context.currentWriteHolder().writeHandlerMap().get(CellWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof CellWriteHandler) {
((CellWriteHandler)writeHandler).beforeCellCreate(context.writeSheetHolder(),
context.writeTableHolder(), row, head, relativeRowIndex, false);
@Override
public void addContent(List data, WriteSheet writeSheet, WriteTable writeTable, String password) {
try {
if (data == null) {
return;
}
}
}
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);
context.currentSheet(writeSheet, WriteTypeEnum.ADD);
context.currentTable(writeTable);
if (excelWriteAddExecutor == null) {
excelWriteAddExecutor = new ExcelWriteAddExecutor(context);
}
}
if (null != context.writeWorkbookHolder().getWriteWorkbook().getWriteHandler()) {
context.writeWorkbookHolder().getWriteWorkbook().getWriteHandler().cell(cell.getRowIndex(), cell);
}
}
private CellData converterAndSet(WriteHolder currentWriteHolder, Class clazz, Cell cell, Object value,
ExcelContentProperty excelContentProperty) {
if (value == null) {
return null;
}
if (value instanceof String && currentWriteHolder.globalConfiguration().getAutoTrim()) {
value = ((String)value).trim();
}
CellData cellData = convert(currentWriteHolder, clazz, cell, value, excelContentProperty);
if (cellData == null || cellData.getType() == null) {
throw new ExcelDataConvertException(
"Convert data:" + value + " return null,at row:" + cell.getRow().getRowNum());
}
if (cellData.getFormula() != null && cellData.getFormula()) {
cell.setCellFormula(cellData.getFormulaValue());
}
switch (cellData.getType()) {
case STRING:
cell.setCellValue(cellData.getStringValue());
return cellData;
case BOOLEAN:
cell.setCellValue(cellData.getBooleanValue());
return cellData;
case NUMBER:
cell.setCellValue(cellData.getNumberValue().doubleValue());
return cellData;
case IMAGE:
setImageValue(cellData, cell);
return cellData;
default:
throw new ExcelDataConvertException("Not supported data:" + value + " return type:" + cell.getCellType()
+ "at row:" + cell.getRow().getRowNum());
excelWriteAddExecutor.add(data);
} catch (RuntimeException e) {
finish();
throw e;
} catch (Throwable e) {
finish();
throw new ExcelGenerateException(e);
}
}
private void setImageValue(CellData cellData, Cell cell) {
Sheet sheet = cell.getSheet();
int index = sheet.getWorkbook().addPicture(cellData.getImageValue(), HSSFWorkbook.PICTURE_TYPE_PNG);
Drawing drawing = sheet.getDrawingPatriarch();
if (drawing == null) {
drawing = sheet.createDrawingPatriarch();
}
CreationHelper helper = sheet.getWorkbook().getCreationHelper();
ClientAnchor anchor = helper.createClientAnchor();
anchor.setDx1(0);
anchor.setDx2(0);
anchor.setDy1(0);
anchor.setDy2(0);
anchor.setCol1(cell.getColumnIndex());
anchor.setCol2(cell.getColumnIndex() + 1);
anchor.setRow1(cell.getRowIndex());
anchor.setRow2(cell.getRowIndex() + 1);
anchor.setAnchorType(ClientAnchor.AnchorType.DONT_MOVE_AND_RESIZE);
drawing.createPicture(anchor, index);
@Override
public void merge(int firstRow, int lastRow, int firstCol, int lastCol) {
CellRangeAddress cra = new CellRangeAddress(firstRow, lastRow, firstCol, lastCol);
context.writeSheetHolder().getSheet().addMergedRegion(cra);
}
private CellData convert(WriteHolder currentWriteHolder, Class clazz, Cell cell, Object value,
ExcelContentProperty excelContentProperty) {
if (value instanceof CellData) {
return (CellData)value;
}
Converter converter = null;
if (excelContentProperty != null) {
converter = excelContentProperty.getConverter();
}
if (converter == null) {
converter = currentWriteHolder.converterMap().get(ConverterKeyBuild.buildKey(clazz));
}
if (converter == null) {
throw new ExcelDataConvertException(
"Can not find 'Converter' support class " + clazz.getSimpleName() + ".");
}
CellData cellData;
try {
cellData =
converter.convertToExcelData(value, excelContentProperty, currentWriteHolder.globalConfiguration());
} catch (Exception e) {
throw new ExcelDataConvertException("Convert data:" + value + " error,at row:" + cell.getRow().getRowNum(),
e);
}
return cellData;
@Override
public WriteContext writeContext() {
return context;
}
}
......@@ -79,6 +79,30 @@ public class ExcelWriterBuilder {
return this;
}
/**
* Use the default style.Default is true.
*
* @param useDefaultStyle
* @return
*/
public ExcelWriterBuilder useDefaultStyle(Boolean useDefaultStyle) {
writeWorkbook.setUseDefaultStyle(useDefaultStyle);
return this;
}
/**
* Whether the encryption.
* <p>
* WARRING:Encryption is when the entire file is read into memory, so it is very memory intensive.
*
* @param password
* @return
*/
public ExcelWriterBuilder password(String password) {
writeWorkbook.setPassword(password);
return this;
}
/**
* The default is all excel objects.if true , you can use {@link com.alibaba.excel.annotation.ExcelIgnore} ignore a
* field. if false , you must use {@link com.alibaba.excel.annotation.ExcelProperty} to use a filed.
......
......@@ -8,6 +8,7 @@ import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.exception.ExcelGenerateException;
import com.alibaba.excel.write.handler.WriteHandler;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
/**
* Build sheet
......@@ -73,6 +74,17 @@ public class ExcelWriterSheetBuilder {
return this;
}
/**
* Use the default style.Default is true.
*
* @param useDefaultStyle
* @return
*/
public ExcelWriterSheetBuilder useDefaultStyle(Boolean useDefaultStyle) {
writeSheet.setUseDefaultStyle(useDefaultStyle);
return this;
}
/**
* Custom type conversions override the default.
*
......@@ -135,6 +147,18 @@ public class ExcelWriterSheetBuilder {
excelWriter.finish();
}
public void doFill(Object data) {
doFill(data, null);
}
public void doFill(Object data, FillConfig fillConfig) {
if (excelWriter == null) {
throw new ExcelGenerateException("Must use 'EasyExcelFactory.write().sheet()' to call this method");
}
excelWriter.fill(data, fillConfig, build());
excelWriter.finish();
}
public ExcelWriterTableBuilder table() {
return table(null);
}
......
......@@ -78,6 +78,17 @@ public class ExcelWriterTableBuilder {
return this;
}
/**
* Use the default style.Default is true.
*
* @param useDefaultStyle
* @return
*/
public ExcelWriterTableBuilder useDefaultStyle(Boolean useDefaultStyle) {
writeTable.setUseDefaultStyle(useDefaultStyle);
return this;
}
/**
* Custom type conversions override the default.
*
......
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);
}
}
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();
}
}
}
package com.alibaba.excel.write.executor;
/**
* Excel write Executor
*
* @author Jiaju Zhuang
*/
public interface ExcelWriteExecutor {
}
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;
}
}
package com.alibaba.excel.write.handler;
import java.util.List;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
......@@ -16,32 +18,56 @@ import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
public interface CellWriteHandler extends WriteHandler {
/**
* called before create the cell
* Called before create the cell
*
* @param writeSheetHolder
* @param writeTableHolder
* Nullable
* Nullable.It is null without using table writes.
* @param row
* @param head
* Nullable.It is null in the case of fill data and without head.
* @param columnIndex
* @param relativeRowIndex
* Nullable.It is null in the case of fill data.
* @param isHead
* It will always be false when fill data.
*/
void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head,
int relativeRowIndex, boolean isHead);
Integer columnIndex, Integer relativeRowIndex, Boolean isHead);
/**
* Called after the cell is created
*
* @param writeSheetHolder
* @param writeTableHolder
* Nullable.It is null without using table writes.
* @param cell
* @param head
* Nullable.It is null in the case of fill data and without head.
* @param relativeRowIndex
* Nullable.It is null in the case of fill data.
* @param isHead
* It will always be false when fill data.
*/
void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head,
Integer relativeRowIndex, Boolean isHead);
/**
* called after the cell is created
* Called after all operations on the cell have been completed
*
* @param writeSheetHolder
* @param writeTableHolder
* Nullable
* Nullable.It is null without using table writes.
* @param cell
* @param head
* @param cellData
* Nullable.
* Nullable.It is null in the case of fill data and without head.
* @param cellDataList
* Nullable.It is null in the case of add header.There may be several when fill the data.
* @param relativeRowIndex
* Nullable.It is null in the case of fill data.
* @param isHead
* It will always be false when fill data.
*/
void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData,
Cell cell, Head head, int relativeRowIndex, boolean isHead);
void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead);
}
......@@ -21,16 +21,18 @@ public class DefaultWriteHandlerLoader {
*
* @return
*/
public static List<WriteHandler> loadDefaultHandler() {
public static List<WriteHandler> loadDefaultHandler(Boolean useDefaultStyle) {
List<WriteHandler> handlerList = new ArrayList<WriteHandler>();
WriteCellStyle headWriteCellStyle = new WriteCellStyle();
headWriteCellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
WriteFont headWriteFont = new WriteFont();
headWriteFont.setFontName("宋体");
headWriteFont.setFontHeightInPoints((short)14);
headWriteFont.setBold(true);
headWriteCellStyle.setWriteFont(headWriteFont);
handlerList.add(new HorizontalCellStyleStrategy(headWriteCellStyle, new ArrayList<WriteCellStyle>()));
if (useDefaultStyle) {
WriteCellStyle headWriteCellStyle = new WriteCellStyle();
headWriteCellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
WriteFont headWriteFont = new WriteFont();
headWriteFont.setFontName("宋体");
headWriteFont.setFontHeightInPoints((short)14);
headWriteFont.setBold(true);
headWriteCellStyle.setWriteFont(headWriteFont);
handlerList.add(new HorizontalCellStyleStrategy(headWriteCellStyle, new ArrayList<WriteCellStyle>()));
}
return handlerList;
}
......
......@@ -13,28 +13,47 @@ import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
public interface RowWriteHandler extends WriteHandler {
/**
* called before create the row
* Called before create the row
*
* @param writeSheetHolder
* @param writeTableHolder
* Nullable
* Nullable.It is null without using table writes.
* @param rowIndex
* @param relativeRowIndex
* Nullable.It is null in the case of fill data.
* @param isHead
* Nullable.It is null in the case of fill data.
*/
void beforeRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, int rowIndex,
int relativeRowIndex, boolean isHead);
void beforeRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Integer rowIndex,
Integer relativeRowIndex, Boolean isHead);
/**
* called after the row is created
* Called after the row is created
*
* @param writeSheetHolder
* @param writeTableHolder
* Nullable
* Nullable.It is null without using table writes.
* @param row
* @param relativeRowIndex
* Nullable.It is null in the case of fill data.
* @param isHead
* Nullable.It is null in the case of fill data.
*/
void afterRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,
int relativeRowIndex, boolean isHead);
Integer relativeRowIndex, Boolean isHead);
/**
* Called after all operations on the row have been completed.This method is not called when fill the data.
*
* @param writeSheetHolder
* @param writeTableHolder
* Nullable.It is null without using table writes.
* @param row
* @param relativeRowIndex
* Nullable.It is null in the case of fill data.
* @param isHead
* Nullable.It is null in the case of fill data.
*/
void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,
Integer relativeRowIndex, Boolean isHead);
}
......@@ -11,7 +11,7 @@ import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
public interface SheetWriteHandler extends WriteHandler {
/**
* called before create the sheet
* Called before create the sheet
*
* @param writeWorkbookHolder
* @param writeSheetHolder
......@@ -19,7 +19,7 @@ public interface SheetWriteHandler extends WriteHandler {
void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder);
/**
* called after the sheet is created
* Called after the sheet is created
*
* @param writeWorkbookHolder
* @param writeSheetHolder
......
......@@ -10,14 +10,21 @@ import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
public interface WorkbookWriteHandler extends WriteHandler {
/**
* called before create the sheet
* Called before create the workbook
*/
void beforeWorkbookCreate();
/**
* called after the sheet is created
* Called after the workbook is created
*
* @param writeWorkbookHolder
*/
void afterWorkbookCreate(WriteWorkbookHolder writeWorkbookHolder);
/**
* Called after all operations on the workbook have been completed
*
* @param writeWorkbookHolder
*/
void afterWorkbookDispose(WriteWorkbookHolder writeWorkbookHolder);
}
package com.alibaba.excel.write.merge;
import java.util.List;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
......@@ -18,13 +20,17 @@ import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
public abstract class AbstractMergeStrategy implements CellWriteHandler {
@Override
public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,
Head head, int relativeRowIndex, boolean isHead) {
Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {
}
@Override
public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData,
Cell cell, Head head, int relativeRowIndex, boolean isHead) {
public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell,
Head head, Integer relativeRowIndex, Boolean isHead) {}
@Override
public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
if (isHead) {
return;
}
......
......@@ -24,6 +24,10 @@ public class WriteBasicParameter extends BasicParameter {
* Custom type handler override the default
*/
private List<WriteHandler> customWriteHandlerList = new ArrayList<WriteHandler>();
/**
* Use the default style.Default is true.
*/
private Boolean useDefaultStyle;
public Integer getRelativeHeadRowIndex() {
return relativeHeadRowIndex;
......@@ -48,4 +52,12 @@ public class WriteBasicParameter extends BasicParameter {
public void setCustomWriteHandlerList(List<WriteHandler> customWriteHandlerList) {
this.customWriteHandlerList = customWriteHandlerList;
}
public Boolean getUseDefaultStyle() {
return useDefaultStyle;
}
public void setUseDefaultStyle(Boolean useDefaultStyle) {
this.useDefaultStyle = useDefaultStyle;
}
}
......@@ -43,13 +43,20 @@ public class WriteWorkbook extends WriteBasicParameter {
*/
private File templateFile;
/**
* Default true
* Default trueuseDefaultStyle
*/
private Boolean autoCloseStream;
/**
* Mandatory use 'inputStream' .Default is false
*/
private Boolean mandatoryUseInputStream;
/**
* Whether the encryption
* <p>
* WARRING:Encryption is when the entire file is read into memory, so it is very memory intensive.
*
*/
private String password;
/**
* The default is all excel objects.Default is true.
* <p>
......@@ -140,4 +147,12 @@ public class WriteWorkbook extends WriteBasicParameter {
public void setWriteHandler(com.alibaba.excel.event.WriteHandler writeHandler) {
this.writeHandler = writeHandler;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
......@@ -21,7 +21,6 @@ import com.alibaba.excel.metadata.AbstractHolder;
import com.alibaba.excel.metadata.Font;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.TableStyle;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.alibaba.excel.metadata.property.RowHeightProperty;
import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.excel.write.handler.CellWriteHandler;
......@@ -62,6 +61,10 @@ public abstract class AbstractWriteHolder extends AbstractHolder implements Writ
* Write handler for workbook
*/
private Map<Class<? extends WriteHandler>, List<WriteHandler>> writeHandlerMap;
/**
* Use the default style.Default is true.
*/
private Boolean useDefaultStyle;
public AbstractWriteHolder(WriteBasicParameter writeBasicParameter, AbstractWriteHolder parentAbstractWriteHolder,
Boolean convertAllFiled) {
......@@ -97,6 +100,16 @@ public abstract class AbstractWriteHolder extends AbstractHolder implements Writ
this.relativeHeadRowIndex = writeBasicParameter.getRelativeHeadRowIndex();
}
if (writeBasicParameter.getUseDefaultStyle() == null) {
if (parentAbstractWriteHolder == null) {
this.useDefaultStyle = Boolean.TRUE;
} else {
this.useDefaultStyle = parentAbstractWriteHolder.getUseDefaultStyle();
}
} else {
this.useDefaultStyle = writeBasicParameter.getUseDefaultStyle();
}
// Initialization property
this.excelWriteHeadProperty = new ExcelWriteHeadProperty(getClazz(), getHead(), convertAllFiled);
......@@ -118,7 +131,7 @@ public abstract class AbstractWriteHolder extends AbstractHolder implements Writ
if (parentAbstractWriteHolder != null) {
parentWriteHandlerMap = parentAbstractWriteHolder.getWriteHandlerMap();
} else {
handlerList.addAll(DefaultWriteHandlerLoader.loadDefaultHandler());
handlerList.addAll(DefaultWriteHandlerLoader.loadDefaultHandler(useDefaultStyle));
}
this.writeHandlerMap = sortAndClearUpHandler(handlerList, parentWriteHandlerMap);
......@@ -135,6 +148,7 @@ public abstract class AbstractWriteHolder extends AbstractHolder implements Writ
getConverterMap().put(ConverterKeyBuild.buildKey(converter.supportJavaTypeKey()), converter);
}
}
}
/**
......@@ -361,6 +375,14 @@ public abstract class AbstractWriteHolder extends AbstractHolder implements Writ
this.relativeHeadRowIndex = relativeHeadRowIndex;
}
public Boolean getUseDefaultStyle() {
return useDefaultStyle;
}
public void setUseDefaultStyle(Boolean useDefaultStyle) {
this.useDefaultStyle = useDefaultStyle;
}
@Override
public ExcelWriteHeadProperty excelWriteHeadProperty() {
return getExcelWriteHeadProperty();
......
......@@ -29,4 +29,6 @@ public class AnnotationData {
private Double number;
@ExcelIgnore
private String ignore;
private static final String staticFinal = "test";
private transient String transientString;
}
......@@ -48,6 +48,7 @@ public class AnnotationDataTest {
data.setDate(DateUtils.parseDate("2020-01-01 01:01:01"));
data.setNumber(99.99);
data.setIgnore("忽略");
data.setTransientString("忽略");
list.add(data);
return list;
}
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册