咔片PPT · AI自动生成演示文稿,模板丰富、排版精美 讯飞智文 · 一键生成PPT和Word,高效应对学习与办公

1.excel数据

字符串

日期

小数

F1

F2

F3

33020220220514123x

2022-05-13 12:34:56

1.23

330202202205141235

2022-05-13 13:34:56

1.24

330202202205141234

2022-05-13 14:34:56

1.25

330202202205141235

2022-05-13 15:34:56

1.26

2.数据接受类

本例,做自定义数据转换,内置的数据转换(日期时间,数值格式)这2种示例

字符串,转大写

时间,转中文时间表示

数字,转中文金额表示

详见下类

package com.example.support.entity; import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.format.DateTimeFormat; import com.alibaba.excel.annotation.format.NumberFormat; import com.example.support.excel.convertor.IdLetterConvertor; import lombok.Data; /** * @author LWB * @Description */ @Data public class ReadConvertorDTO { @ExcelProperty(value = "F1",converter = IdLetterConvertor.class) private String str; /** 这里用string 去接日期才能格式化。我想接收年月日格式 */ @ExcelProperty("F2") @DateTimeFormat("yyyy年MM月dd日 HH时mm分ss秒") private String time; /** 我想接收人民币数值 */ @ExcelProperty("F3") @NumberFormat("¥ #.##") private String money; }

内置的类型转换就这2种,而且这2种比较常用

其他需要自定义的类型转换,需要实现Converter


@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface DateTimeFormat { /** * * Specific format reference {@link java.text.SimpleDateFormat} * * @return Format pattern */ String value() default ""; /** * True if date uses 1904 windowing, or false if using 1900 date windowing. * * @return True if date uses 1904 windowing, or false if using 1900 date windowing. */ BooleanEnum use1904windowing() default BooleanEnum.DEFAULT; }

@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface NumberFormat { /** * * Specific format reference {@link java.text.DecimalFormat} * * @return Format pattern */ String value() default ""; /** * Rounded by default * * @return RoundingMode */ RoundingMode roundingMode() default RoundingMode.HALF_UP; }

3.自定义的类型转换器

