diff --git a/docs/LARGEREAD.md b/docs/LARGEREAD.md index 512596d..8614727 100644 --- a/docs/LARGEREAD.md +++ b/docs/LARGEREAD.md @@ -9,6 +9,7 @@ ```java // 强制使用内存存储,这样大概一个20M的excel使用150M(很多临时对象,所以100M会一直GC)的内存 // 这样效率会比上面的复杂的策略高很多 + // 这里再说明下 就是加了个readCache(new MapCache()) 参数而已,其他的参照其他demo写 这里没有写全 EasyExcel.read().readCache(new MapCache()); ``` ### 对并发要求较高,而且都是经常有超级大文件 @@ -16,7 +17,10 @@ // 第一个参数的意思是 多少M共享字符串以后 采用文件存储 单位MB 默认5M // 第二个参数 文件存储时,内存存放多少M缓存数据 默认20M // 比如 你希望用100M内存(这里说的是解析过程中的永久占用,临时对象不算)来解析excel,前面算过了 大概是 20M+90M 所以设置参数为:20 和 90 + // 这里再说明下 就是加了个readCacheSelector(new SimpleReadCacheSelector(5, 20))参数而已,其他的参照其他demo写 这里没有写全 EasyExcel.read().readCacheSelector(new SimpleReadCacheSelector(5, 20)); ``` ### 关于maxCacheActivateSize 也就是前面第二个参数的详细说明 -easyexcel在使用文件存储的时候,会把共享字符串拆分成1000条一批,然后放到文件存储。然后excel来读取共享字符串大概率是按照顺序的,所以默认20M的1000条的数据放在内存,命中后直接返回,没命中去读文件。所以不能设置太小,太小了,很难命中,一直去读取文件,太大了的话会占用过多的内存。 \ No newline at end of file +easyexcel在使用文件存储的时候,会把共享字符串拆分成1000条一批,然后放到文件存储。然后excel来读取共享字符串大概率是按照顺序的,所以默认20M的1000条的数据放在内存,命中后直接返回,没命中去读文件。所以不能设置太小,太小了,很难命中,一直去读取文件,太大了的话会占用过多的内存。 +### 如何判断 maxCacheActivateSize是否需要调整 +开启debug日志会输出`Already put :4000000` 最后一次输出,大概可以得出值为400W,然后看`Cache misses count:4001`得到值为4K,400W/4K=1000 这代表已经`maxCacheActivateSize` 已经非常合理了。如果小于500 问题就非常大了,500到1000 应该都还行。 diff --git a/img/readme/quickstart/fill/complexFill.png b/img/readme/quickstart/fill/complexFill.png new file mode 100644 index 0000000..d37bb0f Binary files /dev/null and b/img/readme/quickstart/fill/complexFill.png differ diff --git a/img/readme/quickstart/fill/complexFillTemplate.png b/img/readme/quickstart/fill/complexFillTemplate.png new file mode 100644 index 0000000..14e26b9 Binary files /dev/null and b/img/readme/quickstart/fill/complexFillTemplate.png differ diff --git a/img/readme/quickstart/fill/complexFillWithTable.png b/img/readme/quickstart/fill/complexFillWithTable.png new file mode 100644 index 0000000..c107520 Binary files /dev/null and b/img/readme/quickstart/fill/complexFillWithTable.png differ diff --git a/img/readme/quickstart/fill/complexFillWithTableTemplate.png b/img/readme/quickstart/fill/complexFillWithTableTemplate.png new file mode 100644 index 0000000..902cd0d Binary files /dev/null and b/img/readme/quickstart/fill/complexFillWithTableTemplate.png differ diff --git a/img/readme/quickstart/fill/horizontalFill.png b/img/readme/quickstart/fill/horizontalFill.png new file mode 100644 index 0000000..10f90cd Binary files /dev/null and b/img/readme/quickstart/fill/horizontalFill.png differ diff --git a/img/readme/quickstart/fill/horizontalFillTemplate.png b/img/readme/quickstart/fill/horizontalFillTemplate.png new file mode 100644 index 0000000..462b86e Binary files /dev/null and b/img/readme/quickstart/fill/horizontalFillTemplate.png differ diff --git a/img/readme/quickstart/fill/listFill.png b/img/readme/quickstart/fill/listFill.png new file mode 100644 index 0000000..3baca5a Binary files /dev/null and b/img/readme/quickstart/fill/listFill.png differ diff --git a/img/readme/quickstart/fill/listFillTemplate.png b/img/readme/quickstart/fill/listFillTemplate.png new file mode 100644 index 0000000..010c8c1 Binary files /dev/null and b/img/readme/quickstart/fill/listFillTemplate.png differ diff --git a/img/readme/quickstart/fill/simpleFill.png b/img/readme/quickstart/fill/simpleFill.png new file mode 100644 index 0000000..4f57562 Binary files /dev/null and b/img/readme/quickstart/fill/simpleFill.png differ diff --git a/img/readme/quickstart/fill/simpleFillTemplate.png b/img/readme/quickstart/fill/simpleFillTemplate.png new file mode 100644 index 0000000..97a9119 Binary files /dev/null and b/img/readme/quickstart/fill/simpleFillTemplate.png differ diff --git a/quickstart.md b/quickstart.md index db95048..728f373 100644 --- a/quickstart.md +++ b/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样例 ### 最简单的读 ##### 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, Cell cell, + Head head, Integer relativeRowIndex, Boolean isHead) { } @Override - public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, - Cell cell, Head head, int relativeRowIndex, boolean isHead) { + public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, + List 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样例 +### 最简单的填充 +##### 模板 +![img](img/readme/quickstart/fill/simpleFillTemplate.png) +##### 最终效果 +![img](img/readme/quickstart/fill/simpleFill.png) +##### 对象 +```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 map = new HashMap(); + map.put("name", "张三"); + map.put("number", 5.2); + EasyExcel.write(fileName).withTemplate(templateFileName).sheet().doFill(map); + } +``` + +### 填充列表 +##### 模板 +![img](img/readme/quickstart/fill/listFillTemplate.png) +##### 最终效果 +![img](img/readme/quickstart/fill/listFill.png) +##### 对象 +参照:[对象](#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(); + } +``` + +### 复杂的填充 +##### 模板 +![img](img/readme/quickstart/fill/complexFillTemplate.png) +##### 最终效果 +![img](img/readme/quickstart/fill/complexFill.png) +##### 对象 +参照:[对象](#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 map = new HashMap(); + map.put("date", "2019年10月9日13:28:28"); + map.put("total", 1000); + excelWriter.fill(map, writeSheet); + excelWriter.finish(); + } +``` + +### 数据量大的复杂填充 +##### 模板 +![img](img/readme/quickstart/fill/complexFillWithTableTemplate.png) +##### 最终效果 +![img](img/readme/quickstart/fill/complexFillWithTable.png) +##### 对象 +参照:[对象](#simpleFillObject) +##### 代码 +```java + /** + * 数据量大的复杂填充 + *

