EasyPoi 下拉以及样式导入导出实战

本文详细介绍了如何使用EasyPoi进行Excel的导入导出,包括注解配置、数据验证、样式定制等。重点讲解了EasyPoi的@Excel注解,以及在数据验证中遇到的问题和解决方案,如replace参数的使用,以及版本升级后修复的bug。此外,还展示了自定义样式类以改变导出Excel的样式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

技术选型

查找资料简单搜索github上的excel项目,找到四个候选者:

  1. apache poi
  2. alibaba EasyExcel
  3. hutool Excel工具集
  4. 悟耘信息 EasyPoi

apache poi

这几个工具底层都是apache poi。它很强大很灵活,灵活的东西都很复杂,业务不需要这么专业的工具。所以排除

alibaba EasyExcel

这是阿里开源的excel工具,对大数据量优化良好,可以基于注解导入导出,注解功能性不如EasyPoi多。业务数据量不大,所以大可不必。

hutool Excel工具集

hutool的工具做导入导出也很简单,就是不基于注解注解,我不喜欢。

EasyPoi

最终选择EasyPoi,好用的注解,丰富的配置,注解配置即生成下拉,非常契合业务需求。但是也有坑。版本4.3.0.

EasyPoi实战

@Excel注解

文档很详细。
http://doc.wupaas.com/docs/easypoi/easypoi-1c0u96flii98v

    @Excel(name = "是否语音" ,orderNum = "140",width = 15 ,replace = {"否_false","是_true"},addressList = true)
    private Boolean speech;

下拉

replace = {"判断连续_1","判断次数_2","不做判断_3"},addressList = true

这两个参数就够了,数据库里的1导出为判断连续,判断连续导入为1.

replace里下拉选项可以通过反射动态生成。

replace坑

曾用的3.0.1版本的poi,如果excel不按照replace里面配置的填,导入时方法importExcel直接报错,都不给你数据验证的机会,直接是一个空指针。

好在高版本修复了,如果不按照replace配置的来,此字段给你一个null值,然后就可以自己验证了。
在这里插入图片描述

导出

ExportParams是一个配置类,里面有哪些配置可以看看。

ExportParams exportParams = new ExportParams();
        exportParams.setTitle(fileName);
        exportParams.setSheetName("generalRule_List");
        exportParams.setType(ExcelType.XSSF);
        exportParams.setStyle(MyExcelStyleUtil.class);
        try {
            Workbook workbook = ExcelExportUtil.exportExcel(exportParams, BasicRuleTileExcel.class, basicRuleTileExcels);
            response.setCharacterEncoding("UTF-8");
            response.setHeader("Content-Type", "application/vnd.ms-excel");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8") + ".xlsx");
            workbook.write(response.getOutputStream());
        } catch (Exception e) {
            log.error("导出异常:", e);
            throw new AlarmException("文件导出异常");
        }

导入

        ImportParams importParams = new ImportParams();
        importParams.setTitleRows(1);
        importParams.setHeadRows(1);
        // 开启验证
        importParams.setNeedVerify(true);
        importParams.setVerifyHandler(ruleExcelVerifyHandler);
        List<BasicRuleTileExcel> read = Lists.newArrayList();
        ExcelImportResult<BasicRuleTileExcel> readMore = new ExcelImportResult<>();
        try {
            readMore = ExcelImportUtil.importExcelMore(file.getInputStream(), BasicRuleTileExcel.class, importParams);
            read = readMore.getList();
        } catch (Exception e) {
            throw new AlarmException("excel读取错误,请检查下拉框和数据格式合法性");
        }

ExcelImportUtil里有importExcelMore和importExcel方法。
importExcel返回的就是importExcelMore里的list,

@Data
public class ExcelImportResult<T> {

    /**
     * 结果集
     */
    private List<T>  list;
    /**
     * 失败数据
     */
    private List<T>  failList;

    /**
     * 是否存在校验失败
     */
    private boolean  verifyFail;

    /**
     * 数据源
     */
    private Workbook workbook;
    /**
     * 失败的数据源
     */
    private Workbook failWorkbook;

    private Map<String,Object> map;

    public ExcelImportResult() {

    }

    public ExcelImportResult(List<T> list, boolean verifyFail, Workbook workbook) {
        this.list = list;
        this.verifyFail = verifyFail;
        this.workbook = workbook;
    }

}

failList是验证错误的列表。

数据验证

开启验证,导入参数传入验证类。

// 开启验证
importParams.setNeedVerify(true);
importParams.setVerifyHandler(ruleExcelVerifyHandler);

验证类得实现IExcelVerifyHandler