package com.example.support.excel.convertor; import com.alibaba.excel.converters.Converter; import com.alibaba.excel.converters.ReadConverterContext; import lombok.extern.slf4j.Slf4j; /** * @author LWB * @Description 身份证字符转换 * 用于导入身份证号时,若身份证存在小写x,则接收时转换为大写X * 注意:Converter 中的泛型,指的是需要转换的目标类型 */ @Slf4j public class IdLetterConvertor implements Converter { /** * 读取excel时,主要就是重写本方法来实现数据的自定义转换 * @param context * @return * @throws Exception */ @Override public String convertToJavaData(ReadConverterContext context) throws Exception { String data = context.getReadCellData().getStringValue(); if (null == data) return null;//非空判断 String convertedData = data.toUpperCase();//转大写 log.info("{} -> {}",data,convertedData); return convertedData; } }

4.ReadListener

package com.example.support.excel.listener; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.read.listener.ReadListener; import com.example.global.HttpHolder; import com.example.service.ExcelService; import com.example.support.entity.ExcelReadDTO; import com.example.support.entity.ReadConvertorDTO; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import java.util.ArrayList; import java.util.List; /** * @author LWB * @Description excel读取的监听器 * 有个很重要的点 ExcelReadListener监听器 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去 * 所以,如果需要传入spring管理的对象,要么按照文档中的说明,直接使用构造器传参进来,要么使用ThreadLocal线程级别的变量工具传参 * 实际应用中,可能会需要传入很多的spring管理的对象,或者其他上下文参数,遇到这种情况,建议使用ThreadLocal来传递参数,简单,便捷,无需重复修改构造器 * 如果是简单的传递个别上下文参数,也可以选用构造器传参的方式 */ @Slf4j public class ExcelReadConvertorListener implements ReadListener { private ExcelService excelService; /** * 不适用构造器传入,使用threadLocal工具传入 * 适用于读取监听器中,需要使用多个上下文参数的情况 */ public ExcelReadConvertorListener(){ this.excelService = HttpHolder.get("excelService",ExcelService.class); String p1 = HttpHolder.get("p1", String.class); String p2 = HttpHolder.get("p2", String.class); } /** * 构造器中传入spring管理的对象 * 适用于传入较少上下文参数的情况 * @param excelService */ public ExcelReadConvertorListener(ExcelService excelService){ this.excelService = excelService; } /** * 每隔N条存储数据库,实际使用中可以1000条或者更多,然后清理cachedDataList ,方便内存回收 * 如果表格数据量很大,成千上万条,可以分批进行入库,数量不多的话,没必要做分配 */ private static final int BATCH_COUNT = 100; /** * 缓存的数据 */ private List cachedDataList = new ArrayList<>(BATCH_COUNT); /** * 这个方法,每一条数据解析都会来调用 * @param data * @param context */ @Override public void invoke(ReadConvertorDTO data, AnalysisContext context) { log.info("正在读取sheet:[{}]的数据:{}",context.readSheetHolder().getSheetName(), data.toString()); // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM /* if (cachedDataList.size() >= BATCH_COUNT) { //保存 excelService.saveData(); // 存储完成清理 list cachedDataList.clear(); }*/ } /** * 所有数据解析完成了 会来调用 * @param context */ @Override public void doAfterAllAnalysed(AnalysisContext context) { log.info("sheet:[{}]读取完成!",context.readSheetHolder().getSheetName()); //若进行分批处理,在读取完成后,还要检查下 cachedDataList 中是否还有剩余未入库的数据,因为如果没达到缓存最大值,invoke方法不会进行存储 //if(cachedDataList.size() > 0) excelService.saveData(); } }

5.接口方法

/** * 读取excel 并实现数据转换为接收对象中字段的类型 * @param excelFile * @return */ @PostMapping("readConvertor") @SneakyThrows public Ret readConvertor(MultipartFile excelFile){ ExcelReadConvertorListener excelReadListener = new ExcelReadConvertorListener(excelService); EasyExcel.read(excelFile.getInputStream(), ReadConvertorDTO.class,excelReadListener) .sheet()//指定读取哪个sheet .headRowNumber(2)//指定标题行(需要) .doRead();//执行读取 return Ret.success(); }

#6.控制台输出结果

可以看到,

小写x成功转大写X了

日期时间格式成功转换

人民币金额格式成功转换

c.e.s.excel.convertor.IdLetterConvertor : 33020220220514123x -> 33020220220514123X c.e.s.e.l.ExcelReadConvertorListener : 正在读取sheet:[Sheet1]的数据:ReadConvertorDTO(str=33020220220514123X, time=2022年05月13日 12时34分56秒, money=¥ 1.23) c.e.s.excel.convertor.IdLetterConvertor : 330202202205141235 -> 330202202205141235 c.e.s.e.l.ExcelReadConvertorListener : 正在读取sheet:[Sheet1]的数据:ReadConvertorDTO(str=330202202205141235, time=2022年05月13日 13时34分56秒, money=¥ 1.24) c.e.s.excel.convertor.IdLetterConvertor : 330202202205141234 -> 330202202205141234 c.e.s.e.l.ExcelReadConvertorListener : 正在读取sheet:[Sheet1]的数据:ReadConvertorDTO(str=330202202205141234, time=2022年05月13日 14时34分56秒, money=¥ 1.25) c.e.s.excel.convertor.IdLetterConvertor : 330202202205141235 -> 330202202205141235 c.e.s.e.l.ExcelReadConvertorListener : 正在读取sheet:[Sheet1]的数据:ReadConvertorDTO(str=330202202205141235, time=2022年05月13日 15时34分56秒, money=¥ 1.26) c.e.s.e.l.ExcelReadConvertorListener : sheet:[Sheet1]读取完成!