阿里出品 easyExcel[基于poi] 入门小结及优化

本文总结了阿里出品的easyExcel的入门要点,包括常见问题的解决,如Zip bomb异常,以及各种注解和监听器的使用。通过示例代码展示了如何进行日期和数字转换,自定义转换器,以及在导入导出Excel时的操作。

阿里出品 easyExcel[基于poi] 入门小结及优化

着急可直接看最下面java代码

常用maven依赖


        <!-- Excel 工具 开始 -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>4.1.2</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>3.0.5</version>
        </dependency>
        <!-- Excel 工具 结束 -->

  		<!-- 其他依赖 -->

        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.22</version>
            <!--<scope>provided</scope>-->
        </dependency>

 		<!-- JSON 工具 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.47</version>
        </dependency>

		<!-- web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

常见问题

1. com.alibaba.excel.exception.ExcelCommonException: Convert excel format exception.You can try specifying the ‘excelType’ yourself

此情况先看是否能找到指定路径下的文件

注意:获取根目录功能 可能在Junit 中不生效

java.io.IOException: Zip bomb detected! The file would exceed the max. ratio of compressed file size to the size of the expanded data.

zip 炸弹检测!

在解压缩时,它会检查比率compressedBytes/uncompressedBytes,如果低于特定数量 ( MinInflateRatio),则检测到炸弹。

在这里插入图片描述

源码中默认最小比例为 0.01D. 这意味着压缩文件比未压缩文件小 100 倍,而不会丢失信息。换言之,压缩后的文件仅以未压缩文件大小的 1% 存储相同的信息。

Uncompressed size[未压缩大小]: 875067, Raw/compressed size[压缩大小]: 8704, ratio[比例]: 0.009947

解决方案

但这意味着没有要解压缩的字节。因此,MinInflateRatioof0.0d永远无法达到,也无法被低估。因此MinInflateRatio0.0d所有可能的比率都将被接受。

当然MinInflateRatio-1.0d也永远无法达到或被低估。所以使用这个也将接受所有可能的比率。

常用注解

@ColumnWidth 用于设置列宽度的注解。


参数:
注解中只有一个参数value,value的单位是字符长度,最大可以设置255个字符,因为一个excel单元格最大可以写入的字符个数就是255个字符。

@HeadFontStyle 用于定制标题字体格式