@Slf4j
@Component
public class RuleExcelVerifyHandler implements IExcelVerifyHandler<BasicRuleTileExcel> {
        if (obj.getFinishMethod()==2){
            if (ObjectUtil.isEmpty(obj.getFinishTerm()) || ObjectUtil.isEmpty(obj.getFinishTermUnit()) || ObjectUtil.isEmpty(obj.getFinishTimes2())){
                saveError(obj.getCode(), "累计时长,累计时长单位累计次数缺一不可");
                return handlerFail();
            }
            if (!("s".equals(obj.getFinishTermUnit()) || "m".equals(obj.getFinishTermUnit()) ||"h".equals(obj.getFinishTermUnit()))){
                saveError(obj.getCode(), "累计时长单位填写[s,m,h]中的一个");
                return handlerFail();
            }
        }

        return handlerSuccess();
    }

    private ExcelVerifyHandlerResult handlerFail() {
        ExcelVerifyHandlerResult result = new ExcelVerifyHandlerResult();
        result.setSuccess(false);
        result.setMsg("校验不通过");
        return result;
    }

    private ExcelVerifyHandlerResult handlerSuccess() {
        ExcelVerifyHandlerResult result = new ExcelVerifyHandlerResult();
        result.setSuccess(true);
        result.setMsg("通过");
        return result;
    }
}

obj是excel表的一行记录,每一次验证返回ExcelVerifyHandlerResult对象

@Data
public class ExcelVerifyHandlerResult {
    /**
     * 是否正确
     */
    private boolean success;
    /**
     * 错误信息
     */
    private String  msg;

    public ExcelVerifyHandlerResult() {

    }

    public ExcelVerifyHandlerResult(boolean success) {
        this.success = success;
    }

    public ExcelVerifyHandlerResult(boolean success, String msg) {
        this.success = success;
        this.msg = msg;
    }

}

ExcelVerifyHandlerResult对象的success=false,则验证失败,此行数据存入ExcelImportResult.failList.
ExcelVerifyHandlerResult.msg是失败信息。

样式

导出参数设置样式类

exportParams.setStyle(MyExcelStyleUtil.class);

首先,它默认有个样式类ExcelExportStylerDefaultImpl,所以可以仿照它继承AbstractExcelExportStyler,实现IExcelExportStyler。

也可以偷懒直接继承ExcelExportStylerDefaultImpl,修改对应地方。

public class ExcelExportStylerDefaultImpl extends AbstractExcelExportStyler
                                          implements IExcelExportStyler {

    public ExcelExportStylerDefaultImpl(Workbook workbook) {
        super.createStyles(workbook);
    }

    @Override
    public CellStyle getTitleStyle(short color) {
        CellStyle titleStyle = workbook.createCellStyle();
        titleStyle.setAlignment(HorizontalAlignment.CENTER);
        titleStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        titleStyle.setWrapText(true);
        return titleStyle;
    }

    @Override
    public CellStyle stringSeptailStyle(Workbook workbook, boolean isWarp) {
        CellStyle style = workbook.createCellStyle();
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        style.setDataFormat(STRING_FORMAT);
        if (isWarp) {
            style.setWrapText(true);
        }
        return style;
    }

    @Override
    public CellStyle getHeaderStyle(short color) {
        CellStyle titleStyle = workbook.createCellStyle();
        Font font = workbook.createFont();
        font.setFontHeightInPoints((short) 12);
        titleStyle.setFont(font);
        titleStyle.setAlignment(HorizontalAlignment.CENTER);
        titleStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        return titleStyle;
    }

    @Override
    public CellStyle stringNoneStyle(Workbook workbook, boolean isWarp) {
        CellStyle style = workbook.createCellStyle();
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        style.setDataFormat(STRING_FORMAT);
        if (isWarp) {
            style.setWrapText(true);
        }
        return style;
    }

}

重写这些方法,至于样式代码具体怎么写,就不研究了。我这里只重写了表头样式。

public class MyExcelStyleUtil extends ExcelExportStylerDefaultImpl {


    public MyExcelStyleUtil(Workbook workbook) {
        super(workbook);
    }

    @Override
    public CellStyle getTitleStyle(short color) {
        CellStyle titleStyle = workbook.createCellStyle();
        titleStyle.setAlignment(HorizontalAlignment.CENTER);
        titleStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        titleStyle.setWrapText(true);
        
        Font font = this.workbook.createFont();
        font.setBold(true);//字体加粗
        titleStyle.setFillForegroundColor(IndexedColors.AQUA.getIndex());//背景色
        titleStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        return titleStyle;
    }

}

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值