+ * 这里的解决方案是 确保模板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 map = new HashMap(); + map.put("date", "2019年10月9日13:28:28"); + excelWriter.fill(map, writeSheet); + + // list 后面还有个统计 想办法手动写入 + // 这里偷懒直接用list 也可以用对象 + List> totalListList = new ArrayList>(); + List totalList = new ArrayList(); + 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需要新增行的时候,后面的列的数据没法后移,后续会继续想想解决方案 + } +``` + +### 横向的填充 +##### 模板 +![img](img/readme/quickstart/fill/horizontalFillTemplate.png) +##### 最终效果 +![img](img/readme/quickstart/fill/horizontalFill.png) +##### 对象 +参照:[对象](#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 map = new HashMap(); + map.put("date", "2019年10月9日13:28:28"); + excelWriter.fill(map, writeSheet); + + // 别忘记关闭流 + excelWriter.finish(); + } +``` + ## 测试数据分析 ![POI usermodel PK easyexcel(Excel 2003).png](http://ata2-img.cn-hangzhou.img-pub.aliyun-inc.com/02c4bfbbab99a649788523d04f84a42f.png) ![POI usermodel PK easyexcel(Excel 2007).png](http://ata2-img.cn-hangzhou.img-pub.aliyun-inc.com/f6a8a19ec959f0eb564e652de523fc9e.png) diff --git a/src/main/java/com/alibaba/excel/ExcelReader.java b/src/main/java/com/alibaba/excel/ExcelReader.java index 3cb6b01..808ee56 100644 --- a/src/main/java/com/alibaba/excel/ExcelReader.java +++ b/src/main/java/com/alibaba/excel/ExcelReader.java @@ -9,7 +9,7 @@ import org.slf4j.LoggerFactory; import com.alibaba.excel.analysis.ExcelAnalyser; import com.alibaba.excel.analysis.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(); } diff --git a/src/main/java/com/alibaba/excel/ExcelWriter.java b/src/main/java/com/alibaba/excel/ExcelWriter.java index 6ee5b6f..65a99fe 100644 --- a/src/main/java/com/alibaba/excel/ExcelWriter.java +++ b/src/main/java/com/alibaba/excel/ExcelWriter.java @@ -17,6 +17,7 @@ import com.alibaba.excel.write.merge.OnceAbsoluteMergeStrategy; import com.alibaba.excel.write.metadata.WriteSheet; import com.alibaba.excel.write.metadata.WriteTable; import com.alibaba.excel.write.metadata.WriteWorkbook; +import com.alibaba.excel.write.metadata.fill.FillConfig; /** * Excel Writer This tool is used to write value out to Excel via POI. This object can perform the following two @@ -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; } diff --git a/src/main/java/com/alibaba/excel/analysis/ExcelAnalyser.java b/src/main/java/com/alibaba/excel/analysis/ExcelAnalyser.java index 8d987ea..6d014bb 100644 --- a/src/main/java/com/alibaba/excel/analysis/ExcelAnalyser.java +++ b/src/main/java/com/alibaba/excel/analysis/ExcelAnalyser.java @@ -27,7 +27,7 @@ public interface ExcelAnalyser { * * @return Excel file Executor */ - ExcelExecutor excelExecutor(); + ExcelReadExecutor excelExecutor(); /** * get the analysis context. diff --git a/src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java b/src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java index cf2dff9..a924b21 100644 --- a/src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java +++ b/src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java @@ -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 diff --git a/src/main/java/com/alibaba/excel/analysis/ExcelExecutor.java b/src/main/java/com/alibaba/excel/analysis/ExcelReadExecutor.java similarity index 90% rename from src/main/java/com/alibaba/excel/analysis/ExcelExecutor.java rename to src/main/java/com/alibaba/excel/analysis/ExcelReadExecutor.java index 8868d2e..515eeb9 100644 --- a/src/main/java/com/alibaba/excel/analysis/ExcelExecutor.java +++ b/src/main/java/com/alibaba/excel/analysis/ExcelReadExecutor.java @@ -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 diff --git a/src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java b/src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java index 36d2b74..7134e6f 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java @@ -22,7 +22,7 @@ import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.alibaba.excel.analysis.ExcelExecutor; +import com.alibaba.excel.analysis.ExcelReadExecutor; import com.alibaba.excel.analysis.v03.handlers.BlankOrErrorRecordHandler; import com.alibaba.excel.analysis.v03.handlers.BofRecordHandler; import com.alibaba.excel.analysis.v03.handlers.FormulaRecordHandler; @@ -56,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; diff --git a/src/main/java/com/alibaba/excel/analysis/v07/XlsxSaxAnalyser.java b/src/main/java/com/alibaba/excel/analysis/v07/XlsxSaxAnalyser.java index 932fb65..7a34e6c 100644 --- a/src/main/java/com/alibaba/excel/analysis/v07/XlsxSaxAnalyser.java +++ b/src/main/java/com/alibaba/excel/analysis/v07/XlsxSaxAnalyser.java @@ -13,6 +13,7 @@ import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import 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 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 diff --git a/src/main/java/com/alibaba/excel/context/AnalysisContext.java b/src/main/java/com/alibaba/excel/context/AnalysisContext.java index 7b8ba86..5c918f2 100644 --- a/src/main/java/com/alibaba/excel/context/AnalysisContext.java +++ b/src/main/java/com/alibaba/excel/context/AnalysisContext.java @@ -2,7 +2,7 @@ package com.alibaba.excel.context; import java.io.InputStream; -import com.alibaba.excel.analysis.ExcelExecutor; +import com.alibaba.excel.analysis.ExcelReadExecutor; import com.alibaba.excel.event.AnalysisEventListener; import com.alibaba.excel.metadata.Sheet; import com.alibaba.excel.read.metadata.ReadSheet; @@ -22,12 +22,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 diff --git a/src/main/java/com/alibaba/excel/context/AnalysisContextImpl.java b/src/main/java/com/alibaba/excel/context/AnalysisContextImpl.java index d9d7ded..999aa50 100644 --- a/src/main/java/com/alibaba/excel/context/AnalysisContextImpl.java +++ b/src/main/java/com/alibaba/excel/context/AnalysisContextImpl.java @@ -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()); } diff --git a/src/main/java/com/alibaba/excel/context/WriteContext.java b/src/main/java/com/alibaba/excel/context/WriteContext.java index 17db4ca..e561319 100644 --- a/src/main/java/com/alibaba/excel/context/WriteContext.java +++ b/src/main/java/com/alibaba/excel/context/WriteContext.java @@ -5,6 +5,7 @@ import java.io.OutputStream; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; +import com.alibaba.excel.enums.WriteTypeEnum; import com.alibaba.excel.write.metadata.WriteSheet; import com.alibaba.excel.write.metadata.WriteTable; import com.alibaba.excel.write.metadata.holder.WriteHolder; @@ -21,9 +22,11 @@ public interface WriteContext { /** * If the current sheet already exists, select it; if not, create it * - * @param writeSheet Current sheet + * @param writeSheet + * Current sheet + * @param writeType */ - void currentSheet(WriteSheet writeSheet); + void currentSheet(WriteSheet writeSheet, WriteTypeEnum writeType); /** * If the current table already exists, select it; if not, create it diff --git a/src/main/java/com/alibaba/excel/context/WriteContextImpl.java b/src/main/java/com/alibaba/excel/context/WriteContextImpl.java index 34b90ba..c71d08d 100644 --- a/src/main/java/com/alibaba/excel/context/WriteContextImpl.java +++ b/src/main/java/com/alibaba/excel/context/WriteContextImpl.java @@ -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 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 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 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 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 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 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 headMap, int relativeRowIndex) { for (Map.Entry 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 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 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); diff --git a/src/main/java/com/alibaba/excel/enums/WriteDirectionEnum.java b/src/main/java/com/alibaba/excel/enums/WriteDirectionEnum.java new file mode 100644 index 0000000..78803f1 --- /dev/null +++ b/src/main/java/com/alibaba/excel/enums/WriteDirectionEnum.java @@ -0,0 +1,17 @@ +package com.alibaba.excel.enums; + +/** + * Direction of writing + * + * @author Jiaju Zhuang + **/ +public enum WriteDirectionEnum { + /** + * Vertical write. + */ + VERTICAL, + /** + * Horizontal write. + */ + HORIZONTAL,; +} diff --git a/src/main/java/com/alibaba/excel/enums/WriteLastRowType.java b/src/main/java/com/alibaba/excel/enums/WriteLastRowTypeEnum.java similarity index 91% rename from src/main/java/com/alibaba/excel/enums/WriteLastRowType.java rename to src/main/java/com/alibaba/excel/enums/WriteLastRowTypeEnum.java index bd477bd..d9a41ae 100644 --- a/src/main/java/com/alibaba/excel/enums/WriteLastRowType.java +++ b/src/main/java/com/alibaba/excel/enums/WriteLastRowTypeEnum.java @@ -5,7 +5,7 @@ package com.alibaba.excel.enums; * * @author Jiaju Zhuang **/ -public enum WriteLastRowType { +public enum WriteLastRowTypeEnum { /** * Excel are created without templates ,And any data has been written; */ diff --git a/src/main/java/com/alibaba/excel/enums/WriteTemplateAnalysisCellTypeEnum.java b/src/main/java/com/alibaba/excel/enums/WriteTemplateAnalysisCellTypeEnum.java new file mode 100644 index 0000000..e9d22a8 --- /dev/null +++ b/src/main/java/com/alibaba/excel/enums/WriteTemplateAnalysisCellTypeEnum.java @@ -0,0 +1,17 @@ +package com.alibaba.excel.enums; + +/** + * Type of template to read when writing + * + * @author Jiaju Zhuang + **/ +public enum WriteTemplateAnalysisCellTypeEnum { + /** + * Common field. + */ + COMMON, + /** + * A collection of fields. + */ + COLLECTION,; +} diff --git a/src/main/java/com/alibaba/excel/enums/WriteTypeEnum.java b/src/main/java/com/alibaba/excel/enums/WriteTypeEnum.java new file mode 100644 index 0000000..9dbbd31 --- /dev/null +++ b/src/main/java/com/alibaba/excel/enums/WriteTypeEnum.java @@ -0,0 +1,17 @@ +package com.alibaba.excel.enums; + +/** + * Enumeration of write methods + * + * @author Jiaju Zhuang + **/ +public enum WriteTypeEnum { + /** + * Add. + */ + ADD, + /** + * Fill. + */ + FILL,; +} diff --git a/src/main/java/com/alibaba/excel/metadata/property/ExcelHeadProperty.java b/src/main/java/com/alibaba/excel/metadata/property/ExcelHeadProperty.java index a1200d5..09d5560 100644 --- a/src/main/java/com/alibaba/excel/metadata/property/ExcelHeadProperty.java +++ b/src/main/java/com/alibaba/excel/metadata/property/ExcelHeadProperty.java @@ -52,6 +52,10 @@ public class ExcelHeadProperty { * Configuration column information */ private Map contentPropertyMap; + /** + * Configuration column information + */ + private Map fieldNameContentPropertyMap; /** * Fields ignored */ @@ -61,6 +65,7 @@ public class ExcelHeadProperty { this.headClazz = headClazz; headMap = new TreeMap(); contentPropertyMap = new TreeMap(); + fieldNameContentPropertyMap = new HashMap(); ignoreMap = new HashMap(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 getFieldNameContentPropertyMap() { + return fieldNameContentPropertyMap; + } + + public void setFieldNameContentPropertyMap(Map fieldNameContentPropertyMap) { + this.fieldNameContentPropertyMap = fieldNameContentPropertyMap; + } + public Map getIgnoreMap() { return ignoreMap; } diff --git a/src/main/java/com/alibaba/excel/util/StringUtils.java b/src/main/java/com/alibaba/excel/util/StringUtils.java index 25ed127..948ae65 100644 --- a/src/main/java/com/alibaba/excel/util/StringUtils.java +++ b/src/main/java/com/alibaba/excel/util/StringUtils.java @@ -6,10 +6,11 @@ package com.alibaba.excel.util; * @author jipengfei */ public class StringUtils { + public static final String EMPTY = ""; private StringUtils() {} public static boolean isEmpty(Object str) { - return (str == null || "".equals(str)); + return (str == null || EMPTY.equals(str)); } } diff --git a/src/main/java/com/alibaba/excel/util/WorkBookUtil.java b/src/main/java/com/alibaba/excel/util/WorkBookUtil.java index 78cbd27..949c3da 100644 --- a/src/main/java/com/alibaba/excel/util/WorkBookUtil.java +++ b/src/main/java/com/alibaba/excel/util/WorkBookUtil.java @@ -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.getTemplateInputStream() != null) { - xssfWorkbook = new XSSFWorkbook(writeWorkbookHolder.getTemplateInputStream()); + if (writeWorkbookHolder.getTempTemplateInputStream() != null) { + XSSFWorkbook xssfWorkbook = new XSSFWorkbook(writeWorkbookHolder.getTempTemplateInputStream()); + writeWorkbookHolder.setCachedWorkbook(xssfWorkbook); + writeWorkbookHolder.setWorkbook(new SXSSFWorkbook(xssfWorkbook, ROW_ACCESS_WINDOW_SIZE)); + return; } - // 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); - } - if (writeWorkbookHolder.getTemplateFile() != null) { - return new HSSFWorkbook(new POIFSFileSystem(writeWorkbookHolder.getTemplateFile())); + SXSSFWorkbook sxssWorkbook = new SXSSFWorkbook(ROW_ACCESS_WINDOW_SIZE); + writeWorkbookHolder.setCachedWorkbook(sxssWorkbook); + writeWorkbookHolder.setWorkbook(sxssWorkbook); + return; } - if (writeWorkbookHolder.getTemplateInputStream() != null) { - return new HSSFWorkbook(new POIFSFileSystem(writeWorkbookHolder.getTemplateInputStream())); + HSSFWorkbook hssfWorkbook; + if (writeWorkbookHolder.getTempTemplateInputStream() != null) { + hssfWorkbook = new HSSFWorkbook(new POIFSFileSystem(writeWorkbookHolder.getTempTemplateInputStream())); + } else { + hssfWorkbook = new HSSFWorkbook(); } - return new HSSFWorkbook(); + writeWorkbookHolder.setCachedWorkbook(hssfWorkbook); + writeWorkbookHolder.setWorkbook(hssfWorkbook); } public static Sheet createSheet(Workbook workbook, String sheetName) { diff --git a/src/main/java/com/alibaba/excel/util/WriteHandlerUtils.java b/src/main/java/com/alibaba/excel/util/WriteHandlerUtils.java new file mode 100644 index 0000000..b303a31 --- /dev/null +++ b/src/main/java/com/alibaba/excel/util/WriteHandlerUtils.java @@ -0,0 +1,196 @@ +package com.alibaba.excel.util; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Row; + +import com.alibaba.excel.context.WriteContext; +import com.alibaba.excel.metadata.CellData; +import com.alibaba.excel.metadata.Head; +import com.alibaba.excel.write.handler.CellWriteHandler; +import com.alibaba.excel.write.handler.RowWriteHandler; +import com.alibaba.excel.write.handler.SheetWriteHandler; +import com.alibaba.excel.write.handler.WorkbookWriteHandler; +import com.alibaba.excel.write.handler.WriteHandler; + +/** + * Write handler utils + * + * @author Jiaju Zhuang + */ +public class WriteHandlerUtils { + + private WriteHandlerUtils() {} + + public static void beforeWorkbookCreate(WriteContext writeContext) { + List 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 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 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 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 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 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 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 cellDataList = new ArrayList(); + if (cell != null) { + cellDataList.add(cellData); + } + afterCellDispose(writeContext, cellDataList, cell, head, relativeRowIndex, isHead); + } + + public static void afterCellDispose(WriteContext writeContext, List cellDataList, Cell cell, Head head, + Integer relativeRowIndex, Boolean isHead) { + List 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 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 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 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); + } + } +} diff --git a/src/main/java/com/alibaba/excel/write/ExcelBuilder.java b/src/main/java/com/alibaba/excel/write/ExcelBuilder.java index 6dcf947..8a60444 100644 --- a/src/main/java/com/alibaba/excel/write/ExcelBuilder.java +++ b/src/main/java/com/alibaba/excel/write/ExcelBuilder.java @@ -6,6 +6,7 @@ import com.alibaba.excel.context.WriteContext; import com.alibaba.excel.write.merge.OnceAbsoluteMergeStrategy; import com.alibaba.excel.write.metadata.WriteSheet; import com.alibaba.excel.write.metadata.WriteTable; +import com.alibaba.excel.write.metadata.fill.FillConfig; /** * @author jipengfei @@ -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. diff --git a/src/main/java/com/alibaba/excel/write/ExcelBuilderImpl.java b/src/main/java/com/alibaba/excel/write/ExcelBuilderImpl.java index 3bbda25..3d8067a 100644 --- a/src/main/java/com/alibaba/excel/write/ExcelBuilderImpl.java +++ b/src/main/java/com/alibaba/excel/write/ExcelBuilderImpl.java @@ -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 fieldList = new ArrayList(); - 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 templateLastRowMap = context.writeWorkbookHolder().getTemplateLastRowMap(); - if (sheet == null) { - throw new ExcelGenerateException( - "The corresponding table cannot be found,sheetNo:" + writeSheetHolder.getSheetNo()); - } - List analysisCellList = new ArrayList(); - 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 variableList = new ArrayList(); - 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 fileDataStringList = new ArrayList(); - 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 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 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 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 oneRowData, Row row, int relativeRowIndex) { - if (CollectionUtils.isEmpty(oneRowData)) { - return; - } - Map headMap = context.currentWriteHolder().excelWriteHeadProperty().getHeadMap(); - int dataIndex = 0; - int cellIndex = 0; - for (Map.Entry 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 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 fieldList) { - WriteHolder currentWriteHolder = context.currentWriteHolder(); - BeanMap beanMap = BeanMap.create(oneRowData); - Set beanMapHandledSet = new HashSet(); - int cellIndex = 0; - // If it's a class it needs to be cast by type - if (HeadKindEnum.CLASS.equals(context.currentWriteHolder().excelWriteHeadProperty().getHeadKind())) { - Map headMap = context.currentWriteHolder().excelWriteHeadProperty().getHeadMap(); - Map contentPropertyMap = - context.currentWriteHolder().excelWriteHeadProperty().getContentPropertyMap(); - for (Map.Entry 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 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 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 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 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; - } } diff --git a/src/main/java/com/alibaba/excel/write/builder/ExcelWriterSheetBuilder.java b/src/main/java/com/alibaba/excel/write/builder/ExcelWriterSheetBuilder.java index 29e8277..8a9e0c6 100644 --- a/src/main/java/com/alibaba/excel/write/builder/ExcelWriterSheetBuilder.java +++ b/src/main/java/com/alibaba/excel/write/builder/ExcelWriterSheetBuilder.java @@ -8,6 +8,7 @@ import com.alibaba.excel.converters.Converter; import com.alibaba.excel.exception.ExcelGenerateException; import com.alibaba.excel.write.handler.WriteHandler; import com.alibaba.excel.write.metadata.WriteSheet; +import com.alibaba.excel.write.metadata.fill.FillConfig; /** * Build sheet @@ -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(); } diff --git a/src/main/java/com/alibaba/excel/write/executor/AbstractExcelWriteExecutor.java b/src/main/java/com/alibaba/excel/write/executor/AbstractExcelWriteExecutor.java new file mode 100644 index 0000000..9adcb62 --- /dev/null +++ b/src/main/java/com/alibaba/excel/write/executor/AbstractExcelWriteExecutor.java @@ -0,0 +1,140 @@ +package com.alibaba.excel.write.executor; + +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.ClientAnchor; +import org.apache.poi.ss.usermodel.CreationHelper; +import org.apache.poi.ss.usermodel.Drawing; +import org.apache.poi.ss.usermodel.Sheet; + +import com.alibaba.excel.context.WriteContext; +import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.converters.ConverterKeyBuild; +import com.alibaba.excel.enums.CellDataTypeEnum; +import com.alibaba.excel.exception.ExcelDataConvertException; +import com.alibaba.excel.metadata.CellData; +import com.alibaba.excel.metadata.property.ExcelContentProperty; +import com.alibaba.excel.write.metadata.holder.WriteHolder; + +/** + * Excel write Executor + * + * @author Jiaju Zhuang + */ +public abstract class AbstractExcelWriteExecutor implements ExcelWriteExecutor { + protected WriteContext writeContext; + + public AbstractExcelWriteExecutor(WriteContext writeContext) { + this.writeContext = writeContext; + } + + protected CellData converterAndSet(WriteHolder currentWriteHolder, Class clazz, Cell cell, Object value, + ExcelContentProperty excelContentProperty) { + if (value == null) { + return new CellData(); + } + if (value instanceof String && currentWriteHolder.globalConfiguration().getAutoTrim()) { + value = ((String)value).trim(); + } + CellData cellData = convert(currentWriteHolder, clazz, cell, value, excelContentProperty); + if (cellData.getFormula() != null && cellData.getFormula()) { + cell.setCellFormula(cellData.getFormulaValue()); + } + switch (cellData.getType()) { + case STRING: + cell.setCellValue(cellData.getStringValue()); + return cellData; + case BOOLEAN: + cell.setCellValue(cellData.getBooleanValue()); + return cellData; + case NUMBER: + cell.setCellValue(cellData.getNumberValue().doubleValue()); + return cellData; + case IMAGE: + setImageValue(cellData, cell); + return cellData; + case EMPTY: + return cellData; + default: + throw new ExcelDataConvertException("Not supported data:" + value + " return type:" + cell.getCellType() + + "at row:" + cell.getRow().getRowNum()); + } + } + + protected CellData convert(WriteHolder currentWriteHolder, Class clazz, Cell cell, Object value, + ExcelContentProperty excelContentProperty) { + if (value == null) { + return new CellData(); + } + // This means that the user has defined the data. + if (value instanceof CellData) { + CellData cellDataValue = (CellData)value; + if (cellDataValue.getType() != null) { + return cellDataValue; + } else { + if (cellDataValue.getData() == null) { + cellDataValue.setType(CellDataTypeEnum.EMPTY); + return cellDataValue; + } + } + CellData cellDataReturn = doConvert(currentWriteHolder, cellDataValue.getData().getClass(), cell, + cellDataValue.getData(), excelContentProperty); + // The formula information is subject to user input + if (cellDataValue.getFormula() != null) { + cellDataReturn.setFormula(cellDataValue.getFormula()); + cellDataReturn.setFormulaValue(cellDataValue.getFormulaValue()); + } + return cellDataReturn; + } + return doConvert(currentWriteHolder, clazz, cell, value, excelContentProperty); + } + + private CellData doConvert(WriteHolder currentWriteHolder, Class clazz, Cell cell, Object value, + ExcelContentProperty excelContentProperty) { + Converter converter = null; + if (excelContentProperty != null) { + converter = excelContentProperty.getConverter(); + } + if (converter == null) { + converter = currentWriteHolder.converterMap().get(ConverterKeyBuild.buildKey(clazz)); + } + if (converter == null) { + throw new ExcelDataConvertException( + "Can not find 'Converter' support class " + clazz.getSimpleName() + "."); + } + CellData cellData; + try { + cellData = + converter.convertToExcelData(value, excelContentProperty, currentWriteHolder.globalConfiguration()); + } catch (Exception e) { + throw new ExcelDataConvertException("Convert data:" + value + " error,at row:" + cell.getRow().getRowNum(), + e); + } + if (cellData == null || cellData.getType() == null) { + throw new ExcelDataConvertException( + "Convert data:" + value + " return null,at row:" + cell.getRow().getRowNum()); + } + return cellData; + } + + private void setImageValue(CellData cellData, Cell cell) { + Sheet sheet = cell.getSheet(); + int index = sheet.getWorkbook().addPicture(cellData.getImageValue(), HSSFWorkbook.PICTURE_TYPE_PNG); + Drawing drawing = sheet.getDrawingPatriarch(); + if (drawing == null) { + drawing = sheet.createDrawingPatriarch(); + } + CreationHelper helper = sheet.getWorkbook().getCreationHelper(); + ClientAnchor anchor = helper.createClientAnchor(); + anchor.setDx1(0); + anchor.setDx2(0); + anchor.setDy1(0); + anchor.setDy2(0); + anchor.setCol1(cell.getColumnIndex()); + anchor.setCol2(cell.getColumnIndex() + 1); + anchor.setRow1(cell.getRowIndex()); + anchor.setRow2(cell.getRowIndex() + 1); + anchor.setAnchorType(ClientAnchor.AnchorType.DONT_MOVE_AND_RESIZE); + drawing.createPicture(anchor, index); + } +} diff --git a/src/main/java/com/alibaba/excel/write/executor/ExcelWriteAddExecutor.java b/src/main/java/com/alibaba/excel/write/executor/ExcelWriteAddExecutor.java new file mode 100644 index 0000000..8843e2c --- /dev/null +++ b/src/main/java/com/alibaba/excel/write/executor/ExcelWriteAddExecutor.java @@ -0,0 +1,179 @@ +package com.alibaba.excel.write.executor; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Row; + +import com.alibaba.excel.context.WriteContext; +import com.alibaba.excel.enums.HeadKindEnum; +import com.alibaba.excel.metadata.BaseRowModel; +import com.alibaba.excel.metadata.CellData; +import com.alibaba.excel.metadata.Head; +import com.alibaba.excel.metadata.property.ExcelContentProperty; +import com.alibaba.excel.util.CollectionUtils; +import com.alibaba.excel.util.WorkBookUtil; +import com.alibaba.excel.util.WriteHandlerUtils; +import com.alibaba.excel.write.metadata.holder.WriteHolder; +import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; + +import net.sf.cglib.beans.BeanMap; + +/** + * Add the data into excel + * + * @author Jiaju Zhuang + */ +public class ExcelWriteAddExecutor extends AbstractExcelWriteExecutor { + + public ExcelWriteAddExecutor(WriteContext writeContext) { + super(writeContext); + } + + public void add(List data) { + if (CollectionUtils.isEmpty(data)) { + return; + } + WriteSheetHolder writeSheetHolder = writeContext.writeSheetHolder(); + int newRowIndex = writeSheetHolder.getNewRowIndexAndStartDoWrite(); + if (writeSheetHolder.isNew() && !writeSheetHolder.getExcelWriteHeadProperty().hasHead()) { + newRowIndex += writeContext.currentWriteHolder().relativeHeadRowIndex(); + } + // BeanMap is out of order,so use fieldList + List fieldList = new ArrayList(); + 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 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 oneRowData, Row row, int relativeRowIndex) { + if (CollectionUtils.isEmpty(oneRowData)) { + return; + } + Map headMap = writeContext.currentWriteHolder().excelWriteHeadProperty().getHeadMap(); + int dataIndex = 0; + int cellIndex = 0; + for (Map.Entry 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 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 fieldList) { + WriteHolder currentWriteHolder = writeContext.currentWriteHolder(); + BeanMap beanMap = BeanMap.create(oneRowData); + Set beanMapHandledSet = new HashSet(); + int cellIndex = 0; + // If it's a class it needs to be cast by type + if (HeadKindEnum.CLASS.equals(writeContext.currentWriteHolder().excelWriteHeadProperty().getHeadKind())) { + Map headMap = writeContext.currentWriteHolder().excelWriteHeadProperty().getHeadMap(); + Map contentPropertyMap = + writeContext.currentWriteHolder().excelWriteHeadProperty().getContentPropertyMap(); + for (Map.Entry 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 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 fieldList) { + if (!fieldList.isEmpty()) { + return; + } + Class tempClass = clazz; + while (tempClass != null) { + if (tempClass != BaseRowModel.class) { + Collections.addAll(fieldList, tempClass.getDeclaredFields()); + } + tempClass = tempClass.getSuperclass(); + } + } + +} diff --git a/src/main/java/com/alibaba/excel/write/executor/ExcelWriteExecutor.java b/src/main/java/com/alibaba/excel/write/executor/ExcelWriteExecutor.java new file mode 100644 index 0000000..b7cb607 --- /dev/null +++ b/src/main/java/com/alibaba/excel/write/executor/ExcelWriteExecutor.java @@ -0,0 +1,9 @@ +package com.alibaba.excel.write.executor; + +/** + * Excel write Executor + * + * @author Jiaju Zhuang + */ +public interface ExcelWriteExecutor { +} diff --git a/src/main/java/com/alibaba/excel/write/executor/ExcelWriteFillExecutor.java b/src/main/java/com/alibaba/excel/write/executor/ExcelWriteFillExecutor.java new file mode 100644 index 0000000..217f21e --- /dev/null +++ b/src/main/java/com/alibaba/excel/write/executor/ExcelWriteFillExecutor.java @@ -0,0 +1,377 @@ +package com.alibaba.excel.write.executor; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; + +import com.alibaba.excel.context.WriteContext; +import com.alibaba.excel.enums.WriteDirectionEnum; +import com.alibaba.excel.enums.WriteTemplateAnalysisCellTypeEnum; +import com.alibaba.excel.exception.ExcelGenerateException; +import com.alibaba.excel.metadata.CellData; +import com.alibaba.excel.metadata.Head; +import com.alibaba.excel.metadata.property.ExcelContentProperty; +import com.alibaba.excel.util.CollectionUtils; +import com.alibaba.excel.util.StringUtils; +import com.alibaba.excel.util.WriteHandlerUtils; +import com.alibaba.excel.write.metadata.fill.AnalysisCell; +import com.alibaba.excel.write.metadata.fill.FillConfig; +import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; + +import net.sf.cglib.beans.BeanMap; + +/** + * Fill the data into excel + * + * @author Jiaju Zhuang + */ +public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor { + + private static final String ESCAPE_FILL_PREFIX = "\\\\\\{"; + private static final String ESCAPE_FILL_SUFFIX = "\\\\\\}"; + private static final String FILL_PREFIX = "{"; + private static final String FILL_SUFFIX = "}"; + private static final char IGNORE_CHAR = '\\'; + private static final String COLLECTION_PREFIX = "."; + /** + * Fields to replace in the template + */ + private Map> templateAnalysisCache = new HashMap>(8); + /** + * Collection fields to replace in the template + */ + private Map> templateCollectionAnalysisCache = + new HashMap>(8); + /** + * Style cache for collection fields + */ + private Map> collectionFieldStyleCache = + new HashMap>(8); + /** + * Last index cache for collection fields + */ + private Map> collectionLastIndexCache = + new HashMap>(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 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 analysisCellList) { + if (CollectionUtils.isEmpty(analysisCellList)) { + return; + } + int maxRowIndex = 0; + Integer sheetNo = writeContext.writeSheetHolder().getSheetNo(); + Map 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 analysisCellList, Object oneRowData, FillConfig fillConfig) { + Map dataMap; + if (oneRowData instanceof Map) { + dataMap = (Map)oneRowData; + } else { + dataMap = BeanMap.create(oneRowData); + } + WriteSheetHolder writeSheetHolder = writeContext.writeSheetHolder(); + Map 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 cellDataList = new ArrayList(); + 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 collectionLastIndexMap = collectionLastIndexCache.get(sheetNo); + if (collectionLastIndexMap == null) { + collectionLastIndexMap = new HashMap(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 collectionFieldStyleMap = collectionFieldStyleCache.get(sheetNo); + if (collectionFieldStyleMap == null) { + collectionFieldStyleMap = new HashMap(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 readTemplateData(Map> analysisCache) { + Integer sheetNo = writeContext.writeSheetHolder().getSheetNo(); + List analysisCellList = analysisCache.get(sheetNo); + if (analysisCellList != null) { + return analysisCellList; + } + Sheet sheet = writeContext.writeSheetHolder().getCachedSheet(); + analysisCellList = new ArrayList(); + List collectionAnalysisCellList = new ArrayList(); + 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 analysisCellList, + List 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 variableList = new ArrayList(); + analysisCell.setVariableList(variableList); + List prepareDataList = new ArrayList(); + 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; + } + +} diff --git a/src/main/java/com/alibaba/excel/write/handler/CellWriteHandler.java b/src/main/java/com/alibaba/excel/write/handler/CellWriteHandler.java index 9e8af22..4d98138 100644 --- a/src/main/java/com/alibaba/excel/write/handler/CellWriteHandler.java +++ b/src/main/java/com/alibaba/excel/write/handler/CellWriteHandler.java @@ -1,5 +1,7 @@ package com.alibaba.excel.write.handler; +import java.util.List; + import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; @@ -16,32 +18,56 @@ import com.alibaba.excel.write.metadata.holder.WriteTableHolder; public interface CellWriteHandler extends WriteHandler { /** - * called before create the cell + * Called before create the cell * * @param writeSheetHolder * @param writeTableHolder - * Nullable + * Nullable.It is null without using table writes. * @param row * @param head + * Nullable.It is null in the case of fill data and without head. + * @param columnIndex * @param relativeRowIndex + * Nullable.It is null in the case of fill data. * @param isHead + * It will always be false when fill data. */ void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, - int relativeRowIndex, boolean isHead); + Integer columnIndex, Integer relativeRowIndex, Boolean isHead); + + /** + * Called after the cell is created + * + * @param writeSheetHolder + * @param writeTableHolder + * Nullable.It is null without using table writes. + * @param cell + * @param head + * Nullable.It is null in the case of fill data and without head. + * @param relativeRowIndex + * Nullable.It is null in the case of fill data. + * @param isHead + * It will always be false when fill data. + */ + void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, + Integer relativeRowIndex, Boolean isHead); /** - * called after the cell is created + * Called after all operations on the cell have been completed * * @param writeSheetHolder * @param writeTableHolder - * Nullable + * Nullable.It is null without using table writes. * @param cell * @param head - * @param cellData - * Nullable. + * Nullable.It is null in the case of fill data and without head. + * @param cellDataList + * Nullable.It is null in the case of add header.There may be several when fill the data. * @param relativeRowIndex + * Nullable.It is null in the case of fill data. * @param isHead + * It will always be false when fill data. */ - void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, - Cell cell, Head head, int relativeRowIndex, boolean isHead); + void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, + List cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead); } diff --git a/src/main/java/com/alibaba/excel/write/handler/RowWriteHandler.java b/src/main/java/com/alibaba/excel/write/handler/RowWriteHandler.java index 1630bd3..29ac10b 100644 --- a/src/main/java/com/alibaba/excel/write/handler/RowWriteHandler.java +++ b/src/main/java/com/alibaba/excel/write/handler/RowWriteHandler.java @@ -13,28 +13,47 @@ import com.alibaba.excel.write.metadata.holder.WriteTableHolder; public interface RowWriteHandler extends WriteHandler { /** - * called before create the row + * Called before create the row * * @param writeSheetHolder * @param writeTableHolder - * Nullable + * Nullable.It is null without using table writes. * @param rowIndex * @param relativeRowIndex + * Nullable.It is null in the case of fill data. * @param isHead + * Nullable.It is null in the case of fill data. */ - void beforeRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, int rowIndex, - int relativeRowIndex, boolean isHead); + void beforeRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Integer rowIndex, + Integer relativeRowIndex, Boolean isHead); /** - * called after the row is created + * Called after the row is created * * @param writeSheetHolder * @param writeTableHolder - * Nullable + * Nullable.It is null without using table writes. * @param row * @param relativeRowIndex + * Nullable.It is null in the case of fill data. * @param isHead + * Nullable.It is null in the case of fill data. */ void afterRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, - int relativeRowIndex, boolean isHead); + Integer relativeRowIndex, Boolean isHead); + + /** + * Called after all operations on the row have been completed.This method is not called when fill the data. + * + * @param writeSheetHolder + * @param writeTableHolder + * Nullable.It is null without using table writes. + * @param row + * @param relativeRowIndex + * Nullable.It is null in the case of fill data. + * @param isHead + * Nullable.It is null in the case of fill data. + */ + void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, + Integer relativeRowIndex, Boolean isHead); } diff --git a/src/main/java/com/alibaba/excel/write/handler/SheetWriteHandler.java b/src/main/java/com/alibaba/excel/write/handler/SheetWriteHandler.java index 080abbf..b97e1d1 100644 --- a/src/main/java/com/alibaba/excel/write/handler/SheetWriteHandler.java +++ b/src/main/java/com/alibaba/excel/write/handler/SheetWriteHandler.java @@ -11,7 +11,7 @@ import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; public interface SheetWriteHandler extends WriteHandler { /** - * called before create the sheet + * Called before create the sheet * * @param writeWorkbookHolder * @param writeSheetHolder @@ -19,7 +19,7 @@ public interface SheetWriteHandler extends WriteHandler { void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder); /** - * called after the sheet is created + * Called after the sheet is created * * @param writeWorkbookHolder * @param writeSheetHolder diff --git a/src/main/java/com/alibaba/excel/write/handler/WorkbookWriteHandler.java b/src/main/java/com/alibaba/excel/write/handler/WorkbookWriteHandler.java index 508c9c5..8dba964 100644 --- a/src/main/java/com/alibaba/excel/write/handler/WorkbookWriteHandler.java +++ b/src/main/java/com/alibaba/excel/write/handler/WorkbookWriteHandler.java @@ -10,14 +10,21 @@ import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; public interface WorkbookWriteHandler extends WriteHandler { /** - * called before create the sheet + * Called before create the workbook */ void beforeWorkbookCreate(); /** - * called after the sheet is created + * Called after the workbook is created * * @param writeWorkbookHolder */ void afterWorkbookCreate(WriteWorkbookHolder writeWorkbookHolder); + + /** + * Called after all operations on the workbook have been completed + * + * @param writeWorkbookHolder + */ + void afterWorkbookDispose(WriteWorkbookHolder writeWorkbookHolder); } diff --git a/src/main/java/com/alibaba/excel/write/merge/AbstractMergeStrategy.java b/src/main/java/com/alibaba/excel/write/merge/AbstractMergeStrategy.java index 7b95f1c..13bdac3 100644 --- a/src/main/java/com/alibaba/excel/write/merge/AbstractMergeStrategy.java +++ b/src/main/java/com/alibaba/excel/write/merge/AbstractMergeStrategy.java @@ -1,5 +1,7 @@ package com.alibaba.excel.write.merge; +import java.util.List; + import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; @@ -18,13 +20,17 @@ import com.alibaba.excel.write.metadata.holder.WriteTableHolder; public abstract class AbstractMergeStrategy implements CellWriteHandler { @Override public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, - Head head, int relativeRowIndex, boolean isHead) { + Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) { } @Override - public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, - Cell cell, Head head, int relativeRowIndex, boolean isHead) { + public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, + Head head, Integer relativeRowIndex, Boolean isHead) {} + + @Override + public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, + List cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { if (isHead) { return; } diff --git a/src/main/java/com/alibaba/excel/write/metadata/fill/AnalysisCell.java b/src/main/java/com/alibaba/excel/write/metadata/fill/AnalysisCell.java index 4613891..791e264 100644 --- a/src/main/java/com/alibaba/excel/write/metadata/fill/AnalysisCell.java +++ b/src/main/java/com/alibaba/excel/write/metadata/fill/AnalysisCell.java @@ -2,6 +2,8 @@ package com.alibaba.excel.write.metadata.fill; import java.util.List; +import 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 variableList; - private String prepareData; + private List 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 getPrepareDataList() { + return prepareDataList; + } + + public void setPrepareDataList(List prepareDataList) { + this.prepareDataList = prepareDataList; + } + + public Boolean getOnlyOneVariable() { + return onlyOneVariable; + } + + public void setOnlyOneVariable(Boolean onlyOneVariable) { + this.onlyOneVariable = onlyOneVariable; + } + + public WriteTemplateAnalysisCellTypeEnum getCellType() { + return cellType; + } + + public void setCellType(WriteTemplateAnalysisCellTypeEnum cellType) { + this.cellType = cellType; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AnalysisCell that = (AnalysisCell)o; + if (columnIndex != that.columnIndex) { + return false; + } + return rowIndex == that.rowIndex; } - public void setPrepareData(String prepareData) { - this.prepareData = prepareData; + @Override + public int hashCode() { + int result = columnIndex; + result = 31 * result + rowIndex; + return result; } } diff --git a/src/main/java/com/alibaba/excel/write/metadata/fill/FillConfig.java b/src/main/java/com/alibaba/excel/write/metadata/fill/FillConfig.java new file mode 100644 index 0000000..a5bbe91 --- /dev/null +++ b/src/main/java/com/alibaba/excel/write/metadata/fill/FillConfig.java @@ -0,0 +1,83 @@ +package com.alibaba.excel.write.metadata.fill; + +import com.alibaba.excel.enums.WriteDirectionEnum; + +/** + * Fill config + * + * @author Jiaju Zhuang + **/ +public class FillConfig { + private WriteDirectionEnum direction; + /** + * Create a new row each time you use the list parameter.The default create if necessary. + *

