-
Notifications
You must be signed in to change notification settings - Fork 7.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
关于空值替换 #1776
Comments
目前遇到相同问题,有没有通用的解决方案 |
对于简单需求,你可以尝试定义类似如下 public class NullNumberToHyphenConverter implements Converter<Double> {
@Override
public Class supportJavaTypeKey() {
return Double.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.NUMBER;
}
@Override
public Double convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
return cellData.getNumberValue().doubleValue();
}
@Override
public CellData convertToExcelData(Double value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
if (value == null) {
return new CellData("——");
}
return new CellData(BigDecimal.valueOf(value));
}
}
@NumberFormat("0.00")
@ExcelProperty(value = "xxx", converter = NullNumberToHyphenConverter.class)
private Double xxx; 我使用了多列表头,由于 easyexcel/src/main/java/com/alibaba/excel/metadata/AbstractParameterBuilder.java Lines 15 to 35 in 756f16e
导致我无法使用通过设置 headClass 来使用com.alibaba.excel.annotation.ExcelProperty 指定converter ,所以我转而寻求通过自定义 CellWriteHandler 来达到我的目的.
下面是我目前使用的方案
/**
* 默认值
*
* @author tangcent
* @create 2021-01-29
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Default {
String value();//默认值
}
/**
* 扩展CellWriteHandler方法,仅回调具有指定注解的字段
*
* @author tangcent
* @create 2021-01-29
*/
public class AnnotatedCellWriteHandler<T extends Annotation> implements CellWriteHandler {
private Map<Integer, Pair<Field, T>> annMapper;
@SuppressWarnings("unchecked")
public AnnotatedCellWriteHandler(Class headClass) {
this.annMapper = getFieldMapper(headClass, this.getClass());
}
@Override
public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {
Pair<Field, T> pair = annMapper.get(columnIndex);
if (pair == null) {
return;
}
beforeCellCreate(writeSheetHolder, writeTableHolder, row, head, columnIndex,
relativeRowIndex, isHead, pair.getKey(), pair.getValue());
}
public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead, Field key, T ann) {
}
@Override
public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
Pair<Field, T> pair = annMapper.get(cell.getColumnIndex());
if (pair == null) {
return;
}
afterCellCreate(writeSheetHolder, writeTableHolder, cell, head, relativeRowIndex, isHead,
pair.getKey(), pair.getValue());
}
public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead, Field key, T ann) {
}
@Override
public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
Pair<Field, T> pair = annMapper.get(cell.getColumnIndex());
if (pair == null) {
return;
}
afterCellDataConverted(writeSheetHolder, writeTableHolder, cellData, cell, head, relativeRowIndex, isHead,
pair.getKey(), pair.getValue());
}
public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead, Field key, T ann) {
}
@Override
public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
Pair<Field, T> pair = annMapper.get(cell.getColumnIndex());
if (pair == null) {
return;
}
afterCellDispose(writeSheetHolder, writeTableHolder, cellDataList, cell, head, relativeRowIndex, isHead,
pair.getKey(), pair.getValue());
}
public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead, Field key, T ann) {
}
private static Map<String, Map<Integer, ?>> FIELDS_CACHE = new ConcurrentHashMap<>();
private static Map<Class, Class> HANDLER_ANNOTATION_CACHE = new ConcurrentHashMap<>();
@SuppressWarnings("unchecked")
private static <T> Map<Integer, Pair<Field, T>> getFieldMapper(Class cls, Class handlerClass) {
String key = cls.getName() + "-" + handlerClass.getName();
Map fieldMapper = FIELDS_CACHE.get(key);
if (fieldMapper != null) {
return (Map<Integer, Pair<Field, T>>) fieldMapper;
}
Class annCls = HANDLER_ANNOTATION_CACHE.computeIfAbsent(handlerClass, k -> getAnnotationClass(handlerClass));
FIELDS_CACHE.putIfAbsent(key, parseFields(cls, annCls));
return (Map<Integer, Pair<Field, T>>) FIELDS_CACHE.get(key);
}
@SuppressWarnings("unchecked")
protected static Class getAnnotationClass(Class handlerClass) {
Type genericSuperclass = handlerClass.getGenericSuperclass();
if (genericSuperclass instanceof Class) {
// try to climb up the hierarchy until meet something useful
if (AnnotatedCellWriteHandler.class != genericSuperclass) {
return getAnnotationClass(handlerClass.getSuperclass());
}
throw new TypeException("'" + handlerClass + "' extends AnnotatedCellWriteHandler but misses the type parameter. "
+ "Remove the extension or add a type parameter to it.");
}
Type rawType = ((ParameterizedType) genericSuperclass).getActualTypeArguments()[0];
if (rawType instanceof ParameterizedType) {
rawType = ((ParameterizedType) rawType).getRawType();
}
if (!(rawType instanceof Class)) {
throw new TypeException("'" + handlerClass + "' extends AnnotatedCellWriteHandler but can not find the type parameter. "
+ "Remove the extension or add a type parameter to it.");
}
return (Class) rawType;
}
private static Map<Integer, Object> parseFields(Class cls, Class<? extends Annotation> ann) {
final Map<Integer, Object> fieldMap = new HashMap<>();
final Field[] fields = cls.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
Annotation annotation = field.getAnnotation(ann);
if (annotation == null) {
continue;
}
Pair pair = Pair.of(field, annotation);
ExcelProperty excelProperty = AnnotationUtils.getAnnotation(field, ExcelProperty.class);
if (excelProperty != null) {
int index = excelProperty.index();
if (index != -1) {
Asserts.isNull(fieldMap.put(index, pair), BasicErrorCode.PARAM_ERROR.code(), "duplicated column:" + index);
continue;
}
}
Asserts.isNull(fieldMap.put(i, pair), BasicErrorCode.PARAM_ERROR.code(), "duplicated column:" + i);
}
return fieldMap;
}
}
/**
* 支持默认值
*
* @author tangcent
* @create 2021-01-29
*/
public class DefaultWriteHandler extends AnnotatedCellWriteHandler<Default> {
public DefaultWriteHandler(Class headClass) {
super(headClass);
}
@Override
public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead, Field key, Default ann) {
if (isHead) {
return;
}
if (cellDataList != null && cellDataList.size() == 1) {
CellData cellData = cellDataList.get(0);
cellData.checkEmpty();
if (cellData.getType() == CellDataTypeEnum.EMPTY) {
cell.setCellValue(ann.value());
}
}
}
}
final WriteSheet xxxSheet = EasyExcel.writerSheet(1, "xxx")
...
.registerWriteHandler(new DefaultWriteHandler(XxxExcelVO.class))
.build()
@Default("——")
@ExcelProperty(value = "xxx")
private Double xxx; 如果你有更好的方案或者新的想法,请在此issue告知我 |
如果使用converter能处理单元格为空的情况吗?我发现单元格为空时,没有经过converter |
已经在 |
场景/需求
某些情况下,字段为空,希望展示为
-
尝试的解决方案
我尝试定义如下的
CellWriteHandler
:但是由于
easyexcel/src/main/java/com/alibaba/excel/write/executor/AbstractExcelWriteExecutor.java
Lines 35 to 37 in 756f16e
null值并不会触发:
easyexcel/src/main/java/com/alibaba/excel/write/executor/AbstractExcelWriteExecutor.java
Line 48 in 756f16e
是否有合适的解决方案?
The text was updated successfully, but these errors were encountered: