近期使用EasyPOI实现了excel表格存入数据库的功能,下面介绍一下使用过程和遇到的难点。 

目录

1、背景介绍

2、使用过程及注意点

1、引入依赖

2、编写实体类

3、可以开始尝试上传了

4、尝试导出

3、结语

1、背景介绍

        我的项目是使用ruoyi脚手架搭建的SpringBoot项目,希望实现固定格式excle的上传功能,并且存入数据库,以及从数据库中再导出的功能。这是表格样式以及为其设计的数据表。

SpringBoot集成easypoi springboot easypoi_上传

SpringBoot集成easypoi springboot easypoi_SpringBoot集成easypoi_02

        可以看到,表格样式有固定的一行标题,表头既有两行合并,也有单独一行。这类情况按照以往经验使用Apache POI可以完成,但比较麻烦,所有选择更为简单的EasyPOI。

2、使用过程及注意点

1、引入依赖

在pom.xml文件添加依赖 

<dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-base</artifactId>
    <version>4.1.2</version>
</dependency>
<dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-web</artifactId>
    <version>4.1.2</version>
</dependency>
<dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-annotation</artifactId>
    <version>4.1.2</version>
</dependency>

或者是

<dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-spring-boot-starter</artifactId>
    <version>4.1.2</version>
</dependency>

哪个可以用就用哪个,注意版本号要一致。

        注意点1:easypoi是本身只是对poi的封装,所以引入他的jar包可以会跟其他的包产生冲突,导致项目启动失败,或是接下的错误。所有要解决jar包依赖冲突。我是使用idea的maven heler插件,可显示依赖结构,,处理依赖冲突很方便。

2、编写实体类

        这里需要用到@Excel注解,当然还有其他注解比如@ExcelCollection,@ExcelEntity ,@ExcelIgnore,@ExcelTarget等,我们现在用不到。

        在@Excel注解中,我用到了name(列名)、groupName(组名)、orderNum(列的排序)、fixedIndex(对应excel的列,忽略名字)。

        name对应列名,比较直观,groupName对应合并项的组名,凡是有合并项的都要添加(同时之后表头列数是2,之后会讲到),orderNum可有可无影响不大。值得一提的是这个fixedIndex。因为我的的表头有合并项,刚开始只加了orderNum,只能读到合并列中的第一列。查了很多博客都没有效果,之后才知道需要fixedIndex来固定一下绝对位置。原理不清楚。

        这几个注解要与自己的excel表对应,还有许多其他属性可以参考官网。完成这步是实现导入导出的关键,需要多次尝试。

@Data
@TableName("h_account")
public class HAccount extends Model<HAccount> {

    private static final long serialVersionUID = 1L;
    
    @TableId(value = "id", type = IdType.AUTO)
    @Excel(name = "序号")
    private int id;

    @TableField("`name`")
    @Excel(name = "名称",groupName = "重大应用",orderNum = "1")
    private String name;

    @TableField("req_name")
    @Excel(name = "需求名称",groupName = "重大需求",orderNum = "2",fixedIndex = 2)
    private String reqName;

    @TableField("req_type")
    @Excel(name = "需求类型",groupName = "重大需求",orderNum = "3",fixedIndex = 3)
    private String reqType;

    @TableField("req_content")
    @Excel(name = "需求内容",groupName = "重大需求",orderNum = "4",fixedIndex = 4)
    private String reqContent;

    @TableField("scene_framework")
    @Excel(name = "基本架构",groupName = "多跨场景",orderNum = "5",fixedIndex = 5)
    private String sceneFramework;

    @TableField("scene_sub")
    @Excel(name = "小切口子场景",groupName = "多跨场景",orderNum = "6",fixedIndex = 6)
    private String sceneSub;

    @TableField("reform_project")
    @Excel(name = "改革项目",groupName = "重大改革",orderNum = "7",fixedIndex = 7)
    private String reformProject;

