支持通过模板填充数据
@ -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`得到值为4K,400W/4K=1000 这代表已经`maxCacheActivateSize` 已经非常合理了。如果小于500 问题就非常大了,500到1000 应该都还行。
|
||||
|
BIN
img/readme/quickstart/fill/complexFill.png
Normal file
After Width: | Height: | Size: 5.0 KiB |
BIN
img/readme/quickstart/fill/complexFillTemplate.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
img/readme/quickstart/fill/complexFillWithTable.png
Normal file
After Width: | Height: | Size: 4.8 KiB |
BIN
img/readme/quickstart/fill/complexFillWithTableTemplate.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
img/readme/quickstart/fill/horizontalFill.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
img/readme/quickstart/fill/horizontalFillTemplate.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
img/readme/quickstart/fill/listFill.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
img/readme/quickstart/fill/listFillTemplate.png
Normal file
After Width: | Height: | Size: 811 B |
BIN
img/readme/quickstart/fill/simpleFill.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
img/readme/quickstart/fill/simpleFillTemplate.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
223
quickstart.md
@ -47,6 +47,14 @@ DEMO代码地址:[https://github.com/alibaba/easyexcel/blob/master/src/test/ja
|
||||
* [自定义拦截器(下拉,超链接等上面几点都不符合但是要对单元格进行操作的参照这个)](#customHandlerWrite)
|
||||
* [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" />最简单的填充
|
||||
##### 模板
|
||||

|
||||
##### 最终效果
|
||||

|
||||
##### <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" />填充列表
|
||||
##### 模板
|
||||

|
||||
##### 最终效果
|
||||

|
||||
##### <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" />复杂的填充
|
||||
##### 模板
|
||||

|
||||
##### 最终效果
|
||||

|
||||
##### <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" />数据量大的复杂填充
|
||||
##### 模板
|
||||

|
||||
##### 最终效果
|
||||

|
||||
##### <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" />横向的填充
|
||||
##### 模板
|
||||

|
||||
##### 最终效果
|
||||

|
||||
##### <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();
|
||||
}
|
||||
```
|
||||
|
||||
## 测试数据分析
|
||||

|
||||

