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 4b52e213..3562501d 100644 --- a/src/main/java/com/alibaba/excel/metadata/property/ExcelHeadProperty.java +++ b/src/main/java/com/alibaba/excel/metadata/property/ExcelHeadProperty.java @@ -120,14 +120,15 @@ public class ExcelHeadProperty { return; } // Declared fields - Map sortedAllFiledMap = new TreeMap(); - Map indexFiledMap = new TreeMap(); + Map sortedAllFiledMap = MapUtils.newTreeMap(); + Map 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 entry : sortedAllFiledMap.entrySet()) { diff --git a/src/main/java/com/alibaba/excel/util/ClassUtils.java b/src/main/java/com/alibaba/excel/util/ClassUtils.java index bd41b17e..50e9351a 100644 --- a/src/main/java/com/alibaba/excel/util/ClassUtils.java +++ b/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, SoftReference> 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 sortedAllFiledMap, Map indexFiledMap, Map ignoreMap, Boolean needIgnore, Holder holder) { FieldCache fieldCache = getFieldCache(clazz); @@ -47,11 +48,11 @@ public class ClassUtils { if (ignoreMap != null) { ignoreMap.putAll(fieldCache.getIgnoreMap()); } - Map tempIndexFildMap = indexFiledMap; - if (tempIndexFildMap == null) { - tempIndexFildMap = new TreeMap(); + Map tempIndexFieldMap = indexFiledMap; + if (tempIndexFieldMap == null) { + tempIndexFieldMap = MapUtils.newTreeMap(); } - tempIndexFildMap.putAll(fieldCache.getIndexFiledMap()); + tempIndexFieldMap.putAll(fieldCache.getIndexFiledMap()); Map 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 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); + int index = 0; + for (Map.Entry 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++; + } + 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 orderFiledList = orderFiledMap.get(order); - if (orderFiledList == null) { - orderFiledList = new ArrayList(); - orderFiledMap.put(order, orderFiledList); - } + List orderFiledList = orderFiledMap.computeIfAbsent(order, key -> ListUtils.newArrayList()); orderFiledList.add(field); } private static class FieldCache { - private Map sortedAllFiledMap; - private Map indexFiledMap; - private Map ignoreMap; + private final Map sortedAllFiledMap; + private final Map indexFiledMap; + private final Map ignoreMap; public FieldCache(Map sortedAllFiledMap, Map indexFiledMap, Map ignoreMap) { diff --git a/src/main/java/com/alibaba/excel/util/MapUtils.java b/src/main/java/com/alibaba/excel/util/MapUtils.java index d46da90a..8e8a2778 100644 --- a/src/main/java/com/alibaba/excel/util/MapUtils.java +++ b/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 mutable, empty {@code TreeMap} instance using the natural ordering of its + * elements. + * + *

Note: if mutability is not required, use {@link ImmutableSortedMap#of()} instead. + * + *

Note for Java 7 and later: this method is now unnecessary and should be treated as + * deprecated. Instead, use the {@code TreeMap} constructor directly, taking advantage of the new + * "diamond" syntax. + * + * @return a new, empty {@code TreeMap} + */ + public static TreeMap newTreeMap() { + return new TreeMap<>(); + } + /** * Creates a {@code HashMap} instance, with a high enough "initial capacity" that it should * hold {@code expectedSize} elements without growth. This behavior cannot be broadly guaranteed, 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 9a927176..e053d81f 100644 --- a/src/main/java/com/alibaba/excel/write/executor/ExcelWriteAddExecutor.java +++ b/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); } } 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 c992522f..fc85050d 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/WriteV33Test.java +++ b/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() { + List list = new ArrayList(); + 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; + } } diff --git a/update.md b/update.md index 9d91fae3..c29a6944 100644 --- a/update.md +++ b/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