    @TableField("reform_task")
    @Excel(name = "改革任务",groupName = "重大改革",orderNum = "8",fixedIndex = 8)
    private String reformTask;

    @TableField("departments")
    @Excel(name = "责任单位",orderNum = "9",fixedIndex = 9)
    private String departments;

    @TableField("remark")
    @Excel(name = "备注",orderNum = "10")
    private String remark;
}

3、可以开始尝试上传了

在Controller里编写方法,通过几个easypoi的方法就可以实现读取,这就是他的easy之处。

        首先注意的是引包,因为easypoi是封装的,所以会有重名,所以注意包的正确。再接着注意读取表头的设置,要与自己的表格对应上。

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;

public List<HAccount> upload(@RequestParam("file") MultipartFile multipartFile,
) throws Exception {
    //new一个模板
    ImportParams params = new ImportParams();
    //设置表格标题行数,默认0,这是读取时会跳过的行数
    params.setTitleRows(1);
    //表头行数,默认1。上午提到,如果有合并的列名,就要设置读取表头的行数
    params.setHeadRows(2);
    //开始读取,并用list接收,方便处理
    List<HAccount> result = ExcelImportUtil.importExcel(multipartFile.getInputStream(), HAccount.class, params);
    System.out.println(JSONUtil.toJsonStr(result));
    return result;
}

        通过这样就可以在控制台上看到json格式的上传结果了。再使用for each等方法对其处理,实现自己需要的功能。例如我要实现写入数据库。

SpringBoot集成easypoi springboot easypoi_SpringBoot集成easypoi_03

4、尝试导出

        在上传完成后,数据库已经有了,接下试试导出。

        由于我们在实体类中给每个对象都加了@Excel注解,导出就变得十分简单,不用再用代码设计表格样式,直接导出就会显示原先的样式。

用两种办法接收文件,一是下载到本地的目录下,

public void export1(List<HAccount> result,String title) {
//  输出到本地地址
        try {
            ExportParams params = new ExportParams(title, "sheet1", ExcelType.XSSF);
            Workbook workbook = ExcelExportUtil.exportExcel(params, HAccount.class, result);
           File saveFile = new File("excel");
           if (!saveFile.exists()) {
                saveFile.mkdirs();
            }
            //地址
            FileOutputStream fos = new FileOutputStream("C:/Users/Desktop/55/9.xlsx");
            workbook.write(fos);
            fos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

二是传给浏览器处理。

public int export( @RequestBody List<HAccount> result,
                @RequestParam HttpServletResponse response){
    //生成输出模板
    ExportParams params = new ExportParams(title, "sheet1", ExcelType.XSSF);
    Workbook workbook = ExcelExportUtil.exportExcel(params, HAccount.class, result);
    if(workbook==null){
        return 0;
    }
    // 重置响应对象
    response.reset();
    // 当前日期,用于导出文件名称
    SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
    String dateStr = sdf.format(new Date());
    // 指定下载的文件名--设置响应头
        //设置输出的文件名
    response.setHeader("Content-Disposition", "attachment;filename=" +dateStr+".xlsx");
    response.setContentType("application/vnd.ms-excel;charset=UTF-8");
    response.setHeader("Pragma", "no-cache");
    response.setHeader("Cache-Control", "no-cache");
    response.setDateHeader("Expires", 0);
    // 写出数据输出流到页面
    try {
        OutputStream output = response.getOutputStream();
        BufferedOutputStream bufferedOutPut = new BufferedOutputStream(output);
        workbook.write(bufferedOutPut);
        bufferedOutPut.flush();
        bufferedOutPut.close();
        output.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return 1;
}

通过以上方法的调用就可以生成与原先格式相同的excel表格。

3、结语

        笔者在使用easypoi的过程遇到一些问题,网络上虽然有很多教学的博客,但由于每个人需要处理的表格都不相同,所有问题一直没能有效解决。最关键的就是@Excel注解的使用,里面的许多属性不太直观,需要反复尝试。希望以上的问答能够解决你的问题,同时也欢迎在评论区留言互动。