参数:
fontName	字体名称
fontHeightInPoints	字体高度
italic	是否斜体
strikeout	是否设置删除水平线
color	字体颜色
typeOffset	偏移量
underline	下划线
bold	是否加粗
charset	编码格式
@ContentLoopMerge 用于设置合并单元格的注解
标注在属性上
参数:
eachRow	合并行
columnExtend	合并列
@ContentRowHeight 用于设置行高
参数:
value	行高,-1代表自动行高
@ContentStyle 设置内容格式注解
参数:
dataFormat	日期格式
hidden	设置单元格使用此样式隐藏
locked	设置单元格使用此样式锁定
quotePrefix	在单元格前面增加'`'符号,数字或公式将以字符串形式展示
horizontalAlignment	设置是否水平居中
wrapped	设置文本是否应换行。将此标志设置为true通过在多行上显示使单元格中的所有内容可见
verticalAlignment	设置是否垂直居中
rotation	设置单元格中文本旋转角度。03版本的Excel旋转角度区间为-90°~90°,07版本的Excel旋转角度区间为0°~180°
indent	设置单元格中缩进文本的空格数
borderLeft	设置左边框的样式
borderRight	设置右边框样式
borderTop	设置上边框样式
borderBottom	设置下边框样式
leftBorderColor	设置左边框颜色
rightBorderColor	设置右边框颜色
topBorderColor	设置上边框颜色
bottomBorderColor	设置下边框颜色
fillPatternType	设置填充类型
fillBackgroundColor	设置背景色
fillForegroundColor	设置前景色
shrinkToFit	设置自动单元格自动大小
@HeadRowHeight设置标题行行高
参数:
value 设置行高,-1代表自动行高
@HeadStyle 设置标题样式
参数:
dataFormat	日期格式
hidden	设置单元格使用此样式隐藏
locked	设置单元格使用此样式锁定
quotePrefix	在单元格前面增加`符号,数字或公式将以字符串形式展示
horizontalAlignment	设置是否水平居中
wrapped	设置文本是否应换行。将此标志设置为true通过在多行上显示使单元格中的所有内容可见
verticalAlignment	设置是否垂直居中
rotation	设置单元格中文本旋转角度。03版本的Excel旋转角度区间为-90°~90°,07版本的Excel旋转角度区间为0°~180°
indent	设置单元格中缩进文本的空格数
borderLeft	设置左边框的样式
borderRight	设置右边框样式
borderTop	设置上边框样式
borderBottom	设置下边框样式
leftBorderColor	设置左边框颜色
rightBorderColor	设置右边框颜色
topBorderColor	设置上边框颜色
bottomBorderColor	设置下边框颜色
fillPatternType	设置填充类型
fillBackgroundColor	设置背景色
fillForegroundColor	设置前景色
shrinkToFit	设置自动单元格自动大小
@ExcelIgnore 不将该字段转换成Excel
@ExcelIgnoreUnannotated 没有@ExcelProperty注解的字段都不转换
@ExcelProperty 可以理解为标题列与实体对应的注解

@ExcelProperty("姓名")   # 根据标题[列名]匹配 
@ExcelProperty(index = 1) # 根据列数 0 代表第一列,以此类推
@ExcelProperty(value = "婚姻状态",converter = CustomStringToBooleanConverter.class)

# 注意事项:
# 1、不建议 index 和 name 同时用,要么一个对象只用index,要么一个对象只用name去匹配
# 2、如果用名字去匹配,名字重复,会导致只有一个字段读取到数据
# 根据Excel 结构变化频率去选择 index/name。

参数:
value	标题名
index	列序号
converter 数据转换方式
@DateTimeFormat 日期转换
用String去接收excel日期格式的数据会调用这个注解。里面的value参照 java.text.SimpleDateFormat
例:yyyy-MM-dd HH:mm:ss
@NumberFormat 数字转换
用String去接收excel数字格式的数据会调用这个注解。里面的value参照 java.text.DecimalFormat
例:
“0”——表示一位数值,如没有,显示0。如“0000.0000”,整数位或小数位>4,按实际输出,<4整数位前面补0小数位后面补0,凑足4位。
“#”:无小数,小数部分四舍五入。
“.#”:整数部分不变,一位小数,四舍五入。
“.##”:整数部分不变,二位小数,四舍五入。
“.”——表示小数点。

常用监听器

PageReadListener
# 功能简介:读取Excel数据,默认100条返回一次
# 注意事项: 此处如果调用写入数据库操作,建议用批量插入,最好别一条一条插入。

Java 代码

easyExcel 工具类
package com.husky.easyexcle.utils;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.read.listener.PageReadListener;
import com.alibaba.fastjson.JSON;
import com.husky.easyexcle.entity.ExcelDateEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.system.ApplicationHome;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Author husky
 * @Date 2022/3/14 16:13
 * @Description: easyExcel 工具类
 **/
@Slf4j
public class ExcleUtil {

    /**
     * 读取Excel文件数据
     * @param fileName excel 文件名
     */
    public <T> void readExcel(String fileName, Class<T> tclass) {
        //获取根目录
        ApplicationHome ah = new ApplicationHome(this.getClass());
        String excelPath = ah.getSource().getParentFile().toString()+"/excel/";
        log.info("excelPath={}",excelPath);
        ExcelReader excelReader = null;
        AtomicInteger count = new AtomicInteger();
        try {

            EasyExcel.read(excelPath+fileName, ExcelDateEntity.class, new PageReadListener<T>(
                    dataList -> {
                        for (T demoData : dataList) {

                        }
                        log.info("Excel内容{}", JSON.toJSONString(dataList));
                        count.set(dataList.size());
                        log.info("Excel内容数量:{}",count);
                    }
            )).sheet(0).doRead();
        }catch (Exception e){
            log.error("Excel PageReadListener 读取出错。Exception={}",e);
        }finally {
            if (excelReader != null) {
                // 这里千万别忘记关闭,读的时候会创建临时文件,到时磁盘会崩的
                excelReader.finish();
            }
        }
    }

    /**
     * 将数据写入Excel
     * @param fileName 文件名
     * @param sheetName 工作簿名称
     * @param dataList 带写入数据
     */
    public <T> void exportExcle(String fileName,String sheetName,List<T> dataList, Class headClass){
        //获取根目录
        ApplicationHome ah = new ApplicationHome(this.getClass());

        //excle 导出文件夹
        String excelPath = ah.getSource().getParentFile().toString()+"/excel/";

        //根据年月日创建文件夹
        String timePath = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")).replace("-","/")+"/";
        log.info("excelPath={}",excelPath);
        //如果没有文件夹则新建
        File filePath = new File(excelPath  + timePath);
        if (!filePath.exists()) {
            filePath.mkdirs();
        }

        EasyExcel.write(excelPath+timePath+fileName, headClass)
                .sheet(sheetName)
                .doWrite(() -> {
                    log.info("待导出数据={}",dataList);
                     return dataList;
                });
    }

    public static void main(String[] args) {
        List<ExcelDateEntity> list = new CopyOnWriteArrayList<>();
        ExcelDateEntity excelDateEntity = new ExcelDateEntity();
        excelDateEntity.setAge(19);
        excelDateEntity.setBirthday(LocalDateTime.now());
        excelDateEntity.setMarriedFlag(true);
        excelDateEntity.setName("林婉儿");
        excelDateEntity.setPartyMemberFlag(1);
        excelDateEntity.setShowFlag("不展示");
        excelDateEntity.setSalary("300.2345");
        excelDateEntity.setStature("173");
        list.add(excelDateEntity);
       // new ExcleUtil().exportExcle("aaa.xlsx","我是工作簿",list,ExcelDateEntity.class);
        new ExcleUtil().readExcel("test.xlsx",excelDateEntity.getClass());
    }

    public static <T> List<T> readWebExcelData(MultipartFile file, Class<T> tclass) {
        List<T> resultList = new CopyOnWriteArrayList<>();
        ExcelReader excelReader = null;
        AtomicInteger count = new AtomicInteger();
        try {
            EasyExcel.read(file.getInputStream(), tclass, new PageReadListener<T>(
                    dataList -> {
                        for (T demoData : dataList) {
                            resultList.add(demoData);
                        }
                        log.info("Excel内容{}", JSON.toJSONString(dataList));
                        count.set(dataList.size());
                        log.info("Excel内容数量:{}",count);
                    }

            )).sheet(0).doRead();
            return resultList;
        }catch (Exception e){
            log.error("Excel PageReadListener 读取出错。Exception={}",e);
        }finally {
            if (excelReader != null) {
                // 这里千万别忘记关闭,读的时候会创建临时文件,到时磁盘会崩的
                excelReader.finish();
            }
        }
        return resultList;
    }
}

Excel 数据封装实体
package com.husky.easyexcle.entity;

import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import com.alibaba.excel.annotation.format.NumberFormat;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.HeadFontStyle;
import com.alibaba.excel.annotation.write.style.HeadRowHeight;
import com.husky.easyexcle.annotation.ExportAppendStringAnnotation;
import com.husky.easyexcle.annotation.StringToBooleanConverterAnnotation;
import com.husky.easyexcle.annotation.StringToIntegerConverterAnnotation;
import com.husky.easyexcle.converter.CustomExportAppendStringConverter;
import com.husky.easyexcle.converter.CustomStringToBooleanConverter;
import com.husky.easyexcle.converter.CustomStringToIntegerConverter;
import com.husky.easyexcle.enums.StringToIntegerConverterEnum;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.time.LocalDateTime;

/**
 * @Author husky
 * @Date 2022/3/14 16:18
 * @Description: Excel 数据封装实体
 **/
@ColumnWidth(15)  //列宽
@HeadRowHeight(20) //标题行高
@HeadFontStyle(fontHeightInPoints = 12, color = 9) //文件头的字体大小和颜色
@Data // lombok注解
@Slf4j
public class ExcelDateEntity {

    @ExcelProperty(value = "姓名")
    private String name;

    @ExcelProperty(value = "年龄")
    private Integer age;

    /**
     * 指定字符转转为布尔值
     */
    @StringToBooleanConverterAnnotation(trueStr = "已婚",falseStr = "未婚")
    @ExcelProperty(value = "婚姻状态",converter = CustomStringToBooleanConverter.class)
    private boolean marriedFlag;

    @ExportAppendStringAnnotation(endPositionContent = "万元/月")
    @ExcelProperty(value = "薪资",converter = CustomExportAppendStringConverter.class)
    private String salary;

    @ColumnWidth(20)  //列宽
    @ExcelProperty(value = "生日")
    @DateTimeFormat(value = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime birthday;

    /**
     * 指定字符串转为指定数字
     */
    @StringToIntegerConverterAnnotation(converterEnums = {StringToIntegerConverterEnum.CHINESE_NO,StringToIntegerConverterEnum.CHINESE_YES})
    @ExcelProperty(value = "是否党员",converter = CustomStringToIntegerConverter.class)
    private Integer partyMemberFlag;

    /**
     * NumberFormat 常用
     * “0”——表示一位数值,如没有,显示0。如“0000.0000”,整数位或小数位>4,按实际输出,<4整数位前面补0小数位后面补0,凑足4位。
     * “#”:无小数,小数部分四舍五入。
     * “.#”:整数部分不变,一位小数,四舍五入。
     * “.##”:整数部分不变,二位小数,四舍五入。
     * “.”——表示小数点。
     */
    @ExportAppendStringAnnotation(beginPositionContent = "TA", endPositionContent = "CM")
    @ExcelProperty(value = "身高",converter = CustomExportAppendStringConverter.class)
    @NumberFormat(value = ".#########")
    private String stature;

    /**
     * excel 匹配时忽略该字段
     */
    @ExcelIgnore
    @ExcelProperty(value = "爱好")
    private String showFlag;

}

指定字符串转指定数字枚举类
package com.husky.easyexcle.enums;

/**
 * @Author husky
 * @Date 2022/3/15 13:23
 * @Description: 指定字符串转指定数字枚举类
 **/
public enum StringToIntegerConverterEnum {

    /**
     * 中文是
     */
    CHINESE_YES("是",1,"中文是"),

    /**
     * 中文否
     */
    CHINESE_NO("否",2,"中文否"),

    /**
     * 小写英文是
     */
    LOWERCASE_ENGLISH_YES("yes",2,"小写英文是"),

    /**
     * 小写英文否
     */
    LOWERCASE_ENGLISH_NO("no",2,"小写英文否"),
    ;

    /**
     * 带转换的字符串
     */
    private String key;

    /**
     * 带转换的字符串
     */
    private Integer value;

    /**
     * 备注,便于阅读
     */
    private String remark;

    /**
     * 私有构造,防止被外部调用
     * @param key 带转换的字符串
     * @param value 字符串转换的数字
     * @param remark 备注,便于阅读
     */
    private StringToIntegerConverterEnum(String key, int value,String remark){
        this.key=key;
        this.value=value;
        this.remark = remark;
    }

    /**
     * 获取键[带转换的字符串]
     * @return
     */
    public String getKey(){
        return this.key;
    }

    /**
     * 获取值[字符串转换的数字]
     * @return
     */
    public int getValue(){
        return this.value;
    }
}

字符串转布尔注解

字符串 转布尔 注解,用于easyExcel。与 CustomStringToBooleanConverter 连用

package com.husky.easyexcle.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @Author husky
 * @Date 2022/3/15 11:25
 * @Description: 字符串 转布尔 注解,用于easyExcel。与 CustomStringToBooleanConverter 连用
 **/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface StringToBooleanConverterAnnotation {

    /**
     * 为true时的字符串
     * @return
     */
    public String trueStr();

    /**
     * 为false时的字符串
     * @return
     */
    public String falseStr();
}

指定字符串转指定数字注解

指定字符串转指定数字注解,用于easyExcel。与 CustomStringToIntegerConverter 连用

package com.husky.easyexcle.annotation;

import com.husky.easyexcle.enums.StringToIntegerConverterEnum;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @Author husky
 * @Date 2022/3/15 13:34
 * @Description: 指定字符串转指定数字注解,用于easyExcel。与 CustomStringToIntegerConverter 连用
 **/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface StringToIntegerConverterAnnotation {

    /**
     * 带转换枚举
     * @return
     */
    public StringToIntegerConverterEnum[] converterEnums();
}

导出时追加指定字符串注解
package com.husky.easyexcle.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @Author husky
 * @Date 2022/3/16 16:43
 * @Description: 导出时追加指定字符串
 **/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ExportAppendStringAnnotation {

    /**
     * 开始位置追加内容
     * @return
     */
    public String beginPositionContent() default "";

    /**
     * 结束位置追加内容
     * @return
     */
    public String endPositionContent() default "";


}

自定义字符串转布尔值转换器
package com.husky.easyexcle.converter;

import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.converters.WriteConverterContext;
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 com.husky.easyexcle.annotation.StringToBooleanConverterAnnotation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ObjectUtils;

/**
 * @Author husky
 * @Date 2022/3/15 10:52
 * @Description: 自定义字符串转布尔值转换器
 **/
@Slf4j
public class CustomStringToBooleanConverter  implements Converter<Boolean> {
    @Override
    public Class<?> supportJavaTypeKey() {
        return String.class;
    }

    @Override
    public CellDataTypeEnum supportExcelTypeKey() {
        return CellDataTypeEnum.STRING;
    }

    /**
     * 这里是读的时候会调用
     *
     * @return
     */
    @Override
    public Boolean convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
        // 默认返回false
        boolean result = false;
        try{

            //获取属性上 StringToBooleanConverterAnnotation 注解
            StringToBooleanConverterAnnotation annotation = contentProperty.getField().getAnnotation(StringToBooleanConverterAnnotation.class);

            //判断该注解是否存在
            if(annotation != null){

                //获取Excle读取到的字符串类型的值
                String stringValue = cellData.getStringValue();

                //Excle读取到值真实有效
                if(!ObjectUtils.isEmpty(stringValue)){

                    //判断注解为true时的字符串 是否与 Excle读取到值相同
                    boolean srtFlag = annotation.trueStr().equals(stringValue);
                    if(srtFlag){

                        //相同返回true
                        result = true;
                    }
                }
            }else{
                log.error("使用自定义字符串转布尔值转换器,缺少配套注解@StringToBooleanConverterAnnotation");
            }
        }catch (Exception e){
            log.error("使用自定义字符串转布尔值转换器,获取属性反射异常。Exception={}",e);
        }
        return result;
    }

    /**
     * 这里是写的时候会调用
     * @return
     */
    @Override
    public WriteCellData<?> convertToExcelData(WriteConverterContext<Boolean> context) {

        // 默认返回空字符串
        String result = "";
        try {
            //获取属性上 StringToBooleanConverterAnnotation 注解
            StringToBooleanConverterAnnotation annotation = context.getContentProperty().getField().getAnnotation(StringToBooleanConverterAnnotation.class);

            //判断该注解是否存在
            if(annotation != null){

                //读取待写入的布尔值
                boolean booleanValue = context.getValue();
                if(booleanValue){

                    // 将为true时的字符串反写到Excel
                    result = annotation.trueStr();
                }else{

                    // 将为false时的字符串反写到Excel
                    result = annotation.falseStr();
                }
            }else{
                log.error("写入时使用自定义字符串转布尔值转换器,缺少配套注解@StringToBooleanConverterAnnotation");
            }

        }catch (Exception e){
            log.error("将数据写入Excle出现异常。Exception={}",e);
        }
        return new WriteCellData<>(result);
    }
}

自定义指定字符串转指定数字转换器
package com.husky.easyexcle.converter;

import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.converters.WriteConverterContext;
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 com.husky.easyexcle.annotation.StringToIntegerConverterAnnotation;
import com.husky.easyexcle.enums.StringToIntegerConverterEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ObjectUtils;

/**
 * @Author husky
 * @Date 2022/3/15 10:52
 * @Description: 自定义指定字符串转指定数字转换器
 **/
@Slf4j
public class CustomStringToIntegerConverter implements Converter<Integer> {
    @Override
    public Class<?> supportJavaTypeKey() {
        return String.class;
    }

    @Override
    public CellDataTypeEnum supportExcelTypeKey() {
        return CellDataTypeEnum.STRING;
    }

    /**
     * 这里是读的时候会调用
     *
     * @return
     */
    @Override
    public Integer convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
        // 默认返回 0
        Integer result = 0;
        try{
            StringToIntegerConverterAnnotation annotation = contentProperty.getField().getAnnotation(StringToIntegerConverterAnnotation.class);
            if(annotation != null){
                //获取Excel中读取的数据
                String stringValue = cellData.getStringValue();

                //获取的String类型数据不为空
                if(!ObjectUtils.isEmpty(stringValue)){

                    //获取属性上的注解中传递的枚举值
                    StringToIntegerConverterEnum[] stringToIntegerConverterEnums = annotation.converterEnums();

                    //判断注解中枚举值真实存在
                    if(stringToIntegerConverterEnums != null){

                        //遍历注解中传递的枚举值
                        for(StringToIntegerConverterEnum stice:stringToIntegerConverterEnums){

                            //如果 Excel中读取的数据 与 传递的枚举中数据匹配
                            boolean intFlag = stice.getKey().equals(stringValue);
                            if(intFlag){

                                //返回值为枚举值配置的返回数字
                                result = stice.getValue();
                            }
                        }
                    }
                }
            }else{
                log.error("使用自定义字符串转数字转换器,缺少配套注解@StringToIntegerConverterAnnotation");
            }
        }catch (Exception e){
            log.error("使用自定义字符串转数字转换器,获取属性反射异常。Exception={}",e);
        }
        return result;
    }

    /**
     * 这里是写的时候会调用
     * @return
     */
    @Override
    public WriteCellData<?> convertToExcelData(WriteConverterContext<Integer> context) {

        String result = "";
        try{
            StringToIntegerConverterAnnotation annotation = context.getContentProperty().getField().getAnnotation(StringToIntegerConverterAnnotation.class);
            if(annotation != null){
                //获取带写入Excel中数据
                int intValue = context.getValue();

                //获取的String类型数据不为空
                if(!ObjectUtils.isEmpty(intValue)){

                    //获取属性上的注解中传递的枚举值
                    StringToIntegerConverterEnum[] stringToIntegerConverterEnums = annotation.converterEnums();

                    //判断注解中枚举值真实存在
                    if(stringToIntegerConverterEnums != null){

                        //强烈建议!!!枚举值不要重复,如果重复则取最后一个
                        //遍历注解中传递的枚举值
                        for(StringToIntegerConverterEnum stice:stringToIntegerConverterEnums){

                            //如果 Excel中读取的数据 与 传递的枚举中数据匹配
                            boolean intFlag = stice.getValue() == intValue;
                            if(intFlag){

                                //返回值为枚举中配置的key
                                result = stice.getKey();
                            }
                        }
                    }
                }
            }else{
                log.error("使用自定义字符串转数字转换器,缺少配套注解@StringToIntegerConverterAnnotation");
            }
        }catch (Exception e){
            log.error("使用自定义字符串转数字转换器,获取属性反射异常。Exception={}",e);
        }
        return new WriteCellData<>(result);
    }
}

自定义导出时追加字符串转换器
package com.husky.easyexcle.converter;

import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.converters.WriteConverterContext;
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 com.husky.easyexcle.annotation.ExportAppendStringAnnotation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

/**
 * @Author husky
 * @Date 2022/3/16 16:36
 * @Description: 自定义导出时追加字符串转换器
 * 注意: 此注解不可以写在 BigDecimal 类型的属性上
 **/
@Slf4j
public class CustomExportAppendStringConverter implements Converter<String> {

    @Override
    public Class<?> supportJavaTypeKey() {
        return String.class;
    }

    @Override
    public CellDataTypeEnum supportExcelTypeKey() {
        return CellDataTypeEnum.STRING;
    }
    /**
     * 这里是读的时候会调用
     *
     * @return
     */
    @Override
    public String convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
        return cellData.getStringValue();
    }


    /**
     * 这里是写的时候会调用
     * @return
     */
    @Override
    public WriteCellData<?> convertToExcelData(WriteConverterContext<String> context) {

        String result = "";
        try{
            ExportAppendStringAnnotation annotation = context.getContentProperty().getField().getAnnotation(ExportAppendStringAnnotation.class);
            if(annotation != null){
                //获取带写入Excel中数据 并且将格式强转为字符串
                // String value = context.getValue();
                String value = context.getValue()+"";

                //获取的String类型数据不为空
                if(StringUtils.hasLength(value)){
                    result = value;
                    // 如果开始位置追加内容不为空
                    if(!ObjectUtils.isEmpty(annotation.beginPositionContent())){
                        result = annotation.beginPositionContent()+result;
                    }

                    // 如果结束位置追加内容不为空
                    if(!ObjectUtils.isEmpty(annotation.endPositionContent())){
                        result = result+annotation.endPositionContent();
                    }
                }
            }else{
                log.error("导出时追加指定字符串,缺少配套注解@ExportAppendStringAnnotation");
            }
        }catch (Exception e){
            log.error("自定义导出时追加字符串转换器,获取属性反射异常。Exception={}",e);
        }
        return new WriteCellData<>(result);
    }
}

导入文件读取Excel

Excel相关控制层
package com.husky.easyexcle;

import com.husky.easyexcle.entity.ExcelDateEntity;
import com.husky.easyexcle.service.ExcelService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.List;

/**
 * @Author husky
 * @Date 2022/3/22 15:58
 * @Description: Excel相关控制层
 **/

@RestController
@Slf4j
public class ExcelController {

    @Autowired
    private ExcelService excelServiceImpl;
    /**
     * 读取上传Excel数据
     * @param file
     * @return
     * @throws IOException
     */
    @PostMapping("read/excel/data")
    public String readExcelData(MultipartFile file) throws IOException {
        log.info("读取上传Excel开始。file={}",file);
      try {
          List<ExcelDateEntity> list = excelServiceImpl.readExcelData(file);
          log.info("list={}",list);
          return "SUCCESS";
      }catch (Exception e){
          log.error("读取上传Excel异常。Exception={}",e);
          return "FAIL";
      }

    }

}

Excelweb相关业务接口
package com.husky.easyexcle.service;

import com.husky.easyexcle.entity.ExcelDateEntity;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;

/**
 * @Author husky
 * @Date 2022/3/22 16:08
 * @Description: Excelweb相关业务接口
 **/
public interface ExcelService {

    /**
     * 读取上传Excel数据
     * @param file
     * @return
     */
    List<ExcelDateEntity> readExcelData(MultipartFile file);
}

Excelweb相关业务接口实现类
package com.husky.easyexcle.service.impl;

import com.husky.easyexcle.entity.ExcelDateEntity;
import com.husky.easyexcle.service.ExcelService;
import com.husky.easyexcle.utils.ExcleUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;

/**
 * @Author husky
 * @Date 2022/3/22 16:09
 * @Description: Excelweb相关业务实现类
 **/
@Slf4j
@Service
public class ExcelSerivceImpl implements ExcelService {

    /**
     * 读取上传Excel数据
     * @param file
     * @return
     */
    @Override
    public List<ExcelDateEntity> readExcelData(MultipartFile file) {
        return ExcleUtil.readWebExcelData(file, ExcelDateEntity.class);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值