diff --git a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/aop/RequestExcelArgumentResolver.java b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/aop/RequestExcelArgumentResolver.java index 68e30c2f7..b847802c9 100644 --- a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/aop/RequestExcelArgumentResolver.java +++ b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/aop/RequestExcelArgumentResolver.java @@ -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(); diff --git a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/converters/LongStringConverter.java b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/converters/LongStringConverter.java new file mode 100644 index 000000000..c01df07fc --- /dev/null +++ b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/converters/LongStringConverter.java @@ -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 { + + /** + * 实例 + */ + 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 convertToExcelData(Long value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { + return new WriteCellData<>(String.valueOf(value)); + } + +} diff --git a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/handler/AbstractSheetWriteHandler.java b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/handler/AbstractSheetWriteHandler.java index 14a4b2120..8d4b716be 100644 --- a/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/handler/AbstractSheetWriteHandler.java +++ b/pigx-common/pigx-common-excel/src/main/java/com/pig4cloud/pigx/common/excel/handler/AbstractSheetWriteHandler.java @@ -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>> converterProvider; + private final ObjectProvider>> 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 clazz : responseExcel.writeHandler()) { - writerBuilder.registerWriteHandler(BeanUtils.instantiateClass(clazz)); - } - } + if (responseExcel.writeHandler().length != 0) { + for (Class 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 clazz : responseExcel.converter()) { - writerBuilder.registerConverter(BeanUtils.instantiateClass(clazz)); - } - } + if (responseExcel.converter().length != 0) { + for (Class 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 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 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 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 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 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 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 headGeneratorClass) { - return !Modifier.isInterface(headGeneratorClass.getModifiers()); - } + /** + * 是否为Null Head Generator + * + * @param headGeneratorClass 头生成器类型 + * @return true 已指定 false 未指定(默认值) + */ + private boolean isNotInterface(Class 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; + } }