diff --git a/pom.xml b/pom.xml
index be70e6bf..a887a7c6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
4.0.0
com.alibaba
easyexcel
- 2.2.4
+ 2.2.5
jar
easyexcel
diff --git a/src/main/java/com/alibaba/excel/annotation/ExcelProperty.java b/src/main/java/com/alibaba/excel/annotation/ExcelProperty.java
index b107d32e..78262c6f 100644
--- a/src/main/java/com/alibaba/excel/annotation/ExcelProperty.java
+++ b/src/main/java/com/alibaba/excel/annotation/ExcelProperty.java
@@ -32,12 +32,23 @@ public @interface ExcelProperty {
/**
* Index of column
*
- * Read or write it on the index of column,If it's equal to -1, it's sorted by Java class
+ * Read or write it on the index of column,If it's equal to -1, it's sorted by Java class.
+ *
+ * priority: index > order > default sort
*
* @return Index of column
*/
int index() default -1;
+ /**
+ * Defines the sort order for an column.
+ *
+ * priority: index > order > default sort
+ *
+ * @return Order of column
+ */
+ int order() default Integer.MAX_VALUE;
+
/**
* Force the current field to use this converter.
*
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 5a035772..a191260d 100644
--- a/src/main/java/com/alibaba/excel/metadata/property/ExcelHeadProperty.java
+++ b/src/main/java/com/alibaba/excel/metadata/property/ExcelHeadProperty.java
@@ -21,6 +21,7 @@ import com.alibaba.excel.exception.ExcelCommonException;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.Holder;
import com.alibaba.excel.util.ClassUtils;
+import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.excel.util.StringUtils;
import com.alibaba.excel.write.metadata.holder.AbstractWriteHolder;
@@ -117,24 +118,19 @@ public class ExcelHeadProperty {
return;
}
// Declared fields
- List defaultFieldList = new ArrayList();
- Map customFiledMap = new TreeMap();
- ClassUtils.declaredFields(headClazz, defaultFieldList, customFiledMap, ignoreMap, convertAllFiled);
-
- int index = 0;
- for (Field field : defaultFieldList) {
- while (customFiledMap.containsKey(index)) {
- Field customFiled = customFiledMap.get(index);
- customFiledMap.remove(index);
- if (!initOneColumnProperty(holder, index, customFiled, Boolean.TRUE)) {
- index++;
- }
- }
- initOneColumnProperty(holder, index, field, Boolean.FALSE);
- index++;
- }
- for (Map.Entry entry : customFiledMap.entrySet()) {
- initOneColumnProperty(holder, entry.getKey(), entry.getValue(), Boolean.TRUE);
+ Map sortedAllFiledMap = new TreeMap();
+ Map indexFiledMap = new TreeMap();
+
+ 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(headClazz, sortedAllFiledMap, indexFiledMap, ignoreMap, convertAllFiled, needIgnore,
+ holder);
+
+ for (Map.Entry entry : sortedAllFiledMap.entrySet()) {
+ initOneColumnProperty(entry.getKey(), entry.getValue(), indexFiledMap.containsKey(entry.getKey()));
}
headKind = HeadKindEnum.CLASS;
}
@@ -142,18 +138,12 @@ public class ExcelHeadProperty {
/**
* Initialization column property
*
- * @param holder
* @param index
* @param field
* @param forceIndex
* @return Ignore current field
*/
- private boolean initOneColumnProperty(Holder holder, int index, Field field, Boolean forceIndex) {
- if (holder instanceof AbstractWriteHolder) {
- if (((AbstractWriteHolder) holder).ignore(field.getName(), index)) {
- return true;
- }
- }
+ private void initOneColumnProperty(int index, Field field, Boolean forceIndex) {
ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
List tmpHeadList = new ArrayList();
boolean notForceName = excelProperty == null || excelProperty.value().length <= 0
@@ -189,7 +179,6 @@ public class ExcelHeadProperty {
headMap.put(index, head);
contentPropertyMap.put(index, excelContentProperty);
fieldNameContentPropertyMap.put(field.getName(), excelContentProperty);
- return false;
}
public Class getHeadClazz() {
diff --git a/src/main/java/com/alibaba/excel/util/ClassUtils.java b/src/main/java/com/alibaba/excel/util/ClassUtils.java
index 20b30e34..936c325d 100644
--- a/src/main/java/com/alibaba/excel/util/ClassUtils.java
+++ b/src/main/java/com/alibaba/excel/util/ClassUtils.java
@@ -14,8 +14,12 @@ import java.util.concurrent.ConcurrentHashMap;
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.event.Handler;
import com.alibaba.excel.exception.ExcelCommonException;
import com.alibaba.excel.metadata.BaseRowModel;
+import com.alibaba.excel.metadata.Holder;
+import com.alibaba.excel.write.handler.WriteHandler;
+import com.alibaba.excel.write.metadata.holder.WriteHolder;
/**
* Class utils
@@ -23,26 +27,54 @@ import com.alibaba.excel.metadata.BaseRowModel;
* @author Jiaju Zhuang
**/
public class ClassUtils {
+
private static final Map> FIELD_CACHE =
new ConcurrentHashMap>();
- public static void declaredFields(Class clazz, List defaultFieldList, Map customFiledMap,
- Map ignoreMap, Boolean convertAllFiled) {
+ public static void declaredFields(Class clazz, Map sortedAllFiledMap,
+ Map indexFiledMap, Map ignoreMap, Boolean convertAllFiled,
+ Boolean needIgnore, Holder holder) {
FieldCache fieldCache = getFieldCache(clazz, convertAllFiled);
- if (fieldCache != null) {
- defaultFieldList.addAll(fieldCache.getDefaultFieldList());
- customFiledMap.putAll(fieldCache.getCustomFiledMap());
+ if (fieldCache == null) {
+ return;
+ }
+ if (ignoreMap != null) {
ignoreMap.putAll(fieldCache.getIgnoreMap());
}
- }
+ Map tempIndexFildMap = indexFiledMap;
+ if (tempIndexFildMap == null) {
+ tempIndexFildMap = new TreeMap();
+ }
+ tempIndexFildMap.putAll(fieldCache.getIndexFiledMap());
- public static void declaredFields(Class clazz, List fieldList, Boolean convertAllFiled) {
- FieldCache fieldCache = getFieldCache(clazz, convertAllFiled);
- if (fieldCache != null) {
- fieldList.addAll(fieldCache.getAllFieldList());
+ if (!needIgnore) {
+ sortedAllFiledMap.putAll(fieldCache.getSortedAllFiledMap());
+ return;
+ }
+
+ int index = 0;
+ for (Map.Entry entry : fieldCache.getSortedAllFiledMap().entrySet()) {
+ Field field = entry.getValue();
+ if (((WriteHolder) holder).ignore(entry.getValue().getName(), entry.getKey())) {
+ if (ignoreMap != null) {
+ ignoreMap.put(field.getName(), field);
+ }
+ while (tempIndexFildMap.containsKey(index)) {
+ tempIndexFildMap.remove(index);
+ index++;
+ }
+ } else {
+ sortedAllFiledMap.put(index, field);
+ index++;
+ }
}
}
+ public static void declaredFields(Class clazz, Map sortedAllFiledMap, Boolean convertAllFiled,
+ Boolean needIgnore, WriteHolder writeHolder) {
+ declaredFields(clazz, sortedAllFiledMap, null, null, convertAllFiled, needIgnore, writeHolder);
+ }
+
private static FieldCache getFieldCache(Class clazz, Boolean convertAllFiled) {
if (clazz == null) {
return null;
@@ -72,80 +104,108 @@ public class ClassUtils {
tempClass = tempClass.getSuperclass();
}
// Screening of field
- List defaultFieldList = new ArrayList();
- Map customFiledMap = new TreeMap();
- List allFieldList = new ArrayList();
+ Map> orderFiledMap = new TreeMap>();
+ Map indexFiledMap = new TreeMap();
Map ignoreMap = new HashMap(16);
ExcelIgnoreUnannotated excelIgnoreUnannotated =
- (ExcelIgnoreUnannotated)clazz.getAnnotation(ExcelIgnoreUnannotated.class);
+ (ExcelIgnoreUnannotated) clazz.getAnnotation(ExcelIgnoreUnannotated.class);
for (Field field : tempFieldList) {
- ExcelIgnore excelIgnore = field.getAnnotation(ExcelIgnore.class);
- if (excelIgnore != null) {
- ignoreMap.put(field.getName(), field);
- continue;
- }
- ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
- boolean noExcelProperty = excelProperty == null
- && ((convertAllFiled != null && !convertAllFiled) || excelIgnoreUnannotated != null);
- if (noExcelProperty) {
- ignoreMap.put(field.getName(), field);
- continue;
- }
- boolean isStaticFinalOrTransient =
- (Modifier.isStatic(field.getModifiers()) && Modifier.isFinal(field.getModifiers()))
- || Modifier.isTransient(field.getModifiers());
- if (excelProperty == null && isStaticFinalOrTransient) {
- ignoreMap.put(field.getName(), field);
- continue;
- }
- if (excelProperty == null || excelProperty.index() < 0) {
- defaultFieldList.add(field);
- allFieldList.add(field);
- continue;
+ declaredOneField(field, orderFiledMap, indexFiledMap, ignoreMap, excelIgnoreUnannotated, convertAllFiled);
+ }
+ FIELD_CACHE.put(clazz, new SoftReference(
+ new FieldCache(buildSortedAllFiledMap(orderFiledMap, indexFiledMap), indexFiledMap, ignoreMap)));
+ }
+
+ private static Map buildSortedAllFiledMap(Map> orderFiledMap,
+ Map indexFiledMap) {
+
+ Map sortedAllFiledMap = new HashMap(
+ (orderFiledMap.size() + indexFiledMap.size()) * 4 / 3 + 1);
+
+ Map tempIndexFiledMap = new HashMap(indexFiledMap);
+ int index = 0;
+ for (List fieldList : orderFiledMap.values()) {
+ for (Field field : fieldList) {
+ while (tempIndexFiledMap.containsKey(index)) {
+ sortedAllFiledMap.put(index, tempIndexFiledMap.get(index));
+ tempIndexFiledMap.remove(index);
+ index++;
+ }
+ sortedAllFiledMap.put(index, field);
+ index++;
}
- if (customFiledMap.containsKey(excelProperty.index())) {
- throw new ExcelCommonException("The index of '" + customFiledMap.get(excelProperty.index()).getName()
+ }
+ sortedAllFiledMap.putAll(tempIndexFiledMap);
+ return sortedAllFiledMap;
+ }
+
+ private static void declaredOneField(Field field, Map> orderFiledMap,
+ Map indexFiledMap, Map ignoreMap, ExcelIgnoreUnannotated excelIgnoreUnannotated,
+ Boolean convertAllFiled) {
+ ExcelIgnore excelIgnore = field.getAnnotation(ExcelIgnore.class);
+ if (excelIgnore != null) {
+ ignoreMap.put(field.getName(), field);
+ return;
+ }
+ ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
+ boolean noExcelProperty = excelProperty == null
+ && ((convertAllFiled != null && !convertAllFiled) || excelIgnoreUnannotated != null);
+ if (noExcelProperty) {
+ ignoreMap.put(field.getName(), field);
+ return;
+ }
+ boolean isStaticFinalOrTransient =
+ (Modifier.isStatic(field.getModifiers()) && Modifier.isFinal(field.getModifiers()))
+ || Modifier.isTransient(field.getModifiers());
+ if (excelProperty == null && isStaticFinalOrTransient) {
+ ignoreMap.put(field.getName(), field);
+ return;
+ }
+ if (excelProperty != null && excelProperty.index() >= 0) {
+ if (indexFiledMap.containsKey(excelProperty.index())) {
+ throw new ExcelCommonException("The index of '" + indexFiledMap.get(excelProperty.index()).getName()
+ "' and '" + field.getName() + "' must be inconsistent");
}
- customFiledMap.put(excelProperty.index(), field);
+ indexFiledMap.put(excelProperty.index(), field);
+ return;
}
- List allWriteFieldList = new ArrayList(customFiledMap.values());
- allWriteFieldList.addAll(allFieldList);
- FIELD_CACHE.put(clazz,
- new SoftReference(new FieldCache(defaultFieldList, customFiledMap, allWriteFieldList, ignoreMap)));
+ int order = Integer.MAX_VALUE;
+ if (excelProperty != null) {
+ order = excelProperty.order();
+ }
+ List orderFiledList = orderFiledMap.get(order);
+ if (orderFiledList == null) {
+ orderFiledList = new ArrayList();
+ orderFiledMap.put(order, orderFiledList);
+ }
+ orderFiledList.add(field);
}
private static class FieldCache {
- private List defaultFieldList;
- private Map customFiledMap;
- private List allFieldList;
+
+ private Map sortedAllFiledMap;
+ private Map indexFiledMap;
private Map ignoreMap;
- public FieldCache(List defaultFieldList, Map customFiledMap, List allFieldList,
+ public FieldCache(Map sortedAllFiledMap, Map indexFiledMap,
Map ignoreMap) {
- this.defaultFieldList = defaultFieldList;
- this.customFiledMap = customFiledMap;
- this.allFieldList = allFieldList;
+ this.sortedAllFiledMap = sortedAllFiledMap;
+ this.indexFiledMap = indexFiledMap;
this.ignoreMap = ignoreMap;
}
- public List getDefaultFieldList() {
- return defaultFieldList;
+ public Map getSortedAllFiledMap() {
+ return sortedAllFiledMap;
}
- public Map getCustomFiledMap() {
- return customFiledMap;
- }
-
- public List getAllFieldList() {
- return allFieldList;
+ public Map getIndexFiledMap() {
+ return indexFiledMap;
}
public Map getIgnoreMap() {
return ignoreMap;
}
-
}
}
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 728703ef..9f229029 100644
--- a/src/main/java/com/alibaba/excel/write/executor/ExcelWriteAddExecutor.java
+++ b/src/main/java/com/alibaba/excel/write/executor/ExcelWriteAddExecutor.java
@@ -6,6 +6,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.TreeMap;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
@@ -19,8 +20,11 @@ import com.alibaba.excel.util.ClassUtils;
import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.excel.util.WorkBookUtil;
import com.alibaba.excel.util.WriteHandlerUtils;
+import com.alibaba.excel.write.metadata.WriteWorkbook;
+import com.alibaba.excel.write.metadata.holder.AbstractWriteHolder;
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;
@@ -44,17 +48,18 @@ public class ExcelWriteAddExecutor extends AbstractExcelWriteExecutor {
if (writeSheetHolder.isNew() && !writeSheetHolder.getExcelWriteHeadProperty().hasHead()) {
newRowIndex += writeContext.currentWriteHolder().relativeHeadRowIndex();
}
- // BeanMap is out of order,so use fieldList
- List fieldList = new ArrayList();
- int relativeRowIndex=0;
- for(Object oneRowData : data){
+ // BeanMap is out of order,so use sortedAllFiledMap
+ Map sortedAllFiledMap = new TreeMap();
+ int relativeRowIndex = 0;
+ for (Object oneRowData : data) {
int n = relativeRowIndex + newRowIndex;
- addOneRowOfDataToExcel(oneRowData, n, relativeRowIndex, fieldList);
+ addOneRowOfDataToExcel(oneRowData, n, relativeRowIndex, sortedAllFiledMap);
relativeRowIndex++;
}
}
- private void addOneRowOfDataToExcel(Object oneRowData, int n, int relativeRowIndex, List fieldList) {
+ private void addOneRowOfDataToExcel(Object oneRowData, int n, int relativeRowIndex,
+ Map sortedAllFiledMap) {
if (oneRowData == null) {
return;
}
@@ -62,9 +67,9 @@ public class ExcelWriteAddExecutor extends AbstractExcelWriteExecutor {
Row row = WorkBookUtil.createRow(writeContext.writeSheetHolder().getSheet(), n);
WriteHandlerUtils.afterRowCreate(writeContext, row, relativeRowIndex, Boolean.FALSE);
if (oneRowData instanceof List) {
- addBasicTypeToExcel((List)oneRowData, row, relativeRowIndex);
+ addBasicTypeToExcel((List) oneRowData, row, relativeRowIndex);
} else {
- addJavaObjectToExcel(oneRowData, row, relativeRowIndex, fieldList);
+ addJavaObjectToExcel(oneRowData, row, relativeRowIndex, sortedAllFiledMap);
}
WriteHandlerUtils.afterRowDispose(writeContext, row, relativeRowIndex, Boolean.FALSE);
}
@@ -99,9 +104,6 @@ public class ExcelWriteAddExecutor extends AbstractExcelWriteExecutor {
private void doAddBasicTypeToExcel(List