diff --git a/src/main/java/com/alibaba/excel/write/executor/ExcelWriteAddExecutor.java b/src/main/java/com/alibaba/excel/write/executor/ExcelWriteAddExecutor.java index 2bd63b6a..c0d2f47f 100644 --- a/src/main/java/com/alibaba/excel/write/executor/ExcelWriteAddExecutor.java +++ b/src/main/java/com/alibaba/excel/write/executor/ExcelWriteAddExecutor.java @@ -24,20 +24,11 @@ import com.alibaba.excel.write.metadata.RowData; import com.alibaba.excel.write.metadata.holder.WriteHolder; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; + import net.sf.cglib.beans.BeanMap; import org.apache.commons.collections4.CollectionUtils; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.Row; - -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; /** * Add the data into excel @@ -70,7 +61,7 @@ public class ExcelWriteAddExecutor extends AbstractExcelWriteExecutor { } private void addOneRowOfDataToExcel(Object oneRowData, int n, int relativeRowIndex, - Map sortedAllFiledMap) { + Map sortedAllFiledMap) { if (oneRowData == null) { return; } @@ -94,14 +85,15 @@ public class ExcelWriteAddExecutor extends AbstractExcelWriteExecutor { } Map headMap = writeContext.currentWriteHolder().excelWriteHeadProperty().getHeadMap(); int dataIndex = 0; - int cellIndex = 0; + int maxCellIndex = -1; for (Map.Entry entry : headMap.entrySet()) { if (dataIndex >= oneRowData.size()) { return; } - cellIndex = entry.getKey(); + int cellIndex = entry.getKey(); Head head = entry.getValue(); doAddBasicTypeToExcel(oneRowData, head, row, relativeRowIndex, dataIndex++, cellIndex); + maxCellIndex = Math.max(maxCellIndex, cellIndex); } // Finish if (dataIndex >= oneRowData.size()) { @@ -109,17 +101,16 @@ public class ExcelWriteAddExecutor extends AbstractExcelWriteExecutor { } // fix https://github.com/alibaba/easyexcel/issues/1702 // If there is data, it is written to the next cell - if (dataIndex != 0) { - cellIndex++; - } + maxCellIndex++; + int size = oneRowData.size() - dataIndex; for (int i = 0; i < size; i++) { - doAddBasicTypeToExcel(oneRowData, null, row, relativeRowIndex, dataIndex++, cellIndex++); + doAddBasicTypeToExcel(oneRowData, null, row, relativeRowIndex, dataIndex++, maxCellIndex++); } } private void doAddBasicTypeToExcel(RowData oneRowData, Head head, Row row, int relativeRowIndex, int dataIndex, - int cellIndex) { + 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); @@ -130,18 +121,18 @@ public class ExcelWriteAddExecutor extends AbstractExcelWriteExecutor { } private void addJavaObjectToExcel(Object oneRowData, Row row, int relativeRowIndex, - Map sortedAllFiledMap) { + Map sortedAllFiledMap) { WriteHolder currentWriteHolder = writeContext.currentWriteHolder(); BeanMap beanMap = BeanMapUtils.create(oneRowData); Set beanMapHandledSet = new HashSet(); - int cellIndex; + int maxCellIndex = -1; // 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(); + int cellIndex = entry.getKey(); ExcelContentProperty excelContentProperty = entry.getValue(); String name = FieldUtils.resolveCglibFieldName(excelContentProperty.getField()); if (!beanMap.containsKey(name)) { @@ -157,13 +148,15 @@ public class ExcelWriteAddExecutor extends AbstractExcelWriteExecutor { null, cell, value, excelContentProperty, head, relativeRowIndex); WriteHandlerUtils.afterCellDispose(writeContext, cellData, cell, head, relativeRowIndex, Boolean.FALSE); beanMapHandledSet.add(name); + maxCellIndex = Math.max(maxCellIndex, cellIndex); } - cellIndex++; } // Finish if (beanMapHandledSet.size() == beanMap.size()) { return; } + maxCellIndex++; + Map ignoreMap = writeContext.currentWriteHolder().excelWriteHeadProperty().getIgnoreMap(); initSortedAllFiledMapFieldList(oneRowData.getClass(), sortedAllFiledMap); for (Map.Entry entry : sortedAllFiledMap.entrySet()) { @@ -175,8 +168,10 @@ public class ExcelWriteAddExecutor extends AbstractExcelWriteExecutor { continue; } Object value = beanMap.get(filedName); - WriteHandlerUtils.beforeCellCreate(writeContext, row, null, cellIndex, relativeRowIndex, Boolean.FALSE); - Cell cell = WorkBookUtil.createCell(row, cellIndex++); + WriteHandlerUtils.beforeCellCreate(writeContext, row, null, maxCellIndex, relativeRowIndex, Boolean.FALSE); + // fix https://github.com/alibaba/easyexcel/issues/1870 + // If there is data, it is written to the next cell + Cell cell = WorkBookUtil.createCell(row, maxCellIndex++); WriteHandlerUtils.afterCellCreate(writeContext, cell, null, relativeRowIndex, Boolean.FALSE); WriteCellData cellData = converterAndSet(currentWriteHolder, FieldUtils.getFieldClass(beanMap, filedName), null, cell, value, null, null, relativeRowIndex); diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/WriteV33Test.java b/src/test/java/com/alibaba/easyexcel/test/temp/WriteV33Test.java index ea7b39a2..c992522f 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/WriteV33Test.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/WriteV33Test.java @@ -1,20 +1,23 @@ package com.alibaba.easyexcel.test.temp; import java.util.ArrayList; +import java.util.Collections; import java.util.List; -import org.junit.Ignore; -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.temp.data.DataType; +import com.alibaba.easyexcel.test.temp.data.HeadType; import com.alibaba.easyexcel.test.util.TestFileUtil; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.ExcelWriter; import com.alibaba.excel.write.merge.OnceAbsoluteMergeStrategy; import com.alibaba.excel.write.metadata.WriteSheet; +import org.junit.Ignore; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * 临时测试 * @@ -32,7 +35,8 @@ public class WriteV33Test { OnceAbsoluteMergeStrategy onceAbsoluteMergeStrategy = new OnceAbsoluteMergeStrategy(2, 2, 0, 1); // 这里 指定文件 - ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).registerWriteHandler(onceAbsoluteMergeStrategy).build(); + ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).registerWriteHandler( + onceAbsoluteMergeStrategy).build(); WriteSheet writeSheet1 = EasyExcel.writerSheet(1, "模板1").build(); WriteSheet writeSheet2 = EasyExcel.writerSheet(2, "模板2").build(); WriteSheet writeSheet3 = EasyExcel.writerSheet(3, "模板3").build(); @@ -55,4 +59,25 @@ public class WriteV33Test { return list; } + @Test + public void test33() throws Exception { + List data = getData(); + String fileName = TestFileUtil.getPath() + "repeatedWrite" + System.currentTimeMillis() + ".xlsx"; + + ExcelWriter excelWriter = null; + excelWriter = EasyExcel.write(fileName).build(); + WriteSheet writeSheet = EasyExcel.writerSheet(1, "test") + .head(HeadType.class) + .build(); + excelWriter.write(data, writeSheet); + excelWriter.finish(); + } + + private List getData() { + DataType vo = new DataType(); + vo.setId(738); + vo.setFirstRemark("1222"); + vo.setSecRemark("22222"); + return Collections.singletonList(vo); + } } diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/data/DataType.java b/src/test/java/com/alibaba/easyexcel/test/temp/data/DataType.java new file mode 100644 index 00000000..8a4b1fb7 --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/temp/data/DataType.java @@ -0,0 +1,29 @@ +package com.alibaba.easyexcel.test.temp.data; + +import com.alibaba.excel.annotation.ExcelProperty; + +import lombok.Data; + +@Data +public class DataType { + /** + * 任务id + */ + @ExcelProperty("任务ID") + private Integer id; + + @ExcelProperty("多余字段1") + private String firstSurplus; + + @ExcelProperty("多余字段2") + private String secSurplus; + + @ExcelProperty("多余字段3") + private String thirdSurplus; + + @ExcelProperty(value = "备注1") + private String firstRemark; + + @ExcelProperty(value = "备注2") + private String secRemark; +} diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/data/HeadType.java b/src/test/java/com/alibaba/easyexcel/test/temp/data/HeadType.java new file mode 100644 index 00000000..32bd065e --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/temp/data/HeadType.java @@ -0,0 +1,24 @@ +package com.alibaba.easyexcel.test.temp.data; + +import com.alibaba.excel.annotation.ExcelProperty; + +import lombok.Data; + +@Data +public class HeadType { + + + /** + * 任务id + */ + @ExcelProperty("任务ID") + private Integer id; + + + @ExcelProperty(value = "备注1") + private String firstRemark; + + @ExcelProperty(value = "备注2") + private String secRemark; + +} diff --git a/update.md b/update.md index db002b67..9d91fae3 100644 --- a/update.md +++ b/update.md @@ -1,4 +1,5 @@ # 3.0.0-beta1 + * 升级jdk8 不再支持jdk6 jdk7 * 升级poi 到 4.1.2 * 升级cglib 到 3.3.0 @@ -24,28 +25,35 @@ * 新增头的非空校验 [Issue #1765](https://github.com/alibaba/easyexcel/issues/1765) * 修复某些特殊的excel读取失败的问题 [Issue #1595](https://github.com/alibaba/easyexcel/issues/1595) * 修复不创建对象写入数据异常 [Issue #1702](https://github.com/alibaba/easyexcel/issues/1702) - +* 修复头和数据对象不一致会覆盖的问题 [Issue #1870](https://github.com/alibaba/easyexcel/issues/1870) # 2.2.10 + * 修复读取的时候用string接收数字 可能四舍五入不一致的bug # 2.2.9 + * 修复读取的时候用string接收数字 可能四舍五入不一致的bug # 2.2.8 + * 兼容07在特殊的excel的情况下,读取数据异常 # 2.2.7 + * 修改07在特殊情况下用`String`接收数字会丢小数位的bug # 2.2.6 + * 修改跳着读取03版本空指针bug # 2.2.5 + * `ExcelProperty`新增`order` 用于排序 -* 修复导出指定`index`会导致空行的bug +* 修复导出指定`index`会导致空行的bug # 2.2.4 + * 撤销删除`AbstractMergeStrategy` * 修改默认用String读取数字不使用科学计数法 通过`useScientificFormat`修改 * 修复07版仅有样式的空行 默认不忽略的bug @@ -59,14 +67,17 @@ * 修复`@NumberFormat`注解转换double时可能会丢失精度 [Issue #1306](https://github.com/alibaba/easyexcel/issues/1306) # 2.2.3 + * 修改填充数据空数据的bug [Issue #1274](https://github.com/alibaba/easyexcel/issues/1274) * 回退自定义转换器入参为空 # 2.2.2 + * 修改`sheet`事件未调用的bug * 修复复杂表头不是`index=0`开始 合并异常的bug [Issue #1322](https://github.com/alibaba/easyexcel/issues/1322) # 2.2.1 + * 发布正式版 * 修复第一行为空不会调用`invokeHeadMap`的bug [Issue #993](https://github.com/alibaba/easyexcel/issues/993) * 当类的属性没有按照ExcelProperty的属性index顺序排序的时候,写数据出现错乱 [Issue #1046](https://github.com/alibaba/easyexcel/issues/1046) @@ -76,11 +87,13 @@ * 修复`table`、`sheet`中创建的拦截器不执行`workbook`事件的bug [Issue #1202](https://github.com/alibaba/easyexcel/issues/1202) # 2.2.0-beta2 + * 修复最长匹配策略不同表格会有影响的bug [Issue #1010](https://github.com/alibaba/easyexcel/issues/1010) * `LinkedList`写入的性能问题 #1121 * 修复在某些情况下可能出现不必要的`warn`日志 # 2.2.0-beta1 + * 重写主流程,代码更加优雅 * 修复用String接收日期、数字和excel显示不一致的bug(不是完美修复,但是大部分情况已经兼容) * 降低Ehcache版本 3.7.1(jkd7) -> 3.4.0(jdk6) @@ -98,19 +111,24 @@ * 填充支持多个List对象 # 2.1.7 + * 修复使用1+版本的写法,第1条开始读修改为第0条开始读 # 2.1.6 + * 修复写入只有`sheetName`会抛异常 # 2.1.5 + * 修复部分xlsx没有行号读取异常 * 填充时候支持根据`sheetName`定位`sheet` # 2.1.4 + * 新增参数`useDefaultListener` 可以排除默认对象转换 # 2.1.3 + * 每个java进程单独创建一个缓存目录 [Issue #813](https://github.com/alibaba/easyexcel/issues/813) * 统一修改合并为unsafe,提高大量数据导出的合并的效率 * 修改merge返回参数`relativeRowIndex`为`Integer` @@ -120,9 +138,11 @@ * `SimpleColumnWidthStyleStrategy` 新增 参数`columnIndex` [Issue #806](https://github.com/alibaba/easyexcel/issues/806) # 2.1.2 + * 修复强制创建新行填充,只有一行数据会未填充的bug # 2.1.1 + * 发布正式版 * 修改map返回为LinkedHashMap * 修改同步读取返回对象支持泛型 @@ -138,11 +158,13 @@ * 修复03版无法获取大概总行数的bug # 2.1.0-beta4 + * 修改最长匹配策略会空指针的bug [Issue #747](https://github.com/alibaba/easyexcel/issues/747) * 修改afterRowDispose错误 [Issue #751](https://github.com/alibaba/easyexcel/issues/751) * 修复多个头的情况下会读取数据为空 # 2.1.0-beta3 + * 支持强行指定在内存处理,以支持备注、RichTextString等的写入 * 修复关闭流失败,可能会不删除临时文件的问题 * 支持根据参数自定义导出列 @@ -151,11 +173,13 @@ * 修复填充的时候有数字会异常 # 2.1.0-beta2 + * 修改模板通过流创建报错的bug * 修复空数据未替换掉的bug * 修复空模板会空一行的bug # 2.1.0-beta1 + * 新增支持导入、导出支持公式 * 新增支持读取单元格类型、写入指定单元格类型 * 支持通过模板填充数据 @@ -168,53 +192,65 @@ * 支持导入加密 [Issue #295](https://github.com/alibaba/easyexcel/issues/295) # 2.0.5 + * 优化07版超大文件读取方案 * 支持自己设置超大文件读取参数 * 读取xlsx会改变修改时间的bug [Issue #574](https://github.com/alibaba/easyexcel/issues/574) * 默认读取忽略空行 根据参数ignoreEmptyRow参数设置 # 2.0.4 + * 修复07版整个excel仅存在数字时会出现的NPE * 修复03版 用String接收电话会出现科学计数法的问题 # 2.0.3 + * 修复重大bug 在07版读取文件的时候 小概率导致数字部分丢失 # 2.0.2 + * 修复xls无法获取sheetList的bug [Issue #621](https://github.com/alibaba/easyexcel/issues/621) * 修复监听器转换异常会重复提示的bug # 2.0.1 + * 降级poi为3.17 兼容jdk6 # 2.0.0 + * 修复当cell为空可能会抛出空指针的bug * 修复电话等长数字可能出现科学计数法的问题 [Issue #583](https://github.com/alibaba/easyexcel/issues/583) * 升级为正式版 # 2.0.0-beta6 + * 修复空行读取空指针异常 * 修复写入指定头为List>,但是数据用List导致的空指针 # 2.0.0-beta5 + * 修复在读取值的时候读取了额外值导致数据转换异常 # 2.0.0-beta4 + * 修改在传入List>判断行数错误 [Issue #526](https://github.com/alibaba/easyexcel/issues/526) * 修复在mac 2016 2017导出的excel 可能存在多余字段的问题 * 修复03版 读取无法指定sheet的问题 [Issue #533](https://github.com/alibaba/easyexcel/issues/533) # 2.0.0-beta3 + * 导出完成移除临时目录 [Issue #386](https://github.com/alibaba/easyexcel/issues/386) * 新增读取返回头数据 # 2.0.0-beta2 + * 加速gc回收 [Issue #511](https://github.com/alibaba/easyexcel/issues/511) * 修改空字符串读取可能读取上个字段的数据的bug * 修改换行数据无法读取的bug [Issue #521](https://github.com/alibaba/easyexcel/issues/521) * 修复在空字符串的时候 格式转换异常 [Issue #520](https://github.com/alibaba/easyexcel/issues/520) # 2.0.0-beta1 + * 优化读写逻辑 * 优化读写对外接口 * 加入转换器,方便格式转换 @@ -224,31 +260,41 @@ * 升级poi 到4.0.1 # 1.2.4 + 修复read()方法存在的bug # 1.2.1 + 修复POI在大并发情况下创建临时目录失败的bug -# 1.0.9 +# 1.0.9 + 修复excel超过16列被覆盖的问题,修复数据只有一行时候无法透传的bug。 # 1.0.8 + 如果整行excel数据全部为空,则不解析返回。完善多sheet的解析。 # 1.0.6 + 增加@ExcelColumnNum,修复字符串前后空白,增加过滤功能。 # 1.0.5 + 优化类型转换的性能。 # 1.0.4 + 修复日期类型转换时候数字问题。基础模型支持字段类型int,long,double,boolean,date,string # 1.0.3 + 修复无@ExcelProperty标注的多余字段时候报错。 -# 1.0.2 +# 1.0.2 + 修复拿到一行数据后,存到list中,但最后处理时候变为空的bug。 # 1.0.1 + 完善测试用例,防止歧义,模型字段映射不上时候有抛异常,改为提醒。 \ No newline at end of file