Browse Source

修复头和数据对象不一致会覆盖的问题 [Issue #1870]

pull/2077/head
Jiaju Zhuang 3 years ago
parent
commit
e5b579fdfa
  1. 43
      src/main/java/com/alibaba/excel/write/executor/ExcelWriteAddExecutor.java
  2. 37
      src/test/java/com/alibaba/easyexcel/test/temp/WriteV33Test.java
  3. 29
      src/test/java/com/alibaba/easyexcel/test/temp/data/DataType.java
  4. 24
      src/test/java/com/alibaba/easyexcel/test/temp/data/HeadType.java
  5. 50
      update.md

43
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<Integer, Field> sortedAllFiledMap) {
Map<Integer, Field> sortedAllFiledMap) {
if (oneRowData == null) {
return;
}
@ -94,14 +85,15 @@ public class ExcelWriteAddExecutor extends AbstractExcelWriteExecutor {
}
Map<Integer, Head> headMap = writeContext.currentWriteHolder().excelWriteHeadProperty().getHeadMap();
int dataIndex = 0;
int cellIndex = 0;
int maxCellIndex = -1;
for (Map.Entry<Integer, Head> 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<Integer, Field> sortedAllFiledMap) {
Map<Integer, Field> sortedAllFiledMap) {
WriteHolder currentWriteHolder = writeContext.currentWriteHolder();
BeanMap beanMap = BeanMapUtils.create(oneRowData);
Set<String> beanMapHandledSet = new HashSet<String>();
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<Integer, Head> headMap = writeContext.currentWriteHolder().excelWriteHeadProperty().getHeadMap();
Map<Integer, ExcelContentProperty> contentPropertyMap =
writeContext.currentWriteHolder().excelWriteHeadProperty().getContentPropertyMap();
for (Map.Entry<Integer, ExcelContentProperty> entry : contentPropertyMap.entrySet()) {
cellIndex = entry.getKey();
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<String, Field> ignoreMap = writeContext.currentWriteHolder().excelWriteHeadProperty().getIgnoreMap();
initSortedAllFiledMapFieldList(oneRowData.getClass(), sortedAllFiledMap);
for (Map.Entry<Integer, Field> 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);

37
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<DataType> 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<DataType> getData() {
DataType vo = new DataType();
vo.setId(738);
vo.setFirstRemark("1222");
vo.setSecRemark("22222");
return Collections.singletonList(vo);
}
}

29
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;
}

24
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;
}

50
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<String>>,但是数据用List<Class>导致的空指针
# 2.0.0-beta5
* 修复在读取值的时候读取了额外值导致数据转换异常
# 2.0.0-beta4
* 修改在传入List<List<Object>>判断行数错误 [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
修复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
修复拿到一行数据后,存到list中,但最后处理时候变为空的bug。
# 1.0.1
完善测试用例,防止歧义,模型字段映射不上时候有抛异常,改为提醒。
Loading…
Cancel
Save