支持通过模板填充数据

This commit is contained in:
Jiaju Zhuang 2019-10-09 19:46:45 +08:00
parent 46f35cecec
commit 5ae29e3605
76 changed files with 2169 additions and 812 deletions

View File

@ -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条的数据放在内存命中后直接返回没命中去读文件。所以不能设置太小太小了很难命中一直去读取文件太大了的话会占用过多的内存。
easyexcel在使用文件存储的时候会把共享字符串拆分成1000条一批然后放到文件存储。然后excel来读取共享字符串大概率是按照顺序的所以默认20M的1000条的数据放在内存命中后直接返回没命中去读文件。所以不能设置太小太小了很难命中一直去读取文件太大了的话会占用过多的内存。
### 如何判断 maxCacheActivateSize是否需要调整
开启debug日志会输出`Already put :4000000` 最后一次输出大概可以得出值为400W,然后看`Cache misses count:4001`得到值为4K400W/4K=1000 这代表已经`maxCacheActivateSize` 已经非常合理了。如果小于500 问题就非常大了500到1000 应该都还行。

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 811 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -47,6 +47,14 @@ DEMO代码地址[https://github.com/alibaba/easyexcel/blob/master/src/test/ja
* [自定义拦截器(下拉,超链接等上面几点都不符合但是要对单元格进行操作的参照这个)](#customHandlerWrite)
* [web中的写](#webWrite)
### 填充
DEMO代码地址[https://github.com/alibaba/easyexcel/blob/master/src/test/java/com/alibaba/easyexcel/test/demo/fill/FillTest.java](/src/test/java/com/alibaba/easyexcel/test/demo/fill/FillTest.java)
* [最简单的填充](#simpleFill)
* [填充列表](#listFill)
* [复杂的填充](#complexFill)
* [数据量大的复杂填充](#complexFillWithTable)
* [横向的填充](#horizontalFill)
## 读excel样例
### <span id="simpleRead" />最简单的读
##### <span id="simpleReadExcel" />excel示例
@ -1021,13 +1029,19 @@ public class CustomCellWriteHandler 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) {
// 这里可以对cell进行任何操作
LOGGER.info("第{}行,第{}列写入完成。", cell.getRowIndex(), cell.getColumnIndex());
if (isHead && cell.getColumnIndex() == 0) {
@ -1118,6 +1132,209 @@ DEMO代码地址[https://github.com/alibaba/easyexcel/blob/master/src/test/ja
EasyExcel.write(response.getOutputStream(), DownloadData.class).sheet("模板").doWrite(data());
}
```
## 填充excel样例
### <span id="simpleFill" />最简单的填充
##### 模板
![img](img/readme/quickstart/fill/simpleFillTemplate.png)
##### 最终效果
![img](img/readme/quickstart/fill/simpleFill.png)
##### <span id="simpleFillObject" />对象
```java
@Data
public class FillData {
private String name;
private double number;
}
```
##### 代码
```java
/**
* 最简单的填充
*/
@Test
public void simpleFill() {
// 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
String templateFileName =
TestFileUtil.getPath() + "demo" + File.separator + "fill" + File.separator + "simple.xlsx";
// 方案1 根据对象填充
String fileName = TestFileUtil.getPath() + "simpleFill" + System.currentTimeMillis() + ".xlsx";
// 这里 会填充到第一个sheet 然后文件流会自动关闭
FillData fillData = new FillData();
fillData.setName("张三");
fillData.setNumber(5.2);
EasyExcel.write(fileName).withTemplate(templateFileName).sheet().doFill(fillData);
// 方案2 根据Map填充
fileName = TestFileUtil.getPath() + "simpleFill" + System.currentTimeMillis() + ".xlsx";
// 这里 会填充到第一个sheet 然后文件流会自动关闭
Map<String, Object> map = new HashMap<String, Object>();
map.put("name", "张三");
map.put("number", 5.2);
EasyExcel.write(fileName).withTemplate(templateFileName).sheet().doFill(map);
}
```
### <span id="listFill" />填充列表
##### 模板
![img](img/readme/quickstart/fill/listFillTemplate.png)
##### 最终效果
![img](img/readme/quickstart/fill/listFill.png)
##### <span id="simpleFillObject" />对象
参照:[对象](#simpleFillObject)
##### 代码
```java
/**
* 填充列表
*/
@Test
public void listFill() {
// 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
// 填充list 的时候还要注意 模板中{.} 多了个点 表示list
String templateFileName =
TestFileUtil.getPath() + "demo" + File.separator + "fill" + File.separator + "list.xlsx";
// 方案1 一下子全部放到内存里面 并填充
String fileName = TestFileUtil.getPath() + "listFill" + System.currentTimeMillis() + ".xlsx";
// 这里 会填充到第一个sheet 然后文件流会自动关闭
EasyExcel.write(fileName).withTemplate(templateFileName).sheet().doFill(data());
// 方案2 分多次 填充 会使用文件缓存(省内存)
fileName = TestFileUtil.getPath() + "listFill" + System.currentTimeMillis() + ".xlsx";
ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFileName).build();
WriteSheet writeSheet = EasyExcel.writerSheet().build();
excelWriter.fill(data(), writeSheet);
excelWriter.fill(data(), writeSheet);
// 千万别忘记关闭流
excelWriter.finish();
}
```
### <span id="complexFill" />复杂的填充
##### 模板
![img](img/readme/quickstart/fill/complexFillTemplate.png)
##### 最终效果
![img](img/readme/quickstart/fill/complexFill.png)
##### <span id="simpleFillObject" />对象
参照:[对象](#simpleFillObject)
##### 代码
```java
/**
* 复杂的填充
*/
@Test
public void complexFill() {
// 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
// {} 代表普通变量 {.} 代表是list的变量
String templateFileName =
TestFileUtil.getPath() + "demo" + File.separator + "fill" + File.separator + "complex.xlsx";
String fileName = TestFileUtil.getPath() + "complexFill" + System.currentTimeMillis() + ".xlsx";
ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFileName).build();
WriteSheet writeSheet = EasyExcel.writerSheet().build();
// 这里注意 入参用了forceNewRow 代表在写入list的时候不管list下面有没有空行 都会创建一行,然后下面的数据往后移动。默认 是false会直接使用下一行如果没有则创建。
// forceNewRow 如果设置了true,有个缺点 就是他会把所有的数据都放到内存了,所以慎用
// 简单的说 如果你的模板有list,且list不是最后一行下面还有数据需要填充 就必须设置 forceNewRow=true 但是这个就会把所有数据放到内存 会很耗内存
// 如果数据量大 list不是最后一行 参照下一个
FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
excelWriter.fill(data(), fillConfig, writeSheet);
excelWriter.fill(data(), fillConfig, writeSheet);
Map<String, Object> map = new HashMap<String, Object>();
map.put("date", "2019年10月9日13:28:28");
map.put("total", 1000);
excelWriter.fill(map, writeSheet);
excelWriter.finish();
}
```
### <span id="complexFillWithTable" />数据量大的复杂填充
##### 模板
![img](img/readme/quickstart/fill/complexFillWithTableTemplate.png)
##### 最终效果
![img](img/readme/quickstart/fill/complexFillWithTable.png)
##### <span id="simpleFillObject" />对象
参照:[对象](#simpleFillObject)
##### 代码
```java
/**
* 数据量大的复杂填充
* <p>
* 这里的解决方案是 确保模板list为最后一行然后再拼接table.还有03版没救只能刚正面加内存。
*/
@Test
public void complexFillWithTable() {
// 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
// {} 代表普通变量 {.} 代表是list的变量
// 这里模板 删除了list以后的数据也就是统计的这一行
String templateFileName =
TestFileUtil.getPath() + "demo" + File.separator + "fill" + File.separator + "complexFillWithTable.xlsx";
String fileName = TestFileUtil.getPath() + "complexFillWithTable" + System.currentTimeMillis() + ".xlsx";
ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFileName).build();
WriteSheet writeSheet = EasyExcel.writerSheet().build();
// 直接写入数据
excelWriter.fill(data(), writeSheet);
excelWriter.fill(data(), writeSheet);
// 写入list之前的数据
Map<String, Object> map = new HashMap<String, Object>();
map.put("date", "2019年10月9日13:28:28");
excelWriter.fill(map, writeSheet);
// list 后面还有个统计 想办法手动写入
// 这里偷懒直接用list 也可以用对象
List<List<String>> totalListList = new ArrayList<List<String>>();
List<String> totalList = new ArrayList<String>();
totalListList.add(totalList);
totalList.add(null);
totalList.add(null);
totalList.add(null);
// 第四列
totalList.add("统计:1000");
// 这里是write 别和fill 搞错了
excelWriter.write(totalListList, writeSheet);
excelWriter.finish();
// 总体上写法比较复杂 但是也没有想到好的版本 异步的去写入excel 不支持行的删除和移动,也不支持备注这种的写入,所以也排除了可以
// 新建一个 然后一点点复制过来的方案最后导致list需要新增行的时候后面的列的数据没法后移后续会继续想想解决方案
}
```
### <span id="horizontalFill" />横向的填充
##### 模板
![img](img/readme/quickstart/fill/horizontalFillTemplate.png)
##### 最终效果
![img](img/readme/quickstart/fill/horizontalFill.png)
##### <span id="simpleFillObject" />对象
参照:[对象](#simpleFillObject)
##### 代码
```java
/**
* 横向的填充
*/
@Test
public void horizontalFill() {
// 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
// {} 代表普通变量 {.} 代表是list的变量
String templateFileName =
TestFileUtil.getPath() + "demo" + File.separator + "fill" + File.separator + "horizontal.xlsx";
String fileName = TestFileUtil.getPath() + "horizontalFill" + System.currentTimeMillis() + ".xlsx";
ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFileName).build();
WriteSheet writeSheet = EasyExcel.writerSheet().build();
FillConfig fillConfig = FillConfig.builder().direction(WriteDirectionEnum.HORIZONTAL).build();
excelWriter.fill(data(), fillConfig, writeSheet);
excelWriter.fill(data(), fillConfig, writeSheet);
Map<String, Object> map = new HashMap<String, Object>();
map.put("date", "2019年10月9日13:28:28");
excelWriter.fill(map, writeSheet);
// 别忘记关闭流
excelWriter.finish();
}
```
## 测试数据分析
![POI usermodel PK easyexcel(Excel 2003).png](http://ata2-img.cn-hangzhou.img-pub.aliyun-inc.com/02c4bfbbab99a649788523d04f84a42f.png)
![POI usermodel PK easyexcel(Excel 2007).png](http://ata2-img.cn-hangzhou.img-pub.aliyun-inc.com/f6a8a19ec959f0eb564e652de523fc9e.png)

View File

@ -9,7 +9,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;
@ -149,12 +149,12 @@ public class ExcelReader {
* Parse all sheet content by default
*/
public void read() {
ExcelExecutor excelExecutor = excelAnalyser.excelExecutor();
if (excelExecutor.sheetList().isEmpty()) {
ExcelReadExecutor excelReadExecutor = excelAnalyser.excelExecutor();
if (excelReadExecutor.sheetList().isEmpty()) {
LOGGER.warn("Excel doesn't have any sheets.");
return;
}
for (ReadSheet readSheet : excelExecutor.sheetList()) {
for (ReadSheet readSheet : excelReadExecutor.sheetList()) {
read(readSheet);
}
}
@ -225,7 +225,7 @@ public class ExcelReader {
*
* @return
*/
public ExcelExecutor excelExecutor() {
public ExcelReadExecutor excelExecutor() {
checkFinished();
return excelAnalyser.excelExecutor();
}

View File

@ -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
@ -164,7 +165,19 @@ public class ExcelWriter {
* @return
*/
public ExcelWriter fill(Object data, WriteSheet writeSheet) {
excelBuilder.fill(data, writeSheet);
return fill(data, null, writeSheet);
}
/**
* Fill value to a sheet
*
* @param data
* @param fillConfig
* @param writeSheet
* @return
*/
public ExcelWriter fill(Object data, FillConfig fillConfig, WriteSheet writeSheet) {
excelBuilder.fill(data, fillConfig, writeSheet);
return this;
}

View File

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

View File

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

View File

@ -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

View File

@ -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,7 +56,7 @@ 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;

View File

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

View File

@ -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,12 @@ public interface AnalysisContext {
/**
* Select the current table
*
* @param excelExecutor
* @param excelReadExecutor
* Excel file Executor
* @param readSheet
* sheet to read
*/
void currentSheet(ExcelExecutor excelExecutor, ReadSheet readSheet);
void currentSheet(ExcelReadExecutor excelReadExecutor, ReadSheet readSheet);
/**
* All information about the workbook you are currently working on

View File

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

View File

@ -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

View File

@ -1,7 +1,6 @@
package com.alibaba.excel.context;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;
import org.apache.poi.ss.usermodel.Cell;
@ -10,18 +9,15 @@ import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFSheet;
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;
@ -65,42 +61,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;
@ -113,7 +85,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");
}
@ -137,38 +109,10 @@ 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);
WriteHandlerUtils.afterSheetCreate(this);
}
private void initCurrentSheetHolder(WriteSheet writeSheet) {
@ -181,29 +125,24 @@ public class WriteContextImpl implements WriteContext {
}
}
private void initSheet() {
try {
if (writeWorkbookHolder.getXssfWorkbook() != null) {
writeSheetHolder
.setXssfSheet(writeWorkbookHolder.getXssfWorkbook().getSheetAt(writeSheetHolder.getSheetNo()));
}
} catch (Exception e) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Can not find XSSFSheet:{}.", writeSheetHolder.getSheetNo());
}
}
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());
if (WriteTypeEnum.ADD.equals(writeType)) {
// Initialization head
initHead(writeSheetHolder.excelWriteHeadProperty());
}
}
public void initHead(ExcelWriteHeadProperty excelWriteHeadProperty) {
@ -216,42 +155,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,
@ -262,38 +172,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);
}
}
@ -352,10 +237,10 @@ public class WriteContextImpl implements WriteContext {
@Override
public void finish() {
WriteHandlerUtils.afterWorkbookDispose(this);
if (writeWorkbookHolder == null) {
return;
}
try {
writeWorkbookHolder.getWorkbook().write(writeWorkbookHolder.getOutputStream());
writeWorkbookHolder.getWorkbook().close();
@ -370,13 +255,6 @@ public class WriteContextImpl implements WriteContext {
} catch (Throwable t) {
throwCanNotCloseIo(t);
}
try {
if (writeWorkbookHolder.getTempTemplateInputStream() != null) {
writeWorkbookHolder.getTempTemplateInputStream().close();
}
} catch (Throwable t) {
throwCanNotCloseIo(t);
}
try {
if (writeWorkbookHolder.getAutoCloseStream() && writeWorkbookHolder.getOutputStream() != null) {
writeWorkbookHolder.getOutputStream().close();
@ -385,9 +263,8 @@ public class WriteContextImpl implements WriteContext {
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);

View File

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

View File

@ -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;
*/

View File

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

View File

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

View File

@ -52,6 +52,10 @@ public class ExcelHeadProperty {
* Configuration column information
*/
private Map<Integer, ExcelContentProperty> contentPropertyMap;
/**
* Configuration column information
*/
private Map<String, ExcelContentProperty> fieldNameContentPropertyMap;
/**
* Fields ignored
*/
@ -61,6 +65,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;
@ -78,10 +83,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() {
@ -190,6 +191,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() {
@ -236,6 +238,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;
}

View File

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

View File

@ -2,6 +2,7 @@ package com.alibaba.excel.util;
import java.io.IOException;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
@ -22,36 +23,31 @@ 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.getTempTemplateInputStream() != null) {
XSSFWorkbook xssfWorkbook = new XSSFWorkbook(writeWorkbookHolder.getTempTemplateInputStream());
writeWorkbookHolder.setCachedWorkbook(xssfWorkbook);
writeWorkbookHolder.setWorkbook(new SXSSFWorkbook(xssfWorkbook, ROW_ACCESS_WINDOW_SIZE));
return;
}
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) {
writeWorkbookHolder.setXssfWorkbook(xssfWorkbook);
for (int i = 0; i < xssfWorkbook.getNumberOfSheets(); i++) {
writeWorkbookHolder.getTemplateLastRowMap().put(i, xssfWorkbook.getSheetAt(i).getLastRowNum());
}
return new SXSSFWorkbook(xssfWorkbook);
}
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()));
}
return new HSSFWorkbook();
writeWorkbookHolder.setCachedWorkbook(hssfWorkbook);
writeWorkbookHolder.setWorkbook(hssfWorkbook);
}
public static Sheet createSheet(Workbook workbook, String sheetName) {

View File

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

View File

@ -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
@ -40,9 +41,10 @@ public interface ExcelBuilder {
* WorkBook fill value
*
* @param data
* @param fillConfig
* @param writeSheet
*/
void fill(Object data, WriteSheet writeSheet);
void fill(Object data, FillConfig fillConfig, WriteSheet writeSheet);
/**
* Creates new cell range. Indexes are zero-based.

View File

@ -1,63 +1,29 @@
package com.alibaba.excel.write;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.ss.usermodel.Drawing;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFSheet;
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.CellDataTypeEnum;
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.fill.AnalysisCell;
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
*/
public class ExcelBuilderImpl implements ExcelBuilder {
private static final String FILL_PREFIX = "${";
private static final String FILL_SUFFIX = "}";
private static final Pattern FILL_PATTERN = Pattern.compile("\\$\\{[^}]+}");
private WriteContext context;
private ExcelWriteFillExecutor excelWriteFillExecutor;
private ExcelWriteAddExecutor excelWriteAddExecutor;
public ExcelBuilderImpl(WriteWorkbook writeWorkbook) {
try {
@ -73,23 +39,6 @@ public class ExcelBuilderImpl implements ExcelBuilder {
}
}
private void doAddContent(List data) {
if (CollectionUtils.isEmpty(data)) {
return;
}
WriteSheetHolder writeSheetHolder = context.writeSheetHolder();
int newRowIndex = writeSheetHolder.getNewRowIndexAndStartDoWrite();
if (writeSheetHolder.isNew() && !writeSheetHolder.getExcelWriteHeadProperty().hasHead()) {
newRowIndex += context.currentWriteHolder().relativeHeadRowIndex();
}
// BeanMap is out of order,so use fieldList
List<Field> fieldList = new ArrayList<Field>();
for (int relativeRowIndex = 0; relativeRowIndex < data.size(); relativeRowIndex++) {
int n = relativeRowIndex + newRowIndex;
addOneRowOfDataToExcel(data.get(relativeRowIndex), n, relativeRowIndex, fieldList);
}
}
@Override
public void addContent(List data, WriteSheet writeSheet) {
addContent(data, writeSheet, null);
@ -98,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;
@ -111,14 +66,19 @@ public class ExcelBuilderImpl implements ExcelBuilder {
}
@Override
public void fill(Object data, WriteSheet writeSheet) {
public void fill(Object data, FillConfig fillConfig, WriteSheet writeSheet) {
try {
if (context.writeWorkbookHolder().getTemplateFile() == null
&& context.writeWorkbookHolder().getTemplateInputStream() == null) {
if (data == null) {
return;
}
if (context.writeWorkbookHolder().getTempTemplateInputStream() == null) {
throw new ExcelGenerateException("Calling the 'fill' method must use a template.");
}
context.currentSheet(writeSheet);
doFill(data);
context.currentSheet(writeSheet, WriteTypeEnum.FILL);
if (excelWriteFillExecutor == null) {
excelWriteFillExecutor = new ExcelWriteFillExecutor(context);
}
excelWriteFillExecutor.fill(data, fillConfig);
} catch (RuntimeException e) {
finish();
throw e;
@ -128,73 +88,6 @@ public class ExcelBuilderImpl implements ExcelBuilder {
}
}
private void doFill(Object data) {
WriteSheetHolder writeSheetHolder = context.writeSheetHolder();
XSSFSheet sheet = writeSheetHolder.getXssfSheet();
Map<Integer, Integer> templateLastRowMap = context.writeWorkbookHolder().getTemplateLastRowMap();
if (sheet == null) {
throw new ExcelGenerateException(
"The corresponding table cannot be found,sheetNo:" + writeSheetHolder.getSheetNo());
}
List<AnalysisCell> analysisCellList = new ArrayList<AnalysisCell>();
for (int i = 0; i <= sheet.getLastRowNum(); i++) {
Row row = sheet.getRow(i);
for (int j = 0; j < row.getLastCellNum(); j++) {
Cell cell = row.getCell(j);
String value = cell.getStringCellValue();
if (FILL_PATTERN.matcher(value).matches()) {
AnalysisCell analysisCell = new AnalysisCell();
analysisCell.setRowIndex(i);
analysisCell.setColumnIndex(j);
List<String> variableList = new ArrayList<String>();
analysisCell.setVariableList(variableList);
boolean matches = true;
int index = 0;
while (matches) {
Matcher matcher = FILL_PATTERN.matcher(value);
String variable = value.substring(matcher.regionStart() + 2, matcher.regionEnd() - 1);
variableList.add(variable);
value = matcher.replaceFirst("{" + index++ + "}");
matches = FILL_PATTERN.matcher(value).matches();
analysisCellList.add(analysisCell);
}
}
}
}
if (data instanceof Collection) {
} else if (data instanceof Map) {
} else {
}
BeanMap beanMap = BeanMap.create(data);
for (AnalysisCell analysisCell : analysisCellList) {
Cell cell = sheet.getRow(analysisCell.getRowIndex()).getCell(analysisCell.getColumnIndex());
if (analysisCell.getVariableList().size() == 1) {
Object value = beanMap.get(analysisCell.getVariableList().get(0));
if (value == null) {
continue;
}
converterAndSet(writeSheetHolder, value.getClass(), cell, value, null);
} else {
List<String> fileDataStringList = new ArrayList<String>();
for (String variable : analysisCell.getVariableList()) {
Object value = beanMap.get(variable);
CellData cellData = convert(writeSheetHolder, String.class, cell, value, null);
String fillDataString = cellData.getStringValue();
if (fillDataString == null) {
fillDataString = "";
}
fileDataStringList.add(fillDataString);
}
cell.setCellValue(String.format(analysisCell.getPrepareData(), fileDataStringList));
}
}
}
@Override
public void finish() {
if (context != null) {
@ -212,286 +105,4 @@ public class ExcelBuilderImpl implements ExcelBuilder {
public WriteContext writeContext() {
return context;
}
private void addOneRowOfDataToExcel(Object oneRowData, int n, int relativeRowIndex, List<Field> fieldList) {
beforeRowCreate(n, relativeRowIndex);
Row row = WorkBookUtil.createRow(context.writeSheetHolder().getSheet(), n);
afterRowCreate(row, relativeRowIndex);
if (oneRowData instanceof List) {
addBasicTypeToExcel((List)oneRowData, row, relativeRowIndex);
} else {
addJavaObjectToExcel(oneRowData, row, relativeRowIndex, fieldList);
}
}
private void beforeRowCreate(int rowIndex, int relativeRowIndex) {
List<WriteHandler> handlerList = context.currentWriteHolder().writeHandlerMap().get(RowWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof RowWriteHandler) {
((RowWriteHandler)writeHandler).beforeRowCreate(context.writeSheetHolder(), context.writeTableHolder(),
rowIndex, relativeRowIndex, false);
}
}
}
private void afterRowCreate(Row row, int relativeRowIndex) {
List<WriteHandler> handlerList = context.currentWriteHolder().writeHandlerMap().get(RowWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof RowWriteHandler) {
((RowWriteHandler)writeHandler).afterRowCreate(context.writeSheetHolder(), context.writeTableHolder(),
row, relativeRowIndex, false);
}
}
if (null != context.writeWorkbookHolder().getWriteWorkbook().getWriteHandler()) {
context.writeWorkbookHolder().getWriteWorkbook().getWriteHandler().row(row.getRowNum(), row);
}
}
private void addBasicTypeToExcel(List<Object> oneRowData, Row row, int relativeRowIndex) {
if (CollectionUtils.isEmpty(oneRowData)) {
return;
}
Map<Integer, Head> headMap = context.currentWriteHolder().excelWriteHeadProperty().getHeadMap();
int dataIndex = 0;
int cellIndex = 0;
for (Map.Entry<Integer, Head> entry : headMap.entrySet()) {
if (dataIndex >= oneRowData.size()) {
return;
}
cellIndex = entry.getKey();
Head head = entry.getValue();
doAddBasicTypeToExcel(oneRowData, head, row, relativeRowIndex, dataIndex++, cellIndex);
}
// Finish
if (dataIndex >= oneRowData.size()) {
return;
}
if (cellIndex != 0) {
cellIndex++;
}
int size = oneRowData.size() - dataIndex;
for (int i = 0; i < size; i++) {
doAddBasicTypeToExcel(oneRowData, null, row, relativeRowIndex, dataIndex++, cellIndex++);
}
}
private void doAddBasicTypeToExcel(List<Object> oneRowData, Head head, Row row, int relativeRowIndex, int dataIndex,
int cellIndex) {
beforeCellCreate(row, head, relativeRowIndex);
Cell cell = WorkBookUtil.createCell(row, cellIndex);
Object value = oneRowData.get(dataIndex);
CellData cellData =
converterAndSet(context.currentWriteHolder(), value == null ? null : value.getClass(), cell, value, null);
afterCellCreate(head, cellData, cell, relativeRowIndex);
}
private void addJavaObjectToExcel(Object oneRowData, Row row, int relativeRowIndex, List<Field> fieldList) {
WriteHolder currentWriteHolder = context.currentWriteHolder();
BeanMap beanMap = BeanMap.create(oneRowData);
Set<String> beanMapHandledSet = new HashSet<String>();
int cellIndex = 0;
// If it's a class it needs to be cast by type
if (HeadKindEnum.CLASS.equals(context.currentWriteHolder().excelWriteHeadProperty().getHeadKind())) {
Map<Integer, Head> headMap = context.currentWriteHolder().excelWriteHeadProperty().getHeadMap();
Map<Integer, ExcelContentProperty> contentPropertyMap =
context.currentWriteHolder().excelWriteHeadProperty().getContentPropertyMap();
for (Map.Entry<Integer, ExcelContentProperty> entry : contentPropertyMap.entrySet()) {
cellIndex = entry.getKey();
ExcelContentProperty excelContentProperty = entry.getValue();
String name = excelContentProperty.getField().getName();
if (!beanMap.containsKey(name)) {
continue;
}
Head head = headMap.get(cellIndex);
beforeCellCreate(row, head, relativeRowIndex);
Cell cell = WorkBookUtil.createCell(row, cellIndex);
Object value = beanMap.get(name);
CellData cellData = converterAndSet(currentWriteHolder, excelContentProperty.getField().getType(), cell,
value, excelContentProperty);
afterCellCreate(head, cellData, cell, relativeRowIndex);
beanMapHandledSet.add(name);
}
}
// Finish
if (beanMapHandledSet.size() == beanMap.size()) {
return;
}
if (cellIndex != 0) {
cellIndex++;
}
Map<String, Field> ignoreMap = context.currentWriteHolder().excelWriteHeadProperty().getIgnoreMap();
initFieldList(oneRowData.getClass(), fieldList);
for (Field field : fieldList) {
String filedName = field.getName();
boolean uselessData = !beanMap.containsKey(filedName) || beanMapHandledSet.contains(filedName)
|| ignoreMap.containsKey(filedName);
if (uselessData) {
continue;
}
Object value = beanMap.get(filedName);
if (value == null) {
continue;
}
beforeCellCreate(row, null, relativeRowIndex);
Cell cell = WorkBookUtil.createCell(row, cellIndex++);
CellData cellData = converterAndSet(currentWriteHolder, value.getClass(), cell, value, null);
afterCellCreate(null, cellData, cell, relativeRowIndex);
}
}
private void initFieldList(Class clazz, List<Field> fieldList) {
if (!fieldList.isEmpty()) {
return;
}
Class tempClass = clazz;
while (tempClass != null) {
if (tempClass != BaseRowModel.class) {
Collections.addAll(fieldList, tempClass.getDeclaredFields());
}
tempClass = tempClass.getSuperclass();
}
}
private void beforeCellCreate(Row row, Head head, int relativeRowIndex) {
List<WriteHandler> handlerList = context.currentWriteHolder().writeHandlerMap().get(CellWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof CellWriteHandler) {
((CellWriteHandler)writeHandler).beforeCellCreate(context.writeSheetHolder(),
context.writeTableHolder(), row, head, relativeRowIndex, false);
}
}
}
private void afterCellCreate(Head head, CellData cellData, Cell cell, int relativeRowIndex) {
List<WriteHandler> handlerList = context.currentWriteHolder().writeHandlerMap().get(CellWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof CellWriteHandler) {
((CellWriteHandler)writeHandler).afterCellCreate(context.writeSheetHolder(), context.writeTableHolder(),
cellData, cell, head, relativeRowIndex, false);
}
}
if (null != context.writeWorkbookHolder().getWriteWorkbook().getWriteHandler()) {
context.writeWorkbookHolder().getWriteWorkbook().getWriteHandler().cell(cell.getRowIndex(), cell);
}
}
private CellData converterAndSet(WriteHolder currentWriteHolder, Class clazz, Cell cell, Object value,
ExcelContentProperty excelContentProperty) {
if (value == null) {
return new CellData();
}
if (value instanceof String && currentWriteHolder.globalConfiguration().getAutoTrim()) {
value = ((String)value).trim();
}
CellData cellData = convert(currentWriteHolder, clazz, cell, value, excelContentProperty);
if (cellData.getFormula() != null && cellData.getFormula()) {
cell.setCellFormula(cellData.getFormulaValue());
}
switch (cellData.getType()) {
case STRING:
cell.setCellValue(cellData.getStringValue());
return cellData;
case BOOLEAN:
cell.setCellValue(cellData.getBooleanValue());
return cellData;
case NUMBER:
cell.setCellValue(cellData.getNumberValue().doubleValue());
return cellData;
case IMAGE:
setImageValue(cellData, cell);
return cellData;
case EMPTY:
return cellData;
default:
throw new ExcelDataConvertException("Not supported data:" + value + " return type:" + cell.getCellType()
+ "at row:" + cell.getRow().getRowNum());
}
}
private void setImageValue(CellData cellData, Cell cell) {
Sheet sheet = cell.getSheet();
int index = sheet.getWorkbook().addPicture(cellData.getImageValue(), HSSFWorkbook.PICTURE_TYPE_PNG);
Drawing drawing = sheet.getDrawingPatriarch();
if (drawing == null) {
drawing = sheet.createDrawingPatriarch();
}
CreationHelper helper = sheet.getWorkbook().getCreationHelper();
ClientAnchor anchor = helper.createClientAnchor();
anchor.setDx1(0);
anchor.setDx2(0);
anchor.setDy1(0);
anchor.setDy2(0);
anchor.setCol1(cell.getColumnIndex());
anchor.setCol2(cell.getColumnIndex() + 1);
anchor.setRow1(cell.getRowIndex());
anchor.setRow2(cell.getRowIndex() + 1);
anchor.setAnchorType(ClientAnchor.AnchorType.DONT_MOVE_AND_RESIZE);
drawing.createPicture(anchor, index);
}
private CellData convert(WriteHolder currentWriteHolder, Class clazz, Cell cell, Object value,
ExcelContentProperty excelContentProperty) {
// This means that the user has defined the data.
if (value instanceof CellData) {
CellData cellDataValue = (CellData)value;
if (cellDataValue.getType() != null) {
return cellDataValue;
} else {
if (cellDataValue.getData() == null) {
cellDataValue.setType(CellDataTypeEnum.EMPTY);
return cellDataValue;
}
}
CellData cellDataReturn = doConvert(currentWriteHolder, cellDataValue.getData().getClass(), cell,
cellDataValue.getData(), excelContentProperty);
// The formula information is subject to user input
if (cellDataValue.getFormula() != null) {
cellDataReturn.setFormula(cellDataValue.getFormula());
cellDataReturn.setFormulaValue(cellDataValue.getFormulaValue());
}
return cellDataReturn;
}
return doConvert(currentWriteHolder, clazz, cell, value, excelContentProperty);
}
private CellData doConvert(WriteHolder currentWriteHolder, Class clazz, Cell cell, Object value,
ExcelContentProperty excelContentProperty) {
Converter converter = null;
if (excelContentProperty != null) {
converter = excelContentProperty.getConverter();
}
if (converter == null) {
converter = currentWriteHolder.converterMap().get(ConverterKeyBuild.buildKey(clazz));
}
if (converter == null) {
throw new ExcelDataConvertException(
"Can not find 'Converter' support class " + clazz.getSimpleName() + ".");
}
CellData cellData;
try {
cellData =
converter.convertToExcelData(value, excelContentProperty, currentWriteHolder.globalConfiguration());
} catch (Exception e) {
throw new ExcelDataConvertException("Convert data:" + value + " error,at row:" + cell.getRow().getRowNum(),
e);
}
if (cellData == null || cellData.getType() == null) {
throw new ExcelDataConvertException(
"Convert data:" + value + " return null,at row:" + cell.getRow().getRowNum());
}
return cellData;
}
}

View File

@ -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
@ -136,10 +137,14 @@ public class ExcelWriterSheetBuilder {
}
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, build());
excelWriter.fill(data, fillConfig, build());
excelWriter.finish();
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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

View File

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

View File

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

View File

@ -2,6 +2,8 @@ package com.alibaba.excel.write.metadata.fill;
import java.util.List;
import com.alibaba.excel.enums.WriteTemplateAnalysisCellTypeEnum;
/**
* Read the cells of the template while populating the data.
*
@ -11,7 +13,9 @@ public class AnalysisCell {
private int columnIndex;
private int rowIndex;
private List<String> variableList;
private String prepareData;
private List<String> prepareDataList;
private Boolean onlyOneVariable;
private WriteTemplateAnalysisCellTypeEnum cellType;
public int getColumnIndex() {
return columnIndex;
@ -37,11 +41,49 @@ public class AnalysisCell {
this.variableList = variableList;
}
public String getPrepareData() {
return prepareData;
public List<String> getPrepareDataList() {
return prepareDataList;
}
public void setPrepareData(String prepareData) {
this.prepareData = prepareData;
public void setPrepareDataList(List<String> prepareDataList) {
this.prepareDataList = prepareDataList;
}
public Boolean getOnlyOneVariable() {
return onlyOneVariable;
}
public void setOnlyOneVariable(Boolean onlyOneVariable) {
this.onlyOneVariable = onlyOneVariable;
}
public WriteTemplateAnalysisCellTypeEnum getCellType() {
return cellType;
}
public void setCellType(WriteTemplateAnalysisCellTypeEnum cellType) {
this.cellType = cellType;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
AnalysisCell that = (AnalysisCell)o;
if (columnIndex != that.columnIndex) {
return false;
}
return rowIndex == that.rowIndex;
}
@Override
public int hashCode() {
int result = columnIndex;
result = 31 * result + rowIndex;
return result;
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,5 +1,7 @@
package com.alibaba.easyexcel.test.demo.write;
import java.util.List;
import org.apache.poi.common.usermodel.HyperlinkType;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CreationHelper;
@ -25,13 +27,19 @@ public class CustomCellWriteHandler 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) {
// 这里可以对cell进行任何操作
LOGGER.info("第{}行,第{}列写入完成。", cell.getRowIndex(), cell.getColumnIndex());
if (isHead && cell.getColumnIndex() == 0) {

View File

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

View File

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

View File

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

View File

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

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.