|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@ public interface ExcelAnalyser {
|
||||
*
|
||||
* @return Excel file Executor
|
||||
*/
|
||||
ExcelExecutor excelExecutor();
|
||||
ExcelReadExecutor excelExecutor();
|
||||
|
||||
/**
|
||||
* get the analysis context.
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -0,0 +1,17 @@
|
||||
package com.alibaba.excel.enums;
|
||||
|
||||
/**
|
||||
* Direction of writing
|
||||
*
|
||||
* @author Jiaju Zhuang
|
||||
**/
|
||||
public enum WriteDirectionEnum {
|
||||
/**
|
||||
* Vertical write.
|
||||
*/
|
||||
VERTICAL,
|
||||
/**
|
||||
* Horizontal write.
|
||||
*/
|
||||
HORIZONTAL,;
|
||||
}
|
@ -5,7 +5,7 @@ package com.alibaba.excel.enums;
|
||||
*
|
||||
* @author Jiaju Zhuang
|
||||
**/
|
||||
public enum WriteLastRowType {
|
||||
public enum WriteLastRowTypeEnum {
|
||||
/**
|
||||
* Excel are created without templates ,And any data has been written;
|
||||
*/
|
@ -0,0 +1,17 @@
|
||||
package com.alibaba.excel.enums;
|
||||
|
||||
/**
|
||||
* Type of template to read when writing
|
||||
*
|
||||
* @author Jiaju Zhuang
|
||||
**/
|
||||
public enum WriteTemplateAnalysisCellTypeEnum {
|
||||
/**
|
||||
* Common field.
|
||||
*/
|
||||
COMMON,
|
||||
/**
|
||||
* A collection of fields.
|
||||
*/
|
||||
COLLECTION,;
|
||||
}
|
17
src/main/java/com/alibaba/excel/enums/WriteTypeEnum.java
Normal file
@ -0,0 +1,17 @@
|
||||
package com.alibaba.excel.enums;
|
||||
|
||||
/**
|
||||
* Enumeration of write methods
|
||||
*
|
||||
* @author Jiaju Zhuang
|
||||
**/
|
||||
public enum WriteTypeEnum {
|
||||
/**
|
||||
* Add.
|
||||
*/
|
||||
ADD,
|
||||
/**
|
||||
* Fill.
|
||||
*/
|
||||
FILL,;
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -6,10 +6,11 @@ package com.alibaba.excel.util;
|
||||
* @author jipengfei
|
||||
*/
|
||||
public class StringUtils {
|
||||
public static final String EMPTY = "";
|
||||
|
||||
private StringUtils() {}
|
||||
|
||||
public static boolean isEmpty(Object str) {
|
||||
return (str == null || "".equals(str));
|
||||
return (str == null || EMPTY.equals(str));
|
||||
}
|
||||
}
|
||||
|
@ -2,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) {
|
||||
|
196
src/main/java/com/alibaba/excel/util/WriteHandlerUtils.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package com.alibaba.excel.write.executor;
|
||||
|
||||
/**
|
||||
* Excel write Executor
|
||||
*
|
||||
* @author Jiaju Zhuang
|
||||
*/
|
||||
public interface ExcelWriteExecutor {
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -13,28 +13,47 @@ import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
|
||||
public interface RowWriteHandler extends WriteHandler {
|
||||
|
||||
/**
|
||||
* called before create the row
|
||||
* Called before create the row
|
||||
*
|
||||
* @param writeSheetHolder
|
||||
* @param writeTableHolder
|
||||
* Nullable
|
||||
* Nullable.It is null without using table writes.
|
||||
* @param rowIndex
|
||||
* @param relativeRowIndex
|
||||
* Nullable.It is null in the case of fill data.
|
||||
* @param isHead
|
||||
* Nullable.It is null in the case of fill data.
|
||||
*/
|
||||
void beforeRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, int rowIndex,
|
||||
int relativeRowIndex, boolean isHead);
|
||||
void beforeRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Integer rowIndex,
|
||||
Integer relativeRowIndex, Boolean isHead);
|
||||
|
||||
/**
|
||||
* called after the row is created
|
||||
* Called after the row is created
|
||||
*
|
||||
* @param writeSheetHolder
|
||||
* @param writeTableHolder
|
||||
* Nullable
|
||||
* Nullable.It is null without using table writes.
|
||||
* @param row
|
||||
* @param relativeRowIndex
|
||||
* Nullable.It is null in the case of fill data.
|
||||
* @param isHead
|
||||
* Nullable.It is null in the case of fill data.
|
||||
*/
|
||||
void afterRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,
|
||||
int relativeRowIndex, boolean isHead);
|
||||
Integer relativeRowIndex, Boolean isHead);
|
||||
|
||||
/**
|
||||
* Called after all operations on the row have been completed.This method is not called when fill the data.
|
||||
*
|
||||
* @param writeSheetHolder
|
||||
* @param writeTableHolder
|
||||
* Nullable.It is null without using table writes.
|
||||
* @param row
|
||||
* @param relativeRowIndex
|
||||
* Nullable.It is null in the case of fill data.
|
||||
* @param isHead
|
||||
* Nullable.It is null in the case of fill data.
|
||||
*/
|
||||
void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,
|
||||
Integer relativeRowIndex, Boolean isHead);
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
|
||||
public interface SheetWriteHandler extends WriteHandler {
|
||||
|
||||
/**
|
||||
* called before create the sheet
|
||||
* Called before create the sheet
|
||||
*
|
||||
* @param writeWorkbookHolder
|
||||
* @param writeSheetHolder
|
||||
@ -19,7 +19,7 @@ public interface SheetWriteHandler extends WriteHandler {
|
||||
void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder);
|
||||
|
||||
/**
|
||||
* called after the sheet is created
|
||||
* Called after the sheet is created
|
||||
*
|
||||
* @param writeWorkbookHolder
|
||||
* @param writeSheetHolder
|
||||
|
@ -10,14 +10,21 @@ import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
|
||||
public interface WorkbookWriteHandler extends WriteHandler {
|
||||
|
||||
/**
|
||||
* called before create the sheet
|
||||
* Called before create the workbook
|
||||
*/
|
||||
void beforeWorkbookCreate();
|
||||
|
||||
/**
|
||||
* called after the sheet is created
|
||||
* Called after the workbook is created
|
||||
*
|
||||
* @param writeWorkbookHolder
|
||||
*/
|
||||
void afterWorkbookCreate(WriteWorkbookHolder writeWorkbookHolder);
|
||||
|
||||
/**
|
||||
* Called after all operations on the workbook have been completed
|
||||
*
|
||||
* @param writeWorkbookHolder
|
||||
*/
|
||||
void afterWorkbookDispose(WriteWorkbookHolder writeWorkbookHolder);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,12 @@
|
||||
package com.alibaba.easyexcel.test.demo.fill;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author Jiaju Zhuang
|
||||
*/
|
||||
@Data
|
||||
public class FillData {
|
||||
private String name;
|
||||
private double number;
|
||||
}
|
181
src/test/java/com/alibaba/easyexcel/test/demo/fill/FillTest.java
Normal 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;
|
||||
}
|
||||
}
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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";
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
}
|
||||
|