Browse Source

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

developing
Jiaju Zhuang 3 years ago
parent
commit
ba8f599943
  1. 5
      src/main/java/com/alibaba/excel/metadata/property/ExcelHeadProperty.java
  2. 80
      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; return;
} }
// Declared fields // Declared fields
Map<Integer, Field> sortedAllFiledMap = new TreeMap<Integer, Field>(); Map<Integer, Field> sortedAllFiledMap = MapUtils.newTreeMap();
Map<Integer, Field> indexFiledMap = new TreeMap<Integer, Field>(); Map<Integer, Field> indexFiledMap = MapUtils.newTreeMap();
boolean needIgnore = (holder instanceof AbstractWriteHolder) && ( boolean needIgnore = (holder instanceof AbstractWriteHolder) && (
!CollectionUtils.isEmpty(((AbstractWriteHolder)holder).getExcludeColumnFieldNames()) || !CollectionUtils !CollectionUtils.isEmpty(((AbstractWriteHolder)holder).getExcludeColumnFieldNames()) || !CollectionUtils
.isEmpty(((AbstractWriteHolder)holder).getExcludeColumnIndexes()) || !CollectionUtils .isEmpty(((AbstractWriteHolder)holder).getExcludeColumnIndexes()) || !CollectionUtils
.isEmpty(((AbstractWriteHolder)holder).getIncludeColumnFieldNames()) || !CollectionUtils .isEmpty(((AbstractWriteHolder)holder).getIncludeColumnFieldNames()) || !CollectionUtils
.isEmpty(((AbstractWriteHolder)holder).getIncludeColumnIndexes())); .isEmpty(((AbstractWriteHolder)holder).getIncludeColumnIndexes()));
ClassUtils.declaredFields(headClazz, sortedAllFiledMap, indexFiledMap, ignoreMap, needIgnore, holder); ClassUtils.declaredFields(headClazz, sortedAllFiledMap, indexFiledMap, ignoreMap, needIgnore, holder);
for (Map.Entry<Integer, Field> entry : sortedAllFiledMap.entrySet()) { for (Map.Entry<Integer, Field> entry : sortedAllFiledMap.entrySet()) {

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

@ -1,13 +1,5 @@
package com.alibaba.excel.util; 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.ref.SoftReference;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
@ -21,7 +13,6 @@ import java.util.Map;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import com.alibaba.excel.annotation.ExcelIgnore; import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.ExcelProperty;
@ -38,6 +29,16 @@ public class ClassUtils {
public static final Map<Class<?>, SoftReference<FieldCache>> FIELD_CACHE = new ConcurrentHashMap<>(); 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, public static void declaredFields(Class<?> clazz, Map<Integer, Field> sortedAllFiledMap,
Map<Integer, Field> indexFiledMap, Map<String, Field> ignoreMap, Boolean needIgnore, Holder holder) { Map<Integer, Field> indexFiledMap, Map<String, Field> ignoreMap, Boolean needIgnore, Holder holder) {
FieldCache fieldCache = getFieldCache(clazz); FieldCache fieldCache = getFieldCache(clazz);
@ -47,11 +48,11 @@ public class ClassUtils {
if (ignoreMap != null) { if (ignoreMap != null) {
ignoreMap.putAll(fieldCache.getIgnoreMap()); ignoreMap.putAll(fieldCache.getIgnoreMap());
} }
Map<Integer, Field> tempIndexFildMap = indexFiledMap; Map<Integer, Field> tempIndexFieldMap = indexFiledMap;
if (tempIndexFildMap == null) { if (tempIndexFieldMap == null) {
tempIndexFildMap = new TreeMap<Integer, Field>(); tempIndexFieldMap = MapUtils.newTreeMap();
} }
tempIndexFildMap.putAll(fieldCache.getIndexFiledMap()); tempIndexFieldMap.putAll(fieldCache.getIndexFiledMap());
Map<Integer, Field> originSortedAllFiledMap = fieldCache.getSortedAllFiledMap(); Map<Integer, Field> originSortedAllFiledMap = fieldCache.getSortedAllFiledMap();
if (!needIgnore) { if (!needIgnore) {
@ -59,26 +60,29 @@ public class ClassUtils {
return; return;
} }
// 获取到属性字段的最大index int index = 0;
int maxIndex = -1; for (Map.Entry<Integer, Field> entry : originSortedAllFiledMap.entrySet()) {
for (Integer filedIndex : originSortedAllFiledMap.keySet()) { Integer key = entry.getKey();
maxIndex = Math.max(filedIndex, maxIndex); Field field = entry.getValue();
}
// 被忽略的属性数量 // The current field needs to be ignored
int ignoreNum = 0; if (((WriteHolder)holder).ignore(entry.getValue().getName(), entry.getKey())) {
// 当有属性被忽略时,需要将其后面的所有属性 index 前移 if (ignoreMap != null) {
for (int index = 0; index <= maxIndex; index++) { ignoreMap.put(field.getName(), field);
Field field = originSortedAllFiledMap.get(index); }
String name = field == null? null: field.getName(); tempIndexFieldMap.remove(index);
if (((WriteHolder) holder).ignore(name, index)) { } else {
if (ignoreMap != null && name != null) { // Mandatory sorted fields
ignoreMap.put(name, field); 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++;
}
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) { if (excelProperty != null) {
order = excelProperty.order(); order = excelProperty.order();
} }
List<Field> orderFiledList = orderFiledMap.get(order); List<Field> orderFiledList = orderFiledMap.computeIfAbsent(order, key -> ListUtils.newArrayList());
if (orderFiledList == null) {
orderFiledList = new ArrayList<Field>();
orderFiledMap.put(order, orderFiledList);
}
orderFiledList.add(field); orderFiledList.add(field);
} }
private static class FieldCache { private static class FieldCache {
private Map<Integer, Field> sortedAllFiledMap; private final Map<Integer, Field> sortedAllFiledMap;
private Map<Integer, Field> indexFiledMap; private final Map<Integer, Field> indexFiledMap;
private Map<String, Field> ignoreMap; private final Map<String, Field> ignoreMap;
public FieldCache(Map<Integer, Field> sortedAllFiledMap, Map<Integer, Field> indexFiledMap, public FieldCache(Map<Integer, Field> sortedAllFiledMap, Map<Integer, Field> indexFiledMap,
Map<String, Field> ignoreMap) { 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.HashMap;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.TreeMap;
/** /**
* Map utils * Map utils
@ -30,6 +31,22 @@ public class MapUtils {
return new HashMap<>(16); 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> * 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, * 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; package com.alibaba.excel.write.executor;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; 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.FieldUtils;
import com.alibaba.excel.util.WorkBookUtil; import com.alibaba.excel.util.WorkBookUtil;
import com.alibaba.excel.util.WriteHandlerUtils; 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.WriteHolder;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import net.sf.cglib.beans.BeanMap; 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.Cell;
import org.apache.poi.ss.usermodel.Row; 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 * Add the data into excel
* *
@ -190,16 +183,13 @@ public class ExcelWriteAddExecutor extends AbstractExcelWriteExecutor {
return; return;
} }
// 获取当前的使用的 holder WriteSheetHolder writeSheetHolder = writeContext.writeSheetHolder();
WriteHolder holder = writeContext.currentWriteHolder(); boolean needIgnore =
boolean needIgnore = (holder instanceof AbstractWriteHolder) && ( !CollectionUtils.isEmpty(writeSheetHolder.getExcludeColumnFieldNames()) || !CollectionUtils
!CollectionUtils.isEmpty(((AbstractWriteHolder) holder).getExcludeColumnFiledNames()) || !CollectionUtils .isEmpty(writeSheetHolder.getExcludeColumnIndexes()) || !CollectionUtils
.isEmpty(((AbstractWriteHolder) holder).getExcludeColumnIndexes()) || !CollectionUtils .isEmpty(writeSheetHolder.getIncludeColumnFieldNames()) || !CollectionUtils
.isEmpty(((AbstractWriteHolder) holder).getIncludeColumnFiledNames()) || !CollectionUtils .isEmpty(writeSheetHolder.getIncludeColumnIndexes());
.isEmpty(((AbstractWriteHolder) holder).getIncludeColumnIndexes())); ClassUtils.declaredFields(clazz, sortedAllFiledMap, needIgnore, writeSheetHolder);
ClassUtils.declaredFields(clazz, sortedAllFiledMap,
writeContext.writeWorkbookHolder().getWriteWorkbook().getConvertAllFiled(), needIgnore, holder);
} }
} }

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.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Date;
import java.util.List; import java.util.List;
import com.alibaba.easyexcel.test.demo.write.DemoData; 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.DataType;
import com.alibaba.easyexcel.test.temp.data.HeadType; import com.alibaba.easyexcel.test.temp.data.HeadType;
import com.alibaba.easyexcel.test.util.TestFileUtil; import com.alibaba.easyexcel.test.util.TestFileUtil;
@ -80,4 +82,27 @@ public class WriteV33Test {
vo.setSecRemark("22222"); vo.setSecRemark("22222");
return Collections.singletonList(vo); 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) * 修复某些特殊的excel读取失败的问题 [Issue #1595](https://github.com/alibaba/easyexcel/issues/1595)
* 修复不创建对象写入数据异常 [Issue #1702](https://github.com/alibaba/easyexcel/issues/1702) * 修复不创建对象写入数据异常 [Issue #1702](https://github.com/alibaba/easyexcel/issues/1702)
* 修复头和数据对象不一致会覆盖的问题 [Issue #1870](https://github.com/alibaba/easyexcel/issues/1870) * 修复头和数据对象不一致会覆盖的问题 [Issue #1870](https://github.com/alibaba/easyexcel/issues/1870)
* 修复忽略字段后可能排序不一致的问题
# 2.2.10 # 2.2.10

Loading…
Cancel
Save