+ * Warnning:If you use forceNewRow 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; + } + + } +} diff --git a/src/main/java/com/alibaba/excel/write/metadata/holder/WriteSheetHolder.java b/src/main/java/com/alibaba/excel/write/metadata/holder/WriteSheetHolder.java index 208fb41..1fb19fb 100644 --- a/src/main/java/com/alibaba/excel/write/metadata/holder/WriteSheetHolder.java +++ b/src/main/java/com/alibaba/excel/write/metadata/holder/WriteSheetHolder.java @@ -3,12 +3,13 @@ package com.alibaba.excel.write.metadata.holder; import java.util.HashMap; import java.util.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. + *

    + *
  • 03:{@link HSSFSheet}
  • + *
  • 07:{@link SXSSFSheet}
  • + *
*/ private Sheet sheet; - /** - * When reading version 07 with the template, the sheet cannot read template data, so need to use - * xssfSheet to get it. + /*** + * Current poi Sheet.Be sure to use and this method when reading template data. + *
    + *
  • 03:{@link HSSFSheet}
  • + *
  • 07:{@link XSSFSheet}
  • + *
*/ - 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(); - 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; } diff --git a/src/main/java/com/alibaba/excel/write/metadata/holder/WriteWorkbookHolder.java b/src/main/java/com/alibaba/excel/write/metadata/holder/WriteWorkbookHolder.java index 0120142..ec364fb 100644 --- a/src/main/java/com/alibaba/excel/write/metadata/holder/WriteWorkbookHolder.java +++ b/src/main/java/com/alibaba/excel/write/metadata/holder/WriteWorkbookHolder.java @@ -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. + *
    + *
  • 03:{@link HSSFWorkbook}
  • + *
  • 07:{@link SXSSFWorkbook}
  • + *
