Browse Source

修复忽略字段后可能排序不一致的问题

developing
Jiaju Zhuang 3 years ago
parent
commit
ba8f599943
  1. 5
      src/main/java/com/alibaba/excel/metadata/property/ExcelHeadProperty.java
  2. 78
      src/main/java/com/alibaba/excel/util/ClassUtils.java
  3. 17
      src/main/java/com/alibaba/excel/util/MapUtils.java
  4. 34
      src/main/java/com/alibaba/excel/write/executor/ExcelWriteAddExecutor.java
  5. 25
      src/test/java/com/alibaba/easyexcel/test/temp/WriteV33Test.java
  6. 2
      update.md

5
src/main/java/com/alibaba/excel/metadata/property/ExcelHeadProperty.java

@ -120,14 +120,15 @@ public class ExcelHeadProperty {
return;
}
// Declared fields
Map<Integer, Field> sortedAllFiledMap = new TreeMap<Integer, Field>();
Map<Integer, Field> indexFiledMap = new TreeMap<Integer, Field>();
Map<Integer, Field> sortedAllFiledMap = MapUtils.newTreeMap();
Map<Integer, Field> indexFiledMap = MapUtils.newTreeMap();
boolean needIgnore = (holder instanceof AbstractWriteHolder) && (
!CollectionUtils.isEmpty(((AbstractWriteHolder)holder).getExcludeColumnFieldNames()) || !CollectionUtils
.isEmpty(((AbstractWriteHolder)holder).getExcludeColumnIndexes()) || !CollectionUtils
.isEmpty(((AbstractWriteHolder)holder).getIncludeColumnFieldNames()) || !CollectionUtils
.isEmpty(((AbstractWriteHolder)holder).getIncludeColumnIndexes()));
ClassUtils.declaredFields(headClazz, sortedAllFiledMap, indexFiledMap, ignoreMap, needIgnore, holder);
for (Map.Entry<Integer, Field> entry : sortedAllFiledMap.entrySet()) {

78
src/main/java/com/alibaba/excel/util/ClassUtils.java

@ -1,13 +1,5 @@
package com.alibaba.excel.util;
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.exception.ExcelCommonException;
import com.alibaba.excel.metadata.BaseRowModel;
import com.alibaba.excel.metadata.Holder;
import com.alibaba.excel.write.metadata.holder.WriteHolder;
import java.lang.ref.SoftReference;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
@ -21,7 +13,6 @@ import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
@ -38,6 +29,16 @@ public class ClassUtils {
public static final Map<Class<?>, SoftReference<FieldCache>> FIELD_CACHE = new ConcurrentHashMap<>();
/**
* Parsing filed in the class
*
* @param clazz Need to parse the class
* @param sortedAllFiledMap Complete the map of sorts
* @param indexFiledMap Use the index to sort fields
* @param ignoreMap You want to ignore field map
* @param needIgnore If you want to ignore fields need to ignore
* @param holder holder
*/
public static void declaredFields(Class<?> clazz, Map<Integer, Field> sortedAllFiledMap,
Map<Integer, Field> indexFiledMap, Map<String, Field> ignoreMap, Boolean needIgnore, Holder holder) {
FieldCache fieldCache = getFieldCache(clazz);
@ -47,11 +48,11 @@ public class ClassUtils {
if (ignoreMap != null) {
ignoreMap.putAll(fieldCache.getIgnoreMap());
}
Map<Integer, Field> tempIndexFildMap = indexFiledMap;
if (tempIndexFildMap == null) {
tempIndexFildMap = new TreeMap<Integer, Field>();
Map<Integer, Field> tempIndexFieldMap = indexFiledMap;
if (tempIndexFieldMap == null) {
tempIndexFieldMap = MapUtils.newTreeMap();
}
tempIndexFildMap.putAll(fieldCache.getIndexFiledMap());
tempIndexFieldMap.putAll(fieldCache.getIndexFiledMap());
Map<Integer, Field> originSortedAllFiledMap = fieldCache.getSortedAllFiledMap();
if (!needIgnore) {
@ -59,26 +60,29 @@ public class ClassUtils {
return;
}
// 获取到属性字段的最大index
int maxIndex = -1;
for (Integer filedIndex : originSortedAllFiledMap.keySet()) {
maxIndex = Math.max(filedIndex, maxIndex);
int index = 0;
for (Map.Entry<Integer, Field> entry : originSortedAllFiledMap.entrySet()) {
Integer key = entry.getKey();
Field field = entry.getValue();
// The current field needs to be ignored
if (((WriteHolder)holder).ignore(entry.getValue().getName(), entry.getKey())) {
if (ignoreMap != null) {
ignoreMap.put(field.getName(), field);
}
tempIndexFieldMap.remove(index);
} else {
// Mandatory sorted fields
if (tempIndexFieldMap.containsKey(key)) {
sortedAllFiledMap.put(key, field);
} else {
// Need to reorder automatically
// Check whether the current key is already in use
while (sortedAllFiledMap.containsKey(index)) {
index++;
}
// 被忽略的属性数量
int ignoreNum = 0;
// 当有属性被忽略时,需要将其后面的所有属性 index 前移
for (int index = 0; index <= maxIndex; index++) {
Field field = originSortedAllFiledMap.get(index);
String name = field == null? null: field.getName();
if (((WriteHolder) holder).ignore(name, index)) {
if (ignoreMap != null && name != null) {
ignoreMap.put(name, field);
sortedAllFiledMap.put(index++, field);
}
tempIndexFildMap.remove(index);
ignoreNum++;
} else if(field != null){
int finalIndex = index - ignoreNum;
sortedAllFiledMap.put(finalIndex, field);
}
}
}
@ -187,19 +191,15 @@ public class ClassUtils {
if (excelProperty != null) {
order = excelProperty.order();
}
List<Field> orderFiledList = orderFiledMap.get(order);
if (orderFiledList == null) {
orderFiledList = new ArrayList<Field>();
orderFiledMap.put(order, orderFiledList);
}
List<Field> orderFiledList = orderFiledMap.computeIfAbsent(order, key -> ListUtils.newArrayList());
orderFiledList.add(field);
}
private static class FieldCache {
private Map<Integer, Field> sortedAllFiledMap;
private Map<Integer, Field> indexFiledMap;
private Map<String, Field> ignoreMap;
private final Map<Integer, Field> sortedAllFiledMap;
private final Map<Integer, Field> indexFiledMap;
private final Map<String, Field> ignoreMap;
public FieldCache(Map<Integer, Field> sortedAllFiledMap, Map<Integer, Field> indexFiledMap,
Map<String, Field> ignoreMap) {

17
src/main/java/com/alibaba/excel/util/MapUtils.java

@ -2,6 +2,7 @@ package com.alibaba.excel.util;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.TreeMap;
/**
* Map utils
@ -30,6 +31,22 @@ public class MapUtils {
return new HashMap<>(16);
}
/**
* Creates a <i>mutable</i>, empty {@code TreeMap} instance using the natural ordering of its
* elements.
*
* <p><b>Note:</b> if mutability is not required, use {@link ImmutableSortedMap#of()} instead.
*
* <p><b>Note for Java 7 and later:</b> this method is now unnecessary and should be treated as
* deprecated. Instead, use the {@code TreeMap} constructor directly, taking advantage of the new
* <a href="http://goo.gl/iz2Wi">"diamond" syntax</a>.
*
* @return a new, empty {@code TreeMap}
*/
public static <K extends Comparable, V> TreeMap<K, V> newTreeMap() {
return new TreeMap<>();
}
/**
* Creates a {@code HashMap} instance, with a high enough "initial capacity" that it <i>should</i>
* hold {@code expectedSize} elements without growth. This behavior cannot be broadly guaranteed,

34
src/main/java/com/alibaba/excel/write/executor/ExcelWriteAddExecutor.java

@ -1,6 +1,5 @@
package com.alibaba.excel.write.executor;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
@ -19,23 +18,17 @@ import com.alibaba.excel.util.ClassUtils;
import com.alibaba.excel.util.FieldUtils;
import com.alibaba.excel.util.WorkBookUtil;
import com.alibaba.excel.util.WriteHandlerUtils;
import com.alibaba.excel.write.metadata.holder.AbstractWriteHolder;
import com.alibaba.excel.write.metadata.CollectionRowData;
import com.alibaba.excel.write.metadata.MapRowData;
import com.alibaba.excel.write.metadata.RowData;
import com.alibaba.excel.write.metadata.holder.WriteHolder;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
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 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
*
@ -190,16 +183,13 @@ public class ExcelWriteAddExecutor extends AbstractExcelWriteExecutor {
return;
}
// 获取当前的使用的 holder
WriteHolder holder = writeContext.currentWriteHolder();
boolean needIgnore = (holder instanceof AbstractWriteHolder) && (
!CollectionUtils.isEmpty(((AbstractWriteHolder) holder).getExcludeColumnFiledNames()) || !CollectionUtils
.isEmpty(((AbstractWriteHolder) holder).getExcludeColumnIndexes()) || !CollectionUtils
.isEmpty(((AbstractWriteHolder) holder).getIncludeColumnFiledNames()) || !CollectionUtils
.isEmpty(((AbstractWriteHolder) holder).getIncludeColumnIndexes()));
ClassUtils.declaredFields(clazz, sortedAllFiledMap,
writeContext.writeWorkbookHolder().getWriteWorkbook().getConvertAllFiled(), needIgnore, holder);
WriteSheetHolder writeSheetHolder = writeContext.writeSheetHolder();
boolean needIgnore =
!CollectionUtils.isEmpty(writeSheetHolder.getExcludeColumnFieldNames()) || !CollectionUtils
.isEmpty(writeSheetHolder.getExcludeColumnIndexes()) || !CollectionUtils
.isEmpty(writeSheetHolder.getIncludeColumnFieldNames()) || !CollectionUtils
.isEmpty(writeSheetHolder.getIncludeColumnIndexes());
ClassUtils.declaredFields(clazz, sortedAllFiledMap, needIgnore, writeSheetHolder);
}
}

25
src/test/java/com/alibaba/easyexcel/test/temp/WriteV33Test.java

@ -2,9 +2,11 @@ package com.alibaba.easyexcel.test.temp;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import com.alibaba.easyexcel.test.demo.write.DemoData;
import com.alibaba.easyexcel.test.demo.write.IndexData;
import com.alibaba.easyexcel.test.temp.data.DataType;
import com.alibaba.easyexcel.test.temp.data.HeadType;
import com.alibaba.easyexcel.test.util.TestFileUtil;
@ -80,4 +82,27 @@ public class WriteV33Test {
vo.setSecRemark("22222");
return Collections.singletonList(vo);
}
@Test
public void indexWrite() {
String fileName = TestFileUtil.getPath() + "indexWrite" + System.currentTimeMillis() + ".xlsx";
// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
EasyExcel.write(fileName, IndexData.class)
.excludeColumnIndexes(Collections.singleton(0))
.sheet("模板")
.excludeColumnIndexes(Collections.singleton(1))
.doWrite(indexData());
}
private List<IndexData> indexData() {
List<IndexData> list = new ArrayList<IndexData>();
for (int i = 0; i < 10; i++) {
IndexData data = new IndexData();
data.setString("字符串" + i);
data.setDate(new Date());
data.setDoubleData(0.56);
list.add(data);
}
return list;
}
}

2
update.md

@ -26,6 +26,8 @@
* 修复某些特殊的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

Loading…
Cancel
Save