⚡ 替换easyexcel默认处理类
This commit is contained in:
@@ -0,0 +1,215 @@
|
||||
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;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Class utils
|
||||
*
|
||||
* @author Jiaju Zhuang
|
||||
**/
|
||||
public class ClassUtils {
|
||||
|
||||
private static final Map<Class, SoftReference<FieldCache>> FIELD_CACHE = new ConcurrentHashMap<Class, SoftReference<FieldCache>>();
|
||||
|
||||
public static void declaredFields(Class clazz, Map<Integer, Field> sortedAllFiledMap,
|
||||
Map<Integer, Field> indexFiledMap, Map<String, Field> ignoreMap, Boolean convertAllFiled,
|
||||
Boolean needIgnore, Holder holder) {
|
||||
FieldCache fieldCache = getFieldCache(clazz, convertAllFiled);
|
||||
if (fieldCache == null) {
|
||||
return;
|
||||
}
|
||||
if (ignoreMap != null) {
|
||||
ignoreMap.putAll(fieldCache.getIgnoreMap());
|
||||
}
|
||||
Map<Integer, Field> tempIndexFildMap = indexFiledMap;
|
||||
if (tempIndexFildMap == null) {
|
||||
tempIndexFildMap = new TreeMap<Integer, Field>();
|
||||
}
|
||||
tempIndexFildMap.putAll(fieldCache.getIndexFiledMap());
|
||||
|
||||
Map<Integer, Field> originSortedAllFiledMap = fieldCache.getSortedAllFiledMap();
|
||||
if (!needIgnore) {
|
||||
sortedAllFiledMap.putAll(originSortedAllFiledMap);
|
||||
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);
|
||||
}
|
||||
tempIndexFildMap.remove(index);
|
||||
ignoreNum++;
|
||||
}
|
||||
else if (field != null) {
|
||||
int finalIndex = index - ignoreNum;
|
||||
sortedAllFiledMap.put(finalIndex, field);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void declaredFields(Class clazz, Map<Integer, Field> 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;
|
||||
}
|
||||
SoftReference<FieldCache> fieldCacheSoftReference = FIELD_CACHE.get(clazz);
|
||||
if (fieldCacheSoftReference != null && fieldCacheSoftReference.get() != null) {
|
||||
return fieldCacheSoftReference.get();
|
||||
}
|
||||
synchronized (clazz) {
|
||||
fieldCacheSoftReference = FIELD_CACHE.get(clazz);
|
||||
if (fieldCacheSoftReference != null && fieldCacheSoftReference.get() != null) {
|
||||
return fieldCacheSoftReference.get();
|
||||
}
|
||||
declaredFields(clazz, convertAllFiled);
|
||||
}
|
||||
return FIELD_CACHE.get(clazz).get();
|
||||
}
|
||||
|
||||
private static void declaredFields(Class clazz, Boolean convertAllFiled) {
|
||||
List<Field> tempFieldList = new ArrayList<Field>();
|
||||
Class tempClass = clazz;
|
||||
// When the parent class is null, it indicates that the parent class (Object
|
||||
// class) has reached the top
|
||||
// level.
|
||||
while (tempClass != null && tempClass != BaseRowModel.class) {
|
||||
Collections.addAll(tempFieldList, tempClass.getDeclaredFields());
|
||||
// Get the parent class and give it to yourself
|
||||
tempClass = tempClass.getSuperclass();
|
||||
}
|
||||
// Screening of field
|
||||
Map<Integer, List<Field>> orderFiledMap = new TreeMap<Integer, List<Field>>();
|
||||
Map<Integer, Field> indexFiledMap = new TreeMap<Integer, Field>();
|
||||
Map<String, Field> ignoreMap = new HashMap<String, Field>(16);
|
||||
|
||||
ExcelIgnoreUnannotated excelIgnoreUnannotated = (ExcelIgnoreUnannotated) clazz
|
||||
.getAnnotation(ExcelIgnoreUnannotated.class);
|
||||
for (Field field : tempFieldList) {
|
||||
declaredOneField(field, orderFiledMap, indexFiledMap, ignoreMap, excelIgnoreUnannotated, convertAllFiled);
|
||||
}
|
||||
FIELD_CACHE.put(clazz, new SoftReference<FieldCache>(
|
||||
new FieldCache(buildSortedAllFiledMap(orderFiledMap, indexFiledMap), indexFiledMap, ignoreMap)));
|
||||
}
|
||||
|
||||
private static Map<Integer, Field> buildSortedAllFiledMap(Map<Integer, List<Field>> orderFiledMap,
|
||||
Map<Integer, Field> indexFiledMap) {
|
||||
|
||||
Map<Integer, Field> sortedAllFiledMap = new HashMap<Integer, Field>(
|
||||
(orderFiledMap.size() + indexFiledMap.size()) * 4 / 3 + 1);
|
||||
|
||||
Map<Integer, Field> tempIndexFiledMap = new HashMap<Integer, Field>(indexFiledMap);
|
||||
int index = 0;
|
||||
for (List<Field> 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++;
|
||||
}
|
||||
}
|
||||
sortedAllFiledMap.putAll(tempIndexFiledMap);
|
||||
return sortedAllFiledMap;
|
||||
}
|
||||
|
||||
private static void declaredOneField(Field field, Map<Integer, List<Field>> orderFiledMap,
|
||||
Map<Integer, Field> indexFiledMap, Map<String, Field> 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");
|
||||
}
|
||||
indexFiledMap.put(excelProperty.index(), field);
|
||||
return;
|
||||
}
|
||||
|
||||
int order = Integer.MAX_VALUE;
|
||||
if (excelProperty != null) {
|
||||
order = excelProperty.order();
|
||||
}
|
||||
List<Field> orderFiledList = orderFiledMap.get(order);
|
||||
if (orderFiledList == null) {
|
||||
orderFiledList = new ArrayList<Field>();
|
||||
orderFiledMap.put(order, orderFiledList);
|
||||
}
|
||||
orderFiledList.add(field);
|
||||
}
|
||||
|
||||
private static class FieldCache {
|
||||
|
||||
private Map<Integer, Field> sortedAllFiledMap;
|
||||
|
||||
private Map<Integer, Field> indexFiledMap;
|
||||
|
||||
private Map<String, Field> ignoreMap;
|
||||
|
||||
public FieldCache(Map<Integer, Field> sortedAllFiledMap, Map<Integer, Field> indexFiledMap,
|
||||
Map<String, Field> ignoreMap) {
|
||||
this.sortedAllFiledMap = sortedAllFiledMap;
|
||||
this.indexFiledMap = indexFiledMap;
|
||||
this.ignoreMap = ignoreMap;
|
||||
}
|
||||
|
||||
public Map<Integer, Field> getSortedAllFiledMap() {
|
||||
return sortedAllFiledMap;
|
||||
}
|
||||
|
||||
public Map<Integer, Field> getIndexFiledMap() {
|
||||
return indexFiledMap;
|
||||
}
|
||||
|
||||
public Map<String, Field> getIgnoreMap() {
|
||||
return ignoreMap;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
package com.alibaba.excel.write.executor;
|
||||
|
||||
import com.alibaba.excel.context.WriteContext;
|
||||
import com.alibaba.excel.enums.HeadKindEnum;
|
||||
import com.alibaba.excel.metadata.CellData;
|
||||
import com.alibaba.excel.metadata.Head;
|
||||
import com.alibaba.excel.metadata.property.ExcelContentProperty;
|
||||
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.executor.AbstractExcelWriteExecutor;
|
||||
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 net.sf.cglib.beans.BeanMap;
|
||||
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
|
||||
*
|
||||
* @author Jiaju Zhuang
|
||||
*/
|
||||
public class ExcelWriteAddExecutor extends AbstractExcelWriteExecutor {
|
||||
|
||||
public ExcelWriteAddExecutor(WriteContext writeContext) {
|
||||
super(writeContext);
|
||||
}
|
||||
|
||||
public void add(List data) {
|
||||
if (CollectionUtils.isEmpty(data)) {
|
||||
data = new ArrayList();
|
||||
}
|
||||
WriteSheetHolder writeSheetHolder = writeContext.writeSheetHolder();
|
||||
int newRowIndex = writeSheetHolder.getNewRowIndexAndStartDoWrite();
|
||||
if (writeSheetHolder.isNew() && !writeSheetHolder.getExcelWriteHeadProperty().hasHead()) {
|
||||
newRowIndex += writeContext.currentWriteHolder().relativeHeadRowIndex();
|
||||
}
|
||||
// BeanMap is out of order,so use sortedAllFiledMap
|
||||
Map<Integer, Field> sortedAllFiledMap = new TreeMap<Integer, Field>();
|
||||
int relativeRowIndex = 0;
|
||||
for (Object oneRowData : data) {
|
||||
int n = relativeRowIndex + newRowIndex;
|
||||
addOneRowOfDataToExcel(oneRowData, n, relativeRowIndex, sortedAllFiledMap);
|
||||
relativeRowIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
private void addOneRowOfDataToExcel(Object oneRowData, int n, int relativeRowIndex,
|
||||
Map<Integer, Field> sortedAllFiledMap) {
|
||||
if (oneRowData == null) {
|
||||
return;
|
||||
}
|
||||
WriteHandlerUtils.beforeRowCreate(writeContext, n, relativeRowIndex, Boolean.FALSE);
|
||||
Row row = WorkBookUtil.createRow(writeContext.writeSheetHolder().getSheet(), n);
|
||||
WriteHandlerUtils.afterRowCreate(writeContext, row, relativeRowIndex, Boolean.FALSE);
|
||||
if (oneRowData instanceof List) {
|
||||
addBasicTypeToExcel((List) oneRowData, row, relativeRowIndex);
|
||||
}
|
||||
else {
|
||||
addJavaObjectToExcel(oneRowData, row, relativeRowIndex, sortedAllFiledMap);
|
||||
}
|
||||
WriteHandlerUtils.afterRowDispose(writeContext, row, relativeRowIndex, Boolean.FALSE);
|
||||
}
|
||||
|
||||
private void addBasicTypeToExcel(List<Object> oneRowData, Row row, int relativeRowIndex) {
|
||||
if (CollectionUtils.isEmpty(oneRowData)) {
|
||||
return;
|
||||
}
|
||||
Map<Integer, Head> headMap = writeContext.currentWriteHolder().excelWriteHeadProperty().getHeadMap();
|
||||
int dataIndex = 0;
|
||||
int cellIndex = 0;
|
||||
for (Map.Entry<Integer, Head> entry : headMap.entrySet()) {
|
||||
if (dataIndex >= oneRowData.size()) {
|
||||
return;
|
||||
}
|
||||
cellIndex = entry.getKey();
|
||||
Head head = entry.getValue();
|
||||
doAddBasicTypeToExcel(oneRowData, head, row, relativeRowIndex, dataIndex++, cellIndex);
|
||||
}
|
||||
// Finish
|
||||
if (dataIndex >= oneRowData.size()) {
|
||||
return;
|
||||
}
|
||||
if (cellIndex != 0) {
|
||||
cellIndex++;
|
||||
}
|
||||
int size = oneRowData.size() - dataIndex;
|
||||
for (int i = 0; i < size; i++) {
|
||||
doAddBasicTypeToExcel(oneRowData, null, row, relativeRowIndex, dataIndex++, cellIndex++);
|
||||
}
|
||||
}
|
||||
|
||||
private void doAddBasicTypeToExcel(List<Object> oneRowData, Head head, Row row, int relativeRowIndex, int dataIndex,
|
||||
int cellIndex) {
|
||||
WriteHandlerUtils.beforeCellCreate(writeContext, row, head, cellIndex, relativeRowIndex, Boolean.FALSE);
|
||||
Cell cell = WorkBookUtil.createCell(row, cellIndex);
|
||||
WriteHandlerUtils.afterCellCreate(writeContext, cell, head, relativeRowIndex, Boolean.FALSE);
|
||||
Object value = oneRowData.get(dataIndex);
|
||||
CellData cellData = converterAndSet(writeContext.currentWriteHolder(), value == null ? null : value.getClass(),
|
||||
cell, value, null, head, relativeRowIndex);
|
||||
WriteHandlerUtils.afterCellDispose(writeContext, cellData, cell, head, relativeRowIndex, Boolean.FALSE);
|
||||
}
|
||||
|
||||
private void addJavaObjectToExcel(Object oneRowData, Row row, int relativeRowIndex,
|
||||
Map<Integer, Field> sortedAllFiledMap) {
|
||||
WriteHolder currentWriteHolder = writeContext.currentWriteHolder();
|
||||
BeanMap beanMap = BeanMap.create(oneRowData);
|
||||
Set<String> beanMapHandledSet = new HashSet<String>();
|
||||
int cellIndex = 0;
|
||||
// If it's a class it needs to be cast by type
|
||||
if (HeadKindEnum.CLASS.equals(writeContext.currentWriteHolder().excelWriteHeadProperty().getHeadKind())) {
|
||||
Map<Integer, Head> headMap = writeContext.currentWriteHolder().excelWriteHeadProperty().getHeadMap();
|
||||
Map<Integer, ExcelContentProperty> contentPropertyMap = writeContext.currentWriteHolder()
|
||||
.excelWriteHeadProperty().getContentPropertyMap();
|
||||
for (Map.Entry<Integer, ExcelContentProperty> entry : contentPropertyMap.entrySet()) {
|
||||
cellIndex = entry.getKey();
|
||||
ExcelContentProperty excelContentProperty = entry.getValue();
|
||||
String name = excelContentProperty.getField().getName();
|
||||
if (!beanMap.containsKey(name)) {
|
||||
continue;
|
||||
}
|
||||
Head head = headMap.get(cellIndex);
|
||||
WriteHandlerUtils.beforeCellCreate(writeContext, row, head, cellIndex, relativeRowIndex, Boolean.FALSE);
|
||||
Cell cell = WorkBookUtil.createCell(row, cellIndex);
|
||||
WriteHandlerUtils.afterCellCreate(writeContext, cell, head, relativeRowIndex, Boolean.FALSE);
|
||||
Object value = beanMap.get(name);
|
||||
CellData cellData = converterAndSet(currentWriteHolder, excelContentProperty.getField().getType(), cell,
|
||||
value, excelContentProperty, head, relativeRowIndex);
|
||||
WriteHandlerUtils.afterCellDispose(writeContext, cellData, cell, head, relativeRowIndex, Boolean.FALSE);
|
||||
beanMapHandledSet.add(name);
|
||||
}
|
||||
}
|
||||
// Finish
|
||||
if (beanMapHandledSet.size() == beanMap.size()) {
|
||||
return;
|
||||
}
|
||||
Map<String, Field> ignoreMap = writeContext.currentWriteHolder().excelWriteHeadProperty().getIgnoreMap();
|
||||
initSortedAllFiledMapFieldList(oneRowData.getClass(), sortedAllFiledMap);
|
||||
for (Map.Entry<Integer, Field> entry : sortedAllFiledMap.entrySet()) {
|
||||
cellIndex = entry.getKey();
|
||||
Field field = entry.getValue();
|
||||
String filedName = field.getName();
|
||||
boolean uselessData = !beanMap.containsKey(filedName) || beanMapHandledSet.contains(filedName)
|
||||
|| ignoreMap.containsKey(filedName);
|
||||
if (uselessData) {
|
||||
continue;
|
||||
}
|
||||
Object value = beanMap.get(filedName);
|
||||
WriteHandlerUtils.beforeCellCreate(writeContext, row, null, cellIndex, relativeRowIndex, Boolean.FALSE);
|
||||
Cell cell = WorkBookUtil.createCell(row, cellIndex);
|
||||
WriteHandlerUtils.afterCellCreate(writeContext, cell, null, relativeRowIndex, Boolean.FALSE);
|
||||
CellData cellData = converterAndSet(currentWriteHolder, value == null ? null : value.getClass(), cell,
|
||||
value, null, null, relativeRowIndex);
|
||||
WriteHandlerUtils.afterCellDispose(writeContext, cellData, cell, null, relativeRowIndex, Boolean.FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
private void initSortedAllFiledMapFieldList(Class clazz, Map<Integer, Field> sortedAllFiledMap) {
|
||||
if (!sortedAllFiledMap.isEmpty()) {
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user