Browse Source

Merge pull request #3197 from gongxuanzhang/field_col

Field col
pull/3201/head
gongxuanzhang 2 years ago committed by GitHub
parent
commit
d56db467e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 53
      easyexcel-core/src/main/java/com/alibaba/excel/util/ClassUtils.java
  2. 18
      easyexcel-test/src/test/java/com/alibaba/easyexcel/test/demo/write/WriteTest.java

53
easyexcel-core/src/main/java/com/alibaba/excel/util/ClassUtils.java

@ -36,6 +36,7 @@ import com.alibaba.excel.metadata.property.StyleProperty;
import com.alibaba.excel.write.metadata.holder.WriteHolder; import com.alibaba.excel.write.metadata.holder.WriteHolder;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
@ -49,7 +50,7 @@ import org.springframework.cglib.beans.BeanMap;
* The ASF licenses this file to You under the Apache License, Version 2.0 * The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with * (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 * the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
* * <p>
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -63,11 +64,11 @@ public class ClassUtils {
/** /**
* memory cache * memory cache
*/ */
public static final ConcurrentHashMap<Class<?>, FieldCache> FIELD_CACHE = new ConcurrentHashMap<>(); public static final Map<FieldCacheKey, FieldCache> FIELD_CACHE = new ConcurrentHashMap<>();
/** /**
* thread local cahe * thread local cache
*/ */
private static final ThreadLocal<Map<Class<?>, FieldCache>> FIELD_THREAD_LOCAL = new ThreadLocal<>(); private static final ThreadLocal<Map<FieldCacheKey, FieldCache>> FIELD_THREAD_LOCAL = new ThreadLocal<>();
/** /**
* The cache configuration information for each of the class * The cache configuration information for each of the class
@ -102,7 +103,8 @@ public class ClassUtils {
* @return * @return
*/ */
public static ExcelContentProperty declaredExcelContentProperty(Map<?, ?> dataMap, Class<?> headClazz, public static ExcelContentProperty declaredExcelContentProperty(Map<?, ?> dataMap, Class<?> headClazz,
String fieldName, ConfigurationHolder configurationHolder) { String fieldName,
ConfigurationHolder configurationHolder) {
Class<?> clazz = null; Class<?> clazz = null;
if (dataMap instanceof BeanMap) { if (dataMap instanceof BeanMap) {
Object bean = ((BeanMap)dataMap).getBean(); Object bean = ((BeanMap)dataMap).getBean();
@ -137,7 +139,8 @@ public class ClassUtils {
} }
private static ExcelContentProperty doGetExcelContentProperty(Class<?> clazz, Class<?> headClass, private static ExcelContentProperty doGetExcelContentProperty(Class<?> clazz, Class<?> headClass,
String fieldName, ConfigurationHolder configurationHolder) { String fieldName,
ConfigurationHolder configurationHolder) {
ExcelContentProperty excelContentProperty = Optional.ofNullable( ExcelContentProperty excelContentProperty = Optional.ofNullable(
declaredFieldContentMap(clazz, configurationHolder)) declaredFieldContentMap(clazz, configurationHolder))
.map(map -> map.get(fieldName)) .map(map -> map.get(fieldName))
@ -277,16 +280,16 @@ public class ClassUtils {
public static FieldCache declaredFields(Class<?> clazz, ConfigurationHolder configurationHolder) { public static FieldCache declaredFields(Class<?> clazz, ConfigurationHolder configurationHolder) {
switch (configurationHolder.globalConfiguration().getFiledCacheLocation()) { switch (configurationHolder.globalConfiguration().getFiledCacheLocation()) {
case THREAD_LOCAL: case THREAD_LOCAL:
Map<Class<?>, FieldCache> fieldCacheMap = FIELD_THREAD_LOCAL.get(); Map<FieldCacheKey, FieldCache> fieldCacheMap = FIELD_THREAD_LOCAL.get();
if (fieldCacheMap == null) { if (fieldCacheMap == null) {
fieldCacheMap = MapUtils.newHashMap(); fieldCacheMap = MapUtils.newHashMap();
FIELD_THREAD_LOCAL.set(fieldCacheMap); FIELD_THREAD_LOCAL.set(fieldCacheMap);
} }
return fieldCacheMap.computeIfAbsent(clazz, key -> { return fieldCacheMap.computeIfAbsent(new FieldCacheKey(clazz, configurationHolder), key -> {
return doDeclaredFields(clazz, configurationHolder); return doDeclaredFields(clazz, configurationHolder);
}); });
case MEMORY: case MEMORY:
return FIELD_CACHE.computeIfAbsent(clazz, key -> { return FIELD_CACHE.computeIfAbsent(new FieldCacheKey(clazz, configurationHolder), key -> {
return doDeclaredFields(clazz, configurationHolder); return doDeclaredFields(clazz, configurationHolder);
}); });
case NONE: case NONE:
@ -333,7 +336,7 @@ public class ClassUtils {
return fieldCache; return fieldCache;
} }
// ignore filed // ignore filed
Map<Integer, FieldWrapper> tempSortedFieldMapp = MapUtils.newHashMap(); Map<Integer, FieldWrapper> tempSortedFieldMap = MapUtils.newHashMap();
int index = 0; int index = 0;
for (Map.Entry<Integer, FieldWrapper> entry : sortedFieldMap.entrySet()) { for (Map.Entry<Integer, FieldWrapper> entry : sortedFieldMap.entrySet()) {
Integer key = entry.getKey(); Integer key = entry.getKey();
@ -346,18 +349,18 @@ public class ClassUtils {
} else { } else {
// Mandatory sorted fields // Mandatory sorted fields
if (indexFieldMap.containsKey(key)) { if (indexFieldMap.containsKey(key)) {
tempSortedFieldMapp.put(key, field); tempSortedFieldMap.put(key, field);
} else { } else {
// Need to reorder automatically // Need to reorder automatically
// Check whether the current key is already in use // Check whether the current key is already in use
while (tempSortedFieldMapp.containsKey(index)) { while (tempSortedFieldMap.containsKey(index)) {
index++; index++;
} }
tempSortedFieldMapp.put(index++, field); tempSortedFieldMap.put(index++, field);
} }
} }
} }
fieldCache.setSortedFieldMap(tempSortedFieldMapp); fieldCache.setSortedFieldMap(tempSortedFieldMap);
// resort field // resort field
resortField(writeHolder, fieldCache); resortField(writeHolder, fieldCache);
@ -406,8 +409,8 @@ public class ClassUtils {
// Index sorted map // Index sorted map
Map<Integer, Integer> filedIndexMap = MapUtils.newHashMap(); Map<Integer, Integer> filedIndexMap = MapUtils.newHashMap();
int fieldIndex = 0; int fieldIndex = 0;
for (Integer includeColumnIndexe : includeColumnIndexes) { for (Integer includeColumnIndex : includeColumnIndexes) {
filedIndexMap.put(includeColumnIndexe, fieldIndex++); filedIndexMap.put(includeColumnIndex, fieldIndex++);
} }
// rebuild sortedFieldMap // rebuild sortedFieldMap
@ -551,6 +554,24 @@ public class ClassUtils {
private String fieldName; private String fieldName;
} }
@Data
public static class FieldCacheKey {
private Class<?> clazz;
private Collection<String> excludeColumnFieldNames;
private Collection<Integer> excludeColumnIndexes;
private Collection<String> includeColumnFieldNames;
private Collection<Integer> includeColumnIndexes;
FieldCacheKey(Class<?> clazz, ConfigurationHolder configurationHolder) {
this.clazz = clazz;
WriteHolder writeHolder = (WriteHolder)configurationHolder;
this.excludeColumnFieldNames = writeHolder.excludeColumnFieldNames();
this.excludeColumnIndexes = writeHolder.excludeColumnIndexes();
this.includeColumnFieldNames = writeHolder.includeColumnFieldNames();
this.includeColumnIndexes = writeHolder.includeColumnIndexes();
}
}
public static void removeThreadLocalCache() { public static void removeThreadLocalCache() {
FIELD_THREAD_LOCAL.remove(); FIELD_THREAD_LOCAL.remove();
CLASS_CONTENT_THREAD_LOCAL.remove(); CLASS_CONTENT_THREAD_LOCAL.remove();

18
easyexcel-test/src/test/java/com/alibaba/easyexcel/test/demo/write/WriteTest.java

@ -4,11 +4,14 @@ import java.io.File;
import java.io.InputStream; import java.io.InputStream;
import java.net.URL; import java.net.URL;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import com.alibaba.easyexcel.test.core.head.ComplexHeadData;
import com.alibaba.easyexcel.test.demo.read.ConverterData;
import com.alibaba.easyexcel.test.util.TestFileUtil; import com.alibaba.easyexcel.test.util.TestFileUtil;
import com.alibaba.excel.EasyExcel; import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter; import com.alibaba.excel.ExcelWriter;
@ -409,7 +412,7 @@ public class WriteTest {
/** /**
* 列宽行高 * 列宽行高
* <p> * <p>
* 1. 创建excel对应的实体对象 参照{@link WidthAndHeightData} * 1. 创建excel对应的实体对象 参照{@link WidthAndHeightData }
* <p> * <p>
* 2. 使用注解{@link ColumnWidth}{@link HeadRowHeight}{@link ContentRowHeight}指定宽度或高度 * 2. 使用注解{@link ColumnWidth}{@link HeadRowHeight}{@link ContentRowHeight}指定宽度或高度
* <p> * <p>
@ -703,6 +706,19 @@ public class WriteTest {
EasyExcel.write(fileName).head(head()).sheet("模板").doWrite(dataList()); EasyExcel.write(fileName).head(head()).sheet("模板").doWrite(dataList());
} }
@Test
public void sheetCol(){
String fileName = TestFileUtil.getPath() + "customCol" + System.currentTimeMillis() + ".xlsx";
try (ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).includeColumnFieldNames(Arrays.asList("string","date","doubleData")).build()) {
// 把sheet设置为不需要头 不然会输出sheet的头 这样看起来第一个table 就有2个头了
WriteSheet writeSheet = EasyExcel.writerSheet("模板").includeColumnFieldNames(Arrays.asList("string","date")).build();
excelWriter.write(data(), writeSheet);
writeSheet = EasyExcel.writerSheet(1,"模板1").needHead(false).build();
// 第二次写如也会创建头,然后在第一次的后面写入数据
WriteTable string = EasyExcel.writerTable().needHead(true).includeColumnFieldNames(Arrays.asList("string")).build();
excelWriter.write(data(),writeSheet,string);
}
}
private List<LongestMatchColumnWidthData> dataLong() { private List<LongestMatchColumnWidthData> dataLong() {
List<LongestMatchColumnWidthData> list = ListUtils.newArrayList(); List<LongestMatchColumnWidthData> list = ListUtils.newArrayList();
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {

Loading…
Cancel
Save