mirror of
http://git.pig4cloud.com/pig/pigx.git
synced 2026-11-08 20:49:00 +08:00
✨ Introducing new features. 增加 easyexcel long 转换器 string 避免精度丢失
This commit is contained in:
1 parent
c9a136324d
commit
eb9109375e
3 files changed
+188
-150
No files matched your search
+2
@@ -4,6 +4,7 @@ import com.alibaba.excel.EasyExcel;
|
||||
import com.pig4cloud.pigx.common.excel.annotation.RequestExcel;
|
||||
import com.pig4cloud.pigx.common.excel.converters.LocalDateStringConverter;
|
||||
import com.pig4cloud.pigx.common.excel.converters.LocalDateTimeStringConverter;
|
||||
import com.pig4cloud.pigx.common.excel.converters.LongStringConverter;
|
||||
import com.pig4cloud.pigx.common.excel.converters.StringArrayConverter;
|
||||
import com.pig4cloud.pigx.common.excel.handler.ListAnalysisEventListener;
|
||||
import lombok.SneakyThrows;
|
||||
@@ -75,6 +76,7 @@ public class RequestExcelArgumentResolver implements HandlerMethodArgumentResolv
|
||||
// 这里需要指定读用哪个 class 去读,然后读取第一个 sheet 文件流会自动关闭
|
||||
EasyExcel.read(inputStream, excelModelClass, readListener).registerConverter(LocalDateStringConverter.INSTANCE)
|
||||
.registerConverter(LocalDateTimeStringConverter.INSTANCE)
|
||||
.registerConverter(LongStringConverter.INSTANCE)
|
||||
.registerConverter(StringArrayConverter.INSTANCE).ignoreEmptyRow(requestExcel.ignoreEmptyRow()).sheet()
|
||||
.headRowNumber(requestExcel.headRowNumber()).doRead();
|
||||
|
||||
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
package com.pig4cloud.pigx.common.excel.converters;
|
||||
|
||||
import com.alibaba.excel.converters.Converter;
|
||||
import com.alibaba.excel.enums.CellDataTypeEnum;
|
||||
import com.alibaba.excel.metadata.GlobalConfiguration;
|
||||
import com.alibaba.excel.metadata.data.ReadCellData;
|
||||
import com.alibaba.excel.metadata.data.WriteCellData;
|
||||
import com.alibaba.excel.metadata.property.ExcelContentProperty;
|
||||
|
||||
import java.text.ParseException;
|
||||
|
||||
/**
|
||||
* Long and string converter
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
public enum LongStringConverter implements Converter<Long> {
|
||||
|
||||
/**
|
||||
* 实例
|
||||
*/
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public Class supportJavaTypeKey() {
|
||||
return Long.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CellDataTypeEnum supportExcelTypeKey() {
|
||||
return CellDataTypeEnum.STRING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws ParseException {
|
||||
return Long.parseLong(cellData.getStringValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public WriteCellData<String> convertToExcelData(Long value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
|
||||
return new WriteCellData<>(String.valueOf(value));
|
||||
}
|
||||
|
||||
}
|
||||
+142
-150
@@ -11,6 +11,7 @@ import com.pig4cloud.pigx.common.excel.annotation.ResponseExcel;
|
||||
import com.pig4cloud.pigx.common.excel.annotation.Sheet;
|
||||
import com.pig4cloud.pigx.common.excel.aop.DynamicNameAspect;
|
||||
import com.pig4cloud.pigx.common.excel.config.ExcelConfigProperties;
|
||||
import com.pig4cloud.pigx.common.excel.converters.LongStringConverter;
|
||||
import com.pig4cloud.pigx.common.excel.converters.StringArrayConverter;
|
||||
import com.pig4cloud.pigx.common.excel.enhance.WriterBuilderEnhancer;
|
||||
import com.pig4cloud.pigx.common.excel.head.HeadGenerator;
|
||||
@@ -58,182 +59,173 @@ import java.util.UUID;
|
||||
@RequiredArgsConstructor
|
||||
public abstract class AbstractSheetWriteHandler implements SheetWriteHandler, ApplicationContextAware {
|
||||
|
||||
private final ExcelConfigProperties configProperties;
|
||||
private final ExcelConfigProperties configProperties;
|
||||
|
||||
private final ObjectProvider<List<Converter<?>>> converterProvider;
|
||||
private final ObjectProvider<List<Converter<?>>> converterProvider;
|
||||
|
||||
private final WriterBuilderEnhancer excelWriterBuilderEnhance;
|
||||
private final WriterBuilderEnhancer excelWriterBuilderEnhance;
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Autowired(required = false)
|
||||
private I18nHeaderCellWriteHandler i18nHeaderCellWriteHandler;
|
||||
@Getter
|
||||
@Setter
|
||||
@Autowired(required = false)
|
||||
private I18nHeaderCellWriteHandler i18nHeaderCellWriteHandler;
|
||||
|
||||
@Override
|
||||
public void check(ResponseExcel responseExcel) {
|
||||
if (responseExcel.sheets().length == 0) {
|
||||
throw new ExcelException("@ResponseExcel sheet 配置不合法");
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void check(ResponseExcel responseExcel) {
|
||||
if (responseExcel.sheets().length == 0) {
|
||||
throw new ExcelException("@ResponseExcel sheet 配置不合法");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows(UnsupportedEncodingException.class)
|
||||
public void export(Object o, HttpServletResponse response, ResponseExcel responseExcel) {
|
||||
check(responseExcel);
|
||||
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
|
||||
String name = (String) Objects.requireNonNull(requestAttributes).getAttribute(DynamicNameAspect.EXCEL_NAME_KEY,
|
||||
RequestAttributes.SCOPE_REQUEST);
|
||||
if (name == null) {
|
||||
name = UUID.randomUUID().toString();
|
||||
}
|
||||
String fileName = String.format("%s%s", URLEncoder.encode(name, "UTF-8"), responseExcel.suffix().getValue());
|
||||
// 根据实际的文件类型找到对应的 contentType
|
||||
String contentType = MediaTypeFactory.getMediaType(fileName).map(MediaType::toString)
|
||||
.orElse("application/vnd.ms-excel");
|
||||
response.setContentType(contentType);
|
||||
response.setCharacterEncoding("utf-8");
|
||||
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename*=utf-8''" + fileName);
|
||||
write(o, response, responseExcel);
|
||||
}
|
||||
@Override
|
||||
@SneakyThrows(UnsupportedEncodingException.class)
|
||||
public void export(Object o, HttpServletResponse response, ResponseExcel responseExcel) {
|
||||
check(responseExcel);
|
||||
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
|
||||
String name = (String) Objects.requireNonNull(requestAttributes).getAttribute(DynamicNameAspect.EXCEL_NAME_KEY, RequestAttributes.SCOPE_REQUEST);
|
||||
if (name == null) {
|
||||
name = UUID.randomUUID().toString();
|
||||
}
|
||||
String fileName = String.format("%s%s", URLEncoder.encode(name, "UTF-8"), responseExcel.suffix().getValue());
|
||||
// 根据实际的文件类型找到对应的 contentType
|
||||
String contentType = MediaTypeFactory.getMediaType(fileName).map(MediaType::toString).orElse("application/vnd.ms-excel");
|
||||
response.setContentType(contentType);
|
||||
response.setCharacterEncoding("utf-8");
|
||||
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename*=utf-8''" + fileName);
|
||||
write(o, response, responseExcel);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通用的获取ExcelWriter方法
|
||||
* @param response HttpServletResponse
|
||||
* @param responseExcel ResponseExcel注解
|
||||
* @return ExcelWriter
|
||||
*/
|
||||
@SneakyThrows(IOException.class)
|
||||
public ExcelWriter getExcelWriter(HttpServletResponse response, ResponseExcel responseExcel) {
|
||||
ExcelWriterBuilder writerBuilder = EasyExcel.write(response.getOutputStream())
|
||||
.registerConverter(LocalDateStringConverter.INSTANCE)
|
||||
.registerConverter(LocalDateTimeStringConverter.INSTANCE)
|
||||
.registerConverter(StringArrayConverter.INSTANCE).autoCloseStream(true)
|
||||
.excelType(responseExcel.suffix()).inMemory(responseExcel.inMemory());
|
||||
/**
|
||||
* 通用的获取ExcelWriter方法
|
||||
*
|
||||
* @param response HttpServletResponse
|
||||
* @param responseExcel ResponseExcel注解
|
||||
* @return ExcelWriter
|
||||
*/
|
||||
@SneakyThrows(IOException.class)
|
||||
public ExcelWriter getExcelWriter(HttpServletResponse response, ResponseExcel responseExcel) {
|
||||
ExcelWriterBuilder writerBuilder = EasyExcel.write(response.getOutputStream()).registerConverter(LocalDateStringConverter.INSTANCE).registerConverter(LocalDateTimeStringConverter.INSTANCE).registerConverter(LongStringConverter.INSTANCE).registerConverter(StringArrayConverter.INSTANCE).autoCloseStream(true).excelType(responseExcel.suffix()).inMemory(responseExcel.inMemory());
|
||||
|
||||
if (StringUtils.hasText(responseExcel.password())) {
|
||||
writerBuilder.password(responseExcel.password());
|
||||
}
|
||||
if (StringUtils.hasText(responseExcel.password())) {
|
||||
writerBuilder.password(responseExcel.password());
|
||||
}
|
||||
|
||||
if (responseExcel.include().length != 0) {
|
||||
writerBuilder.includeColumnFieldNames(Arrays.asList(responseExcel.include()));
|
||||
}
|
||||
if (responseExcel.include().length != 0) {
|
||||
writerBuilder.includeColumnFieldNames(Arrays.asList(responseExcel.include()));
|
||||
}
|
||||
|
||||
if (responseExcel.exclude().length != 0) {
|
||||
writerBuilder.includeColumnFieldNames(Arrays.asList(responseExcel.exclude()));
|
||||
}
|
||||
if (responseExcel.exclude().length != 0) {
|
||||
writerBuilder.includeColumnFieldNames(Arrays.asList(responseExcel.exclude()));
|
||||
}
|
||||
|
||||
if (responseExcel.writeHandler().length != 0) {
|
||||
for (Class<? extends WriteHandler> clazz : responseExcel.writeHandler()) {
|
||||
writerBuilder.registerWriteHandler(BeanUtils.instantiateClass(clazz));
|
||||
}
|
||||
}
|
||||
if (responseExcel.writeHandler().length != 0) {
|
||||
for (Class<? extends WriteHandler> clazz : responseExcel.writeHandler()) {
|
||||
writerBuilder.registerWriteHandler(BeanUtils.instantiateClass(clazz));
|
||||
}
|
||||
}
|
||||
|
||||
// 开启国际化头信息处理
|
||||
if (responseExcel.i18nHeader() && i18nHeaderCellWriteHandler != null) {
|
||||
writerBuilder.registerWriteHandler(i18nHeaderCellWriteHandler);
|
||||
}
|
||||
// 开启国际化头信息处理
|
||||
if (responseExcel.i18nHeader() && i18nHeaderCellWriteHandler != null) {
|
||||
writerBuilder.registerWriteHandler(i18nHeaderCellWriteHandler);
|
||||
}
|
||||
|
||||
// 自定义注入的转换器
|
||||
registerCustomConverter(writerBuilder);
|
||||
// 自定义注入的转换器
|
||||
registerCustomConverter(writerBuilder);
|
||||
|
||||
if (responseExcel.converter().length != 0) {
|
||||
for (Class<? extends Converter> clazz : responseExcel.converter()) {
|
||||
writerBuilder.registerConverter(BeanUtils.instantiateClass(clazz));
|
||||
}
|
||||
}
|
||||
if (responseExcel.converter().length != 0) {
|
||||
for (Class<? extends Converter> clazz : responseExcel.converter()) {
|
||||
writerBuilder.registerConverter(BeanUtils.instantiateClass(clazz));
|
||||
}
|
||||
}
|
||||
|
||||
String templatePath = configProperties.getTemplatePath();
|
||||
if (StringUtils.hasText(responseExcel.template())) {
|
||||
ClassPathResource classPathResource = new ClassPathResource(
|
||||
templatePath + File.separator + responseExcel.template());
|
||||
InputStream inputStream = classPathResource.getInputStream();
|
||||
writerBuilder.withTemplate(inputStream);
|
||||
}
|
||||
String templatePath = configProperties.getTemplatePath();
|
||||
if (StringUtils.hasText(responseExcel.template())) {
|
||||
ClassPathResource classPathResource = new ClassPathResource(templatePath + File.separator + responseExcel.template());
|
||||
InputStream inputStream = classPathResource.getInputStream();
|
||||
writerBuilder.withTemplate(inputStream);
|
||||
}
|
||||
|
||||
writerBuilder = excelWriterBuilderEnhance.enhanceExcel(writerBuilder, response, responseExcel, templatePath);
|
||||
writerBuilder = excelWriterBuilderEnhance.enhanceExcel(writerBuilder, response, responseExcel, templatePath);
|
||||
|
||||
return writerBuilder.build();
|
||||
}
|
||||
return writerBuilder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义注入转换器 如果有需要,子类自己重写
|
||||
* @param builder ExcelWriterBuilder
|
||||
*/
|
||||
public void registerCustomConverter(ExcelWriterBuilder builder) {
|
||||
converterProvider.ifAvailable(converters -> converters.forEach(builder::registerConverter));
|
||||
}
|
||||
/**
|
||||
* 自定义注入转换器 如果有需要,子类自己重写
|
||||
*
|
||||
* @param builder ExcelWriterBuilder
|
||||
*/
|
||||
public void registerCustomConverter(ExcelWriterBuilder builder) {
|
||||
converterProvider.ifAvailable(converters -> converters.forEach(builder::registerConverter));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 WriteSheet 对象
|
||||
* @param sheet sheet annotation info
|
||||
* @param dataClass 数据类型
|
||||
* @param template 模板
|
||||
* @param bookHeadEnhancerClass 自定义头处理器
|
||||
* @return WriteSheet
|
||||
*/
|
||||
public WriteSheet sheet(Sheet sheet, Class<?> dataClass, String template,
|
||||
Class<? extends HeadGenerator> bookHeadEnhancerClass) {
|
||||
/**
|
||||
* 获取 WriteSheet 对象
|
||||
*
|
||||
* @param sheet sheet annotation info
|
||||
* @param dataClass 数据类型
|
||||
* @param template 模板
|
||||
* @param bookHeadEnhancerClass 自定义头处理器
|
||||
* @return WriteSheet
|
||||
*/
|
||||
public WriteSheet sheet(Sheet sheet, Class<?> dataClass, String template, Class<? extends HeadGenerator> bookHeadEnhancerClass) {
|
||||
|
||||
// Sheet 编号和名称
|
||||
Integer sheetNo = sheet.sheetNo() >= 0 ? sheet.sheetNo() : null;
|
||||
String sheetName = sheet.sheetName();
|
||||
// Sheet 编号和名称
|
||||
Integer sheetNo = sheet.sheetNo() >= 0 ? sheet.sheetNo() : null;
|
||||
String sheetName = sheet.sheetName();
|
||||
|
||||
// 是否模板写入
|
||||
ExcelWriterSheetBuilder writerSheetBuilder = StringUtils.hasText(template) ? EasyExcel.writerSheet(sheetNo)
|
||||
: EasyExcel.writerSheet(sheetNo, sheetName);
|
||||
// 是否模板写入
|
||||
ExcelWriterSheetBuilder writerSheetBuilder = StringUtils.hasText(template) ? EasyExcel.writerSheet(sheetNo) : EasyExcel.writerSheet(sheetNo, sheetName);
|
||||
|
||||
// 头信息增强 1. 优先使用 sheet 指定的头信息增强 2. 其次使用 @ResponseExcel 中定义的全局头信息增强
|
||||
Class<? extends HeadGenerator> headGenerateClass = null;
|
||||
if (isNotInterface(sheet.headGenerateClass())) {
|
||||
headGenerateClass = sheet.headGenerateClass();
|
||||
}
|
||||
else if (isNotInterface(bookHeadEnhancerClass)) {
|
||||
headGenerateClass = bookHeadEnhancerClass;
|
||||
}
|
||||
// 定义头信息增强则使用其生成头信息,否则使用 dataClass 来自动获取
|
||||
if (headGenerateClass != null) {
|
||||
fillCustomHeadInfo(dataClass, bookHeadEnhancerClass, writerSheetBuilder);
|
||||
}
|
||||
else if (dataClass != null) {
|
||||
writerSheetBuilder.head(dataClass);
|
||||
if (sheet.excludes().length > 0) {
|
||||
writerSheetBuilder.excludeColumnFieldNames(Arrays.asList(sheet.excludes()));
|
||||
}
|
||||
if (sheet.includes().length > 0) {
|
||||
writerSheetBuilder.excludeColumnFieldNames(Arrays.asList(sheet.includes()));
|
||||
}
|
||||
}
|
||||
// 头信息增强 1. 优先使用 sheet 指定的头信息增强 2. 其次使用 @ResponseExcel 中定义的全局头信息增强
|
||||
Class<? extends HeadGenerator> headGenerateClass = null;
|
||||
if (isNotInterface(sheet.headGenerateClass())) {
|
||||
headGenerateClass = sheet.headGenerateClass();
|
||||
} else if (isNotInterface(bookHeadEnhancerClass)) {
|
||||
headGenerateClass = bookHeadEnhancerClass;
|
||||
}
|
||||
// 定义头信息增强则使用其生成头信息,否则使用 dataClass 来自动获取
|
||||
if (headGenerateClass != null) {
|
||||
fillCustomHeadInfo(dataClass, bookHeadEnhancerClass, writerSheetBuilder);
|
||||
} else if (dataClass != null) {
|
||||
writerSheetBuilder.head(dataClass);
|
||||
if (sheet.excludes().length > 0) {
|
||||
writerSheetBuilder.excludeColumnFieldNames(Arrays.asList(sheet.excludes()));
|
||||
}
|
||||
if (sheet.includes().length > 0) {
|
||||
writerSheetBuilder.excludeColumnFieldNames(Arrays.asList(sheet.includes()));
|
||||
}
|
||||
}
|
||||
|
||||
// sheetBuilder 增强
|
||||
writerSheetBuilder = excelWriterBuilderEnhance.enhanceSheet(writerSheetBuilder, sheetNo, sheetName, dataClass,
|
||||
template, headGenerateClass);
|
||||
// sheetBuilder 增强
|
||||
writerSheetBuilder = excelWriterBuilderEnhance.enhanceSheet(writerSheetBuilder, sheetNo, sheetName, dataClass, template, headGenerateClass);
|
||||
|
||||
return writerSheetBuilder.build();
|
||||
}
|
||||
return writerSheetBuilder.build();
|
||||
}
|
||||
|
||||
private void fillCustomHeadInfo(Class<?> dataClass, Class<? extends HeadGenerator> headEnhancerClass,
|
||||
ExcelWriterSheetBuilder writerSheetBuilder) {
|
||||
HeadGenerator headGenerator = this.applicationContext.getBean(headEnhancerClass);
|
||||
Assert.notNull(headGenerator, "The header generated bean does not exist.");
|
||||
HeadMeta head = headGenerator.head(dataClass);
|
||||
writerSheetBuilder.head(head.getHead());
|
||||
writerSheetBuilder.excludeColumnFieldNames(head.getIgnoreHeadFields());
|
||||
}
|
||||
private void fillCustomHeadInfo(Class<?> dataClass, Class<? extends HeadGenerator> headEnhancerClass, ExcelWriterSheetBuilder writerSheetBuilder) {
|
||||
HeadGenerator headGenerator = this.applicationContext.getBean(headEnhancerClass);
|
||||
Assert.notNull(headGenerator, "The header generated bean does not exist.");
|
||||
HeadMeta head = headGenerator.head(dataClass);
|
||||
writerSheetBuilder.head(head.getHead());
|
||||
writerSheetBuilder.excludeColumnFieldNames(head.getIgnoreHeadFields());
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为Null Head Generator
|
||||
* @param headGeneratorClass 头生成器类型
|
||||
* @return true 已指定 false 未指定(默认值)
|
||||
*/
|
||||
private boolean isNotInterface(Class<? extends HeadGenerator> headGeneratorClass) {
|
||||
return !Modifier.isInterface(headGeneratorClass.getModifiers());
|
||||
}
|
||||
/**
|
||||
* 是否为Null Head Generator
|
||||
*
|
||||
* @param headGeneratorClass 头生成器类型
|
||||
* @return true 已指定 false 未指定(默认值)
|
||||
*/
|
||||
private boolean isNotInterface(Class<? extends HeadGenerator> headGeneratorClass) {
|
||||
return !Modifier.isInterface(headGeneratorClass.getModifiers());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user