mirror of https://github.com/alibaba/easyexcel
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
244 lines
8.6 KiB
244 lines
8.6 KiB
package com.alibaba.excel.metadata.property; |
|
|
|
import java.lang.reflect.Field; |
|
import java.util.AbstractMap; |
|
import java.util.ArrayList; |
|
import java.util.Collection; |
|
import java.util.Collections; |
|
import java.util.HashMap; |
|
import java.util.List; |
|
import java.util.Map; |
|
import java.util.TreeMap; |
|
|
|
import org.apache.commons.collections4.CollectionUtils; |
|
import org.slf4j.Logger; |
|
import org.slf4j.LoggerFactory; |
|
|
|
import com.alibaba.excel.annotation.ExcelProperty; |
|
import com.alibaba.excel.annotation.format.DateTimeFormat; |
|
import com.alibaba.excel.annotation.format.NumberFormat; |
|
import com.alibaba.excel.converters.AutoConverter; |
|
import com.alibaba.excel.converters.Converter; |
|
import com.alibaba.excel.enums.HeadKindEnum; |
|
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.StringUtils; |
|
import com.alibaba.excel.write.metadata.holder.AbstractWriteHolder; |
|
|
|
/** |
|
* Define the header attribute of excel |
|
* |
|
* @author jipengfei |
|
*/ |
|
public class ExcelHeadProperty { |
|
|
|
private static final Logger LOGGER = LoggerFactory.getLogger(ExcelHeadProperty.class); |
|
/** |
|
* Custom class |
|
*/ |
|
private Class headClazz; |
|
/** |
|
* The types of head |
|
*/ |
|
private HeadKindEnum headKind; |
|
/** |
|
* The number of rows in the line with the most rows |
|
*/ |
|
private int headRowNumber; |
|
/** |
|
* Configuration header information |
|
*/ |
|
private Map<Integer, Head> headMap; |
|
/** |
|
* Configuration column information |
|
*/ |
|
private Map<Integer, ExcelContentProperty> contentPropertyMap; |
|
/** |
|
* Configuration column information |
|
*/ |
|
private Map<String, ExcelContentProperty> fieldNameContentPropertyMap; |
|
/** |
|
* Fields ignored |
|
*/ |
|
private Map<String, Field> ignoreMap; |
|
|
|
public ExcelHeadProperty(Holder holder, Class headClazz, List<List<String>> head, Boolean convertAllField) { |
|
this.headClazz = headClazz; |
|
headMap = new TreeMap<Integer, Head>(); |
|
contentPropertyMap = new TreeMap<Integer, ExcelContentProperty>(); |
|
fieldNameContentPropertyMap = new HashMap<String, ExcelContentProperty>(); |
|
ignoreMap = new HashMap<String, Field>(16); |
|
headKind = HeadKindEnum.NONE; |
|
headRowNumber = 0; |
|
if (head != null && !head.isEmpty()) { |
|
int headIndex = 0; |
|
for (int i = 0; i < head.size(); i++) { |
|
if (holder instanceof AbstractWriteHolder) { |
|
if (((AbstractWriteHolder) holder).ignore(null, i)) { |
|
continue; |
|
} |
|
} |
|
headMap.put(headIndex, new Head(headIndex, null, head.get(i), Boolean.FALSE, Boolean.TRUE)); |
|
contentPropertyMap.put(headIndex, null); |
|
headIndex++; |
|
} |
|
headKind = HeadKindEnum.STRING; |
|
} |
|
// convert headClazz to head |
|
initColumnProperties(holder, convertAllField); |
|
|
|
initHeadRowNumber(); |
|
if (LOGGER.isDebugEnabled()) { |
|
LOGGER.debug("The initialization sheet/table 'ExcelHeadProperty' is complete , head kind is {}", headKind); |
|
} |
|
} |
|
|
|
private void initHeadRowNumber() { |
|
headRowNumber = 0; |
|
for (Head head : headMap.values()) { |
|
List<String> list = head.getHeadNameList(); |
|
if (list != null && list.size() > headRowNumber) { |
|
headRowNumber = list.size(); |
|
} |
|
} |
|
for (Head head : headMap.values()) { |
|
List<String> list = head.getHeadNameList(); |
|
if (list != null && !list.isEmpty() && list.size() < headRowNumber) { |
|
int lack = headRowNumber - list.size(); |
|
int last = list.size() - 1; |
|
for (int i = 0; i < lack; i++) { |
|
list.add(list.get(last)); |
|
} |
|
} |
|
} |
|
} |
|
|
|
private void initColumnProperties(Holder holder, Boolean convertAllField) { |
|
if (headClazz == null) { |
|
return; |
|
} |
|
// Declared fields |
|
Map<Integer, Field> sortedAllFiledMap = new TreeMap<Integer, Field>(); |
|
Map<Integer, Field> indexFiledMap = new TreeMap<Integer, Field>(); |
|
|
|
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<Integer, Field> entry : sortedAllFiledMap.entrySet()) { |
|
initOneColumnProperty(entry.getKey(), entry.getValue(), indexFiledMap.containsKey(entry.getKey())); |
|
} |
|
} |
|
|
|
/** |
|
* Initialization column property |
|
* |
|
* @param index |
|
* @param field |
|
* @param forceIndex |
|
* @return Ignore current field |
|
*/ |
|
private void initOneColumnProperty(int index, Field field, Boolean forceIndex) { |
|
ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class); |
|
List<String> tmpHeadList = new ArrayList<String>(); |
|
boolean notForceName = excelProperty == null || excelProperty.value().length <= 0 |
|
|| (excelProperty.value().length == 1 && StringUtils.isEmpty((excelProperty.value())[0])); |
|
if (headMap.containsKey(index)) { |
|
tmpHeadList.addAll(headMap.get(index).getHeadNameList()); |
|
} else { |
|
if (notForceName) { |
|
tmpHeadList.add(field.getName()); |
|
} else { |
|
Collections.addAll(tmpHeadList, excelProperty.value()); |
|
} |
|
} |
|
Head head = new Head(index, field.getName(), tmpHeadList, forceIndex, !notForceName); |
|
ExcelContentProperty excelContentProperty = new ExcelContentProperty(); |
|
if (excelProperty != null) { |
|
Class<? extends Converter> convertClazz = excelProperty.converter(); |
|
if (convertClazz != AutoConverter.class) { |
|
try { |
|
Converter converter = convertClazz.newInstance(); |
|
excelContentProperty.setConverter(converter); |
|
} catch (Exception e) { |
|
throw new ExcelCommonException("Can not instance custom converter:" + convertClazz.getName()); |
|
} |
|
} |
|
} |
|
excelContentProperty.setHead(head); |
|
excelContentProperty.setField(field); |
|
excelContentProperty |
|
.setDateTimeFormatProperty(DateTimeFormatProperty.build(field.getAnnotation(DateTimeFormat.class))); |
|
excelContentProperty |
|
.setNumberFormatProperty(NumberFormatProperty.build(field.getAnnotation(NumberFormat.class))); |
|
headMap.put(index, head); |
|
contentPropertyMap.put(index, excelContentProperty); |
|
fieldNameContentPropertyMap.put(field.getName(), excelContentProperty); |
|
} |
|
|
|
public Class getHeadClazz() { |
|
return headClazz; |
|
} |
|
|
|
public void setHeadClazz(Class headClazz) { |
|
this.headClazz = headClazz; |
|
} |
|
|
|
public HeadKindEnum getHeadKind() { |
|
return headKind; |
|
} |
|
|
|
public void setHeadKind(HeadKindEnum headKind) { |
|
this.headKind = headKind; |
|
} |
|
|
|
public boolean hasHead() { |
|
return headKind != HeadKindEnum.NONE; |
|
} |
|
|
|
public int getHeadRowNumber() { |
|
return headRowNumber; |
|
} |
|
|
|
public void setHeadRowNumber(int headRowNumber) { |
|
this.headRowNumber = headRowNumber; |
|
} |
|
|
|
public Map<Integer, Head> getHeadMap() { |
|
return headMap; |
|
} |
|
|
|
public void setHeadMap(Map<Integer, Head> headMap) { |
|
this.headMap = headMap; |
|
} |
|
|
|
public Map<Integer, ExcelContentProperty> getContentPropertyMap() { |
|
return contentPropertyMap; |
|
} |
|
|
|
public void setContentPropertyMap(Map<Integer, ExcelContentProperty> contentPropertyMap) { |
|
this.contentPropertyMap = contentPropertyMap; |
|
} |
|
|
|
public Map<String, ExcelContentProperty> getFieldNameContentPropertyMap() { |
|
return fieldNameContentPropertyMap; |
|
} |
|
|
|
public void setFieldNameContentPropertyMap(Map<String, ExcelContentProperty> fieldNameContentPropertyMap) { |
|
this.fieldNameContentPropertyMap = fieldNameContentPropertyMap; |
|
} |
|
|
|
public Map<String, Field> getIgnoreMap() { |
|
return ignoreMap; |
|
} |
|
|
|
public void setIgnoreMap(Map<String, Field> ignoreMap) { |
|
this.ignoreMap = ignoreMap; |
|
} |
|
}
|
|
|