*/ private Workbook workbook; - /** - * When reading version 07 with the template, the workbook 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. + *
    + *
  • 03:{@link HSSFWorkbook}
  • + *
  • 07:{@link XSSFWorkbook}
  • + *
*/ - 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 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 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(); - this.templateLastRowMap = new HashMap(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 getHasBeenInitializedSheet() { @@ -226,14 +252,6 @@ public class WriteWorkbookHolder extends AbstractWriteHolder { this.mandatoryUseInputStream = mandatoryUseInputStream; } - public Map getTemplateLastRowMap() { - return templateLastRowMap; - } - - public void setTemplateLastRowMap(Map templateLastRowMap) { - this.templateLastRowMap = templateLastRowMap; - } - @Override public HolderEnum holderType() { return HolderEnum.WORKBOOK; diff --git a/src/main/java/com/alibaba/excel/write/style/AbstractCellStyleStrategy.java b/src/main/java/com/alibaba/excel/write/style/AbstractCellStyleStrategy.java index 51b03d1..7aafc44 100644 --- a/src/main/java/com/alibaba/excel/write/style/AbstractCellStyleStrategy.java +++ b/src/main/java/com/alibaba/excel/write/style/AbstractCellStyleStrategy.java @@ -1,5 +1,7 @@ package com.alibaba.excel.write.style; +import java.util.List; + import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Workbook; @@ -27,28 +29,23 @@ public abstract class AbstractCellStyleStrategy implements CellWriteHandler, She } @Override - public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { + public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, + Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) { } @Override - public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { - initCellStyle(writeWorkbookHolder.getWorkbook()); - hasInitialized = true; - } + public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, + Head head, Integer relativeRowIndex, Boolean isHead) { - @Override - public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, - Head head, int relativeRowIndex, boolean isHead) { - if (!hasInitialized) { - initCellStyle(writeSheetHolder.getParentWriteWorkbookHolder().getWorkbook()); - hasInitialized = true; - } } @Override - public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, - Cell cell, Head head, int relativeRowIndex, boolean isHead) { + public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, + List cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { + if (isHead == null || head == null) { + return; + } if (isHead) { setHeadCellStyle(cell, head, relativeRowIndex); } else { @@ -56,6 +53,17 @@ public abstract class AbstractCellStyleStrategy implements CellWriteHandler, She } } + @Override + public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { + + } + + @Override + public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { + initCellStyle(writeWorkbookHolder.getWorkbook()); + hasInitialized = true; + } + /** * Initialization cell style * @@ -70,7 +78,7 @@ public abstract class AbstractCellStyleStrategy implements CellWriteHandler, She * @param head * @param relativeRowIndex */ - protected abstract void setHeadCellStyle(Cell cell, Head head, int relativeRowIndex); + protected abstract void setHeadCellStyle(Cell cell, Head head, Integer relativeRowIndex); /** * Sets the cell style of content @@ -79,6 +87,6 @@ public abstract class AbstractCellStyleStrategy implements CellWriteHandler, She * @param head * @param relativeRowIndex */ - protected abstract void setContentCellStyle(Cell cell, Head head, int relativeRowIndex); + protected abstract void setContentCellStyle(Cell cell, Head head, Integer relativeRowIndex); } diff --git a/src/main/java/com/alibaba/excel/write/style/AbstractVerticalCellStyleStrategy.java b/src/main/java/com/alibaba/excel/write/style/AbstractVerticalCellStyleStrategy.java index 083d9cf..09903a0 100644 --- a/src/main/java/com/alibaba/excel/write/style/AbstractVerticalCellStyleStrategy.java +++ b/src/main/java/com/alibaba/excel/write/style/AbstractVerticalCellStyleStrategy.java @@ -29,7 +29,7 @@ public abstract class AbstractVerticalCellStyleStrategy extends AbstractCellStyl } @Override - protected void setHeadCellStyle(Cell cell, Head head, int relativeRowIndex) { + protected void setHeadCellStyle(Cell cell, Head head, Integer relativeRowIndex) { int columnIndex = head.getColumnIndex(); if (headCellStyleCache.containsKey(columnIndex)) { CellStyle cellStyle = headCellStyleCache.get(columnIndex); @@ -49,7 +49,7 @@ public abstract class AbstractVerticalCellStyleStrategy extends AbstractCellStyl } @Override - protected void setContentCellStyle(Cell cell, Head head, int relativeRowIndex) { + protected void setContentCellStyle(Cell cell, Head head, Integer relativeRowIndex) { int columnIndex = head.getColumnIndex(); if (contentCellStyleCache.containsKey(columnIndex)) { CellStyle cellStyle = contentCellStyleCache.get(columnIndex); diff --git a/src/main/java/com/alibaba/excel/write/style/HorizontalCellStyleStrategy.java b/src/main/java/com/alibaba/excel/write/style/HorizontalCellStyleStrategy.java index da5e53b..295cd55 100644 --- a/src/main/java/com/alibaba/excel/write/style/HorizontalCellStyleStrategy.java +++ b/src/main/java/com/alibaba/excel/write/style/HorizontalCellStyleStrategy.java @@ -51,7 +51,7 @@ public class HorizontalCellStyleStrategy extends AbstractCellStyleStrategy { } @Override - protected void setHeadCellStyle(Cell cell, Head head, int relativeRowIndex) { + protected void setHeadCellStyle(Cell cell, Head head, Integer relativeRowIndex) { if (headCellStyle == null) { return; } @@ -59,7 +59,7 @@ public class HorizontalCellStyleStrategy extends AbstractCellStyleStrategy { } @Override - protected void setContentCellStyle(Cell cell, Head head, int relativeRowIndex) { + protected void setContentCellStyle(Cell cell, Head head, Integer relativeRowIndex) { if (contentCellStyleList == null || contentCellStyleList.isEmpty()) { return; } diff --git a/src/main/java/com/alibaba/excel/write/style/column/AbstractColumnWidthStyleStrategy.java b/src/main/java/com/alibaba/excel/write/style/column/AbstractColumnWidthStyleStrategy.java index 67e9733..07afcfc 100644 --- a/src/main/java/com/alibaba/excel/write/style/column/AbstractColumnWidthStyleStrategy.java +++ b/src/main/java/com/alibaba/excel/write/style/column/AbstractColumnWidthStyleStrategy.java @@ -1,5 +1,7 @@ package com.alibaba.excel.write.style.column; +import java.util.List; + import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; @@ -24,27 +26,28 @@ public abstract class AbstractColumnWidthStyleStrategy implements CellWriteHandl @Override public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, - Head head, int relativeRowIndex, boolean isHead) { + Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {} - } + @Override + public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, + Head head, Integer relativeRowIndex, Boolean isHead) {} @Override - public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, - Cell cell, Head head, int relativeRowIndex, boolean isHead) { - setColumnWidth(writeSheetHolder, cellData, cell, head, relativeRowIndex, isHead); + public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List 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 cellDataList, Cell cell, Head head, + Integer relativeRowIndex, Boolean isHead); } diff --git a/src/main/java/com/alibaba/excel/write/style/column/AbstractHeadColumnWidthStyleStrategy.java b/src/main/java/com/alibaba/excel/write/style/column/AbstractHeadColumnWidthStyleStrategy.java index da9b7da..9908144 100644 --- a/src/main/java/com/alibaba/excel/write/style/column/AbstractHeadColumnWidthStyleStrategy.java +++ b/src/main/java/com/alibaba/excel/write/style/column/AbstractHeadColumnWidthStyleStrategy.java @@ -1,5 +1,7 @@ package com.alibaba.excel.write.style.column; +import java.util.List; + import org.apache.poi.ss.usermodel.Cell; import com.alibaba.excel.metadata.CellData; @@ -12,10 +14,12 @@ import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; * @author Jiaju Zhuang */ public abstract class AbstractHeadColumnWidthStyleStrategy extends AbstractColumnWidthStyleStrategy { + @Override - protected void setColumnWidth(WriteSheetHolder writeSheetHolder, CellData cellData, Cell cell, Head head, - int relativeRowIndex, boolean isHead) { - if (!isHead && relativeRowIndex != 0) { + protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List 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); + } diff --git a/src/main/java/com/alibaba/excel/write/style/column/LongestMatchColumnWidthStyleStrategy.java b/src/main/java/com/alibaba/excel/write/style/column/LongestMatchColumnWidthStyleStrategy.java index fb807f3..006927f 100644 --- a/src/main/java/com/alibaba/excel/write/style/column/LongestMatchColumnWidthStyleStrategy.java +++ b/src/main/java/com/alibaba/excel/write/style/column/LongestMatchColumnWidthStyleStrategy.java @@ -1,12 +1,14 @@ package com.alibaba.excel.write.style.column; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.apache.poi.ss.usermodel.Cell; import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.Head; +import com.alibaba.excel.util.CollectionUtils; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; /** @@ -24,9 +26,10 @@ public class LongestMatchColumnWidthStyleStrategy extends AbstractColumnWidthSty private static final Map> CACHE = new HashMap>(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 cellDataList, Cell cell, Head head, + Integer relativeRowIndex, Boolean isHead) { + boolean needSetWidth = isHead || !CollectionUtils.isEmpty(cellDataList); + if (!needSetWidth) { return; } Map maxColumnWidthMap = CACHE.get(writeSheetHolder.getSheetNo()); @@ -34,24 +37,25 @@ public class LongestMatchColumnWidthStyleStrategy extends AbstractColumnWidthSty maxColumnWidthMap = new HashMap(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 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; diff --git a/src/main/java/com/alibaba/excel/write/style/row/AbstractRowHeightStyleStrategy.java b/src/main/java/com/alibaba/excel/write/style/row/AbstractRowHeightStyleStrategy.java index 3a6a343..303c818 100644 --- a/src/main/java/com/alibaba/excel/write/style/row/AbstractRowHeightStyleStrategy.java +++ b/src/main/java/com/alibaba/excel/write/style/row/AbstractRowHeightStyleStrategy.java @@ -20,14 +20,23 @@ public abstract class AbstractRowHeightStyleStrategy implements RowWriteHandler, } @Override - public void beforeRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, int rowIndex, - int relativeRowIndex, boolean isHead) { + public void beforeRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Integer rowIndex, + Integer relativeRowIndex, Boolean isHead) { } @Override public void afterRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, - int relativeRowIndex, boolean isHead) { + Integer relativeRowIndex, Boolean isHead) { + + } + + @Override + public void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, + Integer relativeRowIndex, Boolean isHead) { + if (isHead == null) { + return; + } if (isHead) { setHeadColumnHeight(row, relativeRowIndex); } else { diff --git a/src/test/java/com/alibaba/easyexcel/test/core/fill/FillData.java b/src/test/java/com/alibaba/easyexcel/test/core/fill/FillData.java index 92e18a8..13dfa17 100644 --- a/src/test/java/com/alibaba/easyexcel/test/core/fill/FillData.java +++ b/src/test/java/com/alibaba/easyexcel/test/core/fill/FillData.java @@ -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; } diff --git a/src/test/java/com/alibaba/easyexcel/test/core/fill/FillDataTest.java b/src/test/java/com/alibaba/easyexcel/test/core/fill/FillDataTest.java index 06236ca..93a5457 100644 --- a/src/test/java/com/alibaba/easyexcel/test/core/fill/FillDataTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/core/fill/FillDataTest.java @@ -2,7 +2,9 @@ package com.alibaba.easyexcel.test.core.fill; import java.io.File; import java.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 map = new HashMap(); + map.put("date", "2019年10月9日13:28:28"); + excelWriter.fill(map, writeSheet); + excelWriter.finish(); + + List list = EasyExcel.read(file).sheet().headRowNumber(0).doReadSync(); + Assert.assertEquals(list.size(), 5L); + Map map0 = (Map)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 map = new HashMap(); + map.put("date", "2019年10月9日13:28:28"); + map.put("total", 1000); + excelWriter.fill(map, writeSheet); + excelWriter.finish(); + List list = EasyExcel.read(file).sheet().headRowNumber(3).doReadSync(); + Assert.assertEquals(list.size(), 21L); + Map map19 = (Map)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 data() { - List list = new ArrayList(); - 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 data10() { - List list = new ArrayList(); + private List data() { + List list = new ArrayList(); 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; } + } diff --git a/src/test/java/com/alibaba/easyexcel/test/core/large/LargeDataTest.java b/src/test/java/com/alibaba/easyexcel/test/core/large/LargeDataTest.java index b7ba56b..fa32433 100644 --- a/src/test/java/com/alibaba/easyexcel/test/core/large/LargeDataTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/core/large/LargeDataTest.java @@ -1,13 +1,19 @@ package com.alibaba.easyexcel.test.core.large; import java.io.File; +import java.util.ArrayList; +import java.util.List; +import org.junit.BeforeClass; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.alibaba.easyexcel.test.demo.write.DemoData; import com.alibaba.easyexcel.test.util.TestFileUtil; import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelWriter; +import com.alibaba.excel.write.metadata.WriteSheet; /** * @@ -15,12 +21,67 @@ import com.alibaba.excel.EasyExcel; */ public class LargeDataTest { private static final Logger LOGGER = LoggerFactory.getLogger(LargeDataTest.class); + private static File fileFill07; + private static File template07; + private int i = 0; + + @BeforeClass + public static void init() { + fileFill07 = TestFileUtil.createNewFile("largefill07.xlsx"); + template07 = TestFileUtil.readFile("large" + File.separator + "fill.xlsx"); + } @Test - public void read() { + public void t01Read() { long start = System.currentTimeMillis(); EasyExcel.read(TestFileUtil.getPath() + "large" + File.separator + "large07.xlsx", LargeData.class, new LargeDataListener()).headRowNumber(2).sheet().doRead(); LOGGER.info("Large data total time spent:{}", System.currentTimeMillis() - start); } + + @Test + public void t02Fill() { + ExcelWriter excelWriter = EasyExcel.write(fileFill07).withTemplate(template07).build(); + WriteSheet writeSheet = EasyExcel.writerSheet().build(); + for (int j = 0; j < 100; j++) { + excelWriter.fill(data(), writeSheet); + LOGGER.info("{} fill success.", j); + } + excelWriter.finish(); + } + + private List data() { + List list = new ArrayList(); + 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; + } } diff --git a/src/test/java/com/alibaba/easyexcel/test/demo/fill/FillData.java b/src/test/java/com/alibaba/easyexcel/test/demo/fill/FillData.java new file mode 100644 index 0000000..8890b82 --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/demo/fill/FillData.java @@ -0,0 +1,12 @@ +package com.alibaba.easyexcel.test.demo.fill; + +import lombok.Data; + +/** + * @author Jiaju Zhuang + */ +@Data +public class FillData { + private String name; + private double number; +} diff --git a/src/test/java/com/alibaba/easyexcel/test/demo/fill/FillTest.java b/src/test/java/com/alibaba/easyexcel/test/demo/fill/FillTest.java new file mode 100644 index 0000000..0159cbc --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/demo/fill/FillTest.java @@ -0,0 +1,181 @@ +package com.alibaba.easyexcel.test.demo.fill; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.junit.Ignore; +import org.junit.Test; + +import com.alibaba.easyexcel.test.util.TestFileUtil; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelWriter; +import com.alibaba.excel.enums.WriteDirectionEnum; +import com.alibaba.excel.write.metadata.WriteSheet; +import com.alibaba.excel.write.metadata.fill.FillConfig; + +/** + * 写的填充写法 + * + * @author Jiaju Zhuang + */ +@Ignore +public class FillTest { + /** + * 最简单的填充 + */ + @Test + public void simpleFill() { + // 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替 + String templateFileName = + TestFileUtil.getPath() + "demo" + File.separator + "fill" + File.separator + "simple.xlsx"; + + // 方案1 根据对象填充 + String fileName = TestFileUtil.getPath() + "simpleFill" + System.currentTimeMillis() + ".xlsx"; + // 这里 会填充到第一个sheet, 然后文件流会自动关闭 + FillData fillData = new FillData(); + fillData.setName("张三"); + fillData.setNumber(5.2); + EasyExcel.write(fileName).withTemplate(templateFileName).sheet().doFill(fillData); + + // 方案2 根据Map填充 + fileName = TestFileUtil.getPath() + "simpleFill" + System.currentTimeMillis() + ".xlsx"; + // 这里 会填充到第一个sheet, 然后文件流会自动关闭 + Map map = new HashMap(); + 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 map = new HashMap(); + map.put("date", "2019年10月9日13:28:28"); + map.put("total", 1000); + excelWriter.fill(map, writeSheet); + excelWriter.finish(); + } + + /** + * 数据量大的复杂填充 + *

+ * 这里的解决方案是 确保模板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 map = new HashMap(); + map.put("date", "2019年10月9日13:28:28"); + excelWriter.fill(map, writeSheet); + + // list 后面还有个统计 想办法手动写入 + // 这里偷懒直接用list 也可以用对象 + List> totalListList = new ArrayList>(); + List totalList = new ArrayList(); + 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 map = new HashMap(); + map.put("date", "2019年10月9日13:28:28"); + excelWriter.fill(map, writeSheet); + + // 别忘记关闭流 + excelWriter.finish(); + } + + private List data() { + List list = new ArrayList(); + for (int i = 0; i < 10; i++) { + FillData fillData = new FillData(); + list.add(fillData); + fillData.setName("张三"); + fillData.setNumber(5.2); + } + return list; + } +} diff --git a/src/test/java/com/alibaba/easyexcel/test/demo/write/CustomCellWriteHandler.java b/src/test/java/com/alibaba/easyexcel/test/demo/write/CustomCellWriteHandler.java index bff544a..b92d44a 100644 --- a/src/test/java/com/alibaba/easyexcel/test/demo/write/CustomCellWriteHandler.java +++ b/src/test/java/com/alibaba/easyexcel/test/demo/write/CustomCellWriteHandler.java @@ -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, Cell cell, + Head head, Integer relativeRowIndex, Boolean isHead) { } @Override - public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, - Cell cell, Head head, int relativeRowIndex, boolean isHead) { + public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, + List cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { // 这里可以对cell进行任何操作 LOGGER.info("第{}行,第{}列写入完成。", cell.getRowIndex(), cell.getColumnIndex()); if (isHead && cell.getColumnIndex() == 0) { diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/large/LargeData.java b/src/test/java/com/alibaba/easyexcel/test/temp/large/LargeData.java index 1424c42..43726ad 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/large/LargeData.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/large/LargeData.java @@ -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; diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/poi/PoiTest.java b/src/test/java/com/alibaba/easyexcel/test/temp/poi/PoiTest.java index 7828bd0..0a19c35 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/poi/PoiTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/poi/PoiTest.java @@ -4,7 +4,10 @@ import java.io.File; import java.io.FileOutputStream; import java.io.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"; diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/poi/PoiWriteTest.java b/src/test/java/com/alibaba/easyexcel/test/temp/poi/PoiWriteTest.java index 02e38c0..5c1620e 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/poi/PoiWriteTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/poi/PoiWriteTest.java @@ -5,6 +5,7 @@ import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.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 clazz = TestCell.class; diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/simple/HgTest.java b/src/test/java/com/alibaba/easyexcel/test/temp/simple/HgTest.java index ad07b70..2eb4d1a 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/simple/HgTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/simple/HgTest.java @@ -27,7 +27,7 @@ public class HgTest { @Test public void hh() throws IOException { List 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)); } diff --git a/src/test/resources/demo/fill/complex.xlsx b/src/test/resources/demo/fill/complex.xlsx new file mode 100644 index 0000000..5376713 Binary files /dev/null and b/src/test/resources/demo/fill/complex.xlsx differ diff --git a/src/test/resources/demo/fill/complexFillWithTable.xlsx b/src/test/resources/demo/fill/complexFillWithTable.xlsx new file mode 100644 index 0000000..4de1a1e Binary files /dev/null and b/src/test/resources/demo/fill/complexFillWithTable.xlsx differ diff --git a/src/test/resources/demo/fill/horizontal.xlsx b/src/test/resources/demo/fill/horizontal.xlsx new file mode 100644 index 0000000..c8b4564 Binary files /dev/null and b/src/test/resources/demo/fill/horizontal.xlsx differ diff --git a/src/test/resources/demo/fill/list.xlsx b/src/test/resources/demo/fill/list.xlsx new file mode 100644 index 0000000..717cb49 Binary files /dev/null and b/src/test/resources/demo/fill/list.xlsx differ diff --git a/src/test/resources/demo/fill/simple.xlsx b/src/test/resources/demo/fill/simple.xlsx new file mode 100644 index 0000000..7514d1d Binary files /dev/null and b/src/test/resources/demo/fill/simple.xlsx differ diff --git a/src/test/resources/fill/complex.xls b/src/test/resources/fill/complex.xls new file mode 100644 index 0000000..d575895 Binary files /dev/null and b/src/test/resources/fill/complex.xls differ diff --git a/src/test/resources/fill/complex.xlsx b/src/test/resources/fill/complex.xlsx new file mode 100644 index 0000000..5376713 Binary files /dev/null and b/src/test/resources/fill/complex.xlsx differ diff --git a/src/test/resources/fill/horizontal.xls b/src/test/resources/fill/horizontal.xls new file mode 100644 index 0000000..570f901 Binary files /dev/null and b/src/test/resources/fill/horizontal.xls differ diff --git a/src/test/resources/fill/horizontal.xlsx b/src/test/resources/fill/horizontal.xlsx new file mode 100644 index 0000000..c8b4564 Binary files /dev/null and b/src/test/resources/fill/horizontal.xlsx differ diff --git a/src/test/resources/fill/simple.xls b/src/test/resources/fill/simple.xls new file mode 100644 index 0000000..ea66e94 Binary files /dev/null and b/src/test/resources/fill/simple.xls differ diff --git a/src/test/resources/fill/simple.xlsx b/src/test/resources/fill/simple.xlsx index b5d7e19..be1753c 100644 Binary files a/src/test/resources/fill/simple.xlsx and b/src/test/resources/fill/simple.xlsx differ diff --git a/src/test/resources/large/fill.xlsx b/src/test/resources/large/fill.xlsx new file mode 100644 index 0000000..c3c376d Binary files /dev/null and b/src/test/resources/large/fill.xlsx differ