欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

SpringBoot+EasyPOI实现快速excel导入导出

程序员文章站 2022-03-15 19:32:25
...

使用场景

SpringBoot可以快速使用EasyPOI进行便捷的导入导出,这里是一份简单的教程,包含导入导出部分。

EasyPoi的主要特点

  1. 设计精巧,使用简单
  2. 接口丰富,扩展简单
  3. 默认值多,write less do more
  4. AbstractView 支持,web导出可以简单明了

官方gitee:https://gitee.com/lemur/easypoi

什么场景该用哪个方法

  • 导出
    1. 正规excel导出 (格式简单,数据量可以,5W以内吧)
      注解方式: ExcelExportUtil.exportExcel(ExportParams entity, Class<?> pojoClass,Collection<?> dataSet)
    2. 不定多少列,但是格式依然简单数据库不大
      自定义方式: ExcelExportUtil.exportExcel(ExportParams entity, List entityList,Collection<?> dataSet)
    3. 数据量大超过5W,还在100W以内
      注解方式 ExcelExportUtil.exportBigExcel(ExportParams entity, Class<?> pojoClass,IExcelExportServer server, Object queryParams)
      自定义方式: ExcelExportUtil.exportBigExcel(ExportParams entity, List excelParams,IExcelExportServer server, Object queryParams)
    4. 样式复杂,数据量尽量别大
      模板导出 ExcelExportUtil.exportExcel(TemplateExportParams params, Map<String, Object> map)
    5. 一次导出多个风格不一致的sheet
      模板导出 ExcelExportUtil.exportExcel(Map<Integer, Map<String, Object>> map,TemplateExportParams params)
    6. 一个模板但是要导出非常多份
      模板导出 ExcelExportUtil.exportExcelClone(Map<Integer, List<Map<String, Object>>> map,TemplateExportParams params)
    7. 模板无法满足你的自定义,试试html
      自己构造html,然后我给你转成excel ExcelXorHtmlUtil.htmlToExcel(String html, ExcelType type)
    8. 数据量过百万级了.放弃excel吧,csv导出
      注解方式: CsvExportUtil.exportCsv(CsvExportParams params, Class<?> pojoClass, OutputStream outputStream)
      自定义方式: CsvExportUtil.exportCsv(CsvExportParams params, List entityList, OutputStream outputStream)
      9. word导出
      模板导出: WordExportUtil.exportWord07(String url, Map<String, Object> map)
      10. PDF导出
      模板导出: TODO
    • 导入
      如果想提高性能 ImportParams 的concurrentTask 可以帮助并发导入,仅单行,最小1000
      excel有单个的那种特殊读取,readSingleCell 参数可以支持
      1. 不需要检验,数据量不大(5W以内)
        注解或者MAP: ExcelImportUtil.importExcel(File file, Class<?> pojoClass, ImportParams params)
      2. 需要导入,数据量不大
        注解或者MAP: ExcelImportUtil.importExcelMore(InputStream inputstream, Class<?> pojoClass, ImportParams params)
      3. 数据量大了,或者你有特别多的导入操作,内存比较少,仅支持单行
        SAX方式 ExcelImportUtil.importExcelBySax(InputStream inputstream, Class<?> pojoClass, ImportParams params, IReadHandler handler)
      4. 数据量超过EXCEL限制,CSV读取
        小数据量: CsvImportUtil.importCsv(InputStream inputstream, Class<?> pojoClass,CsvImportParams params)
        大数据量: CsvImportUtil.importCsv(InputStream inputstream, Class<?> pojoClass,CsvImportParams params, IReadHandler readHandler)

关于Excel导出XLS和XLSX区别

  1. 导出时间XLS比XLSX快2-3倍
  2. 导出大小XLS是XLSX的2-3倍或者更多
  3. 导出需要综合网速和本地速度做考虑~

几个工程的说明

  1. easypoi 父包–作用大家都懂得
  2. easypoi-annotation 基础注解包,作用与实体对象上,拆分后方便maven多工程的依赖管理
  3. easypoi-base 导入导出的工具包,可以完成Excel导出,导入,Word的导出,Excel的导出功能
  4. easypoi-web 耦合了spring-mvc 基于AbstractView,极大的简化spring-mvc下的导出功能
  5. sax 导入使用xercesImpl这个包(这个包可能造成奇怪的问题哈),word导出使用poi-scratchpad,都作为可选包了

maven

maven库直接导入即可,最新版本4.2.0 ,用新不用旧,可以在 https://mvnrepository.com/search?q=EasyPOI 检查一下是否是最新版本。

 <dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-spring-boot-starter</artifactId>
    <version>4.2.0</version>
</dependency>
 <dependency>
	<groupId>cn.afterturn</groupId>
	<artifactId>easypoi-base</artifactId>
	<version>4.2.0</version>
</dependency>
<dependency>
	<groupId>cn.afterturn</groupId>
	<artifactId>easypoi-web</artifactId>
	<version>4.2.0</version>
</dependency>
<dependency>
	<groupId>cn.afterturn</groupId>
	<artifactId>easypoi-annotation</artifactId>
	<version>4.2.0</version>
</dependency>

Annotation注解解析

@Excel

重点关注即可,这个是必须使用的注解,如果需求简单只使用这一个注解也是可以的,涵盖了常用的Excel需求,需要大家熟悉这个功能,附上属性详解。

属性 类型 默认值 功能

name

String

null

列名,支持name_id

needMerge

boolean

fasle

是否需要纵向合并单元格(用于含有list中,单个的单元格,合并list创建的多个row)

orderNum

String

"0"

列的排序,支持name_id

replace

String[]

{}

值得替换导出是{a_id,b_id} 导入反过来

savePath

String

"upload"

导入文件保存路径,如果是图片可以填写,默认是upload/className/ IconEntity这个类对应的就是upload/Icon/

type

int

1

导出类型 1 是文本 2 是图片,3 是函数,10 是数字 默认是文本

width

double

10

列宽

height

double

10

列高,后期打算统一使用@ExcelTarget的height,这个会被废弃,注意

isStatistics

boolean

fasle

自动统计数据,在追加一行统计,把所有数据都和输出这个处理会吞没异常,请注意这一点

isHyperlink

boolean

false

超链接,如果是需要实现接口返回对象

isImportField

boolean

true

校验字段,看看这个字段是不是导入的Excel中有,如果没有说明是错误的Excel,读取失败,支持name_id

exportFormat

String

""

导出的时间格式,以这个是否为空来判断是否需要格式化日期

importFormat

String

""

导入的时间格式,以这个是否为空来判断是否需要格式化日期

format

String

""

时间格式,相当于同时设置了exportFormat 和 importFormat

databaseFormat

String

"yyyyMMddHHmmss"

导出时间设置,如果字段是Date类型则不需要设置 数据库如果是string 类型,这个需要设置这个数据库格式,用以转换时间格式输出

numFormat

String

""

数字格式化,参数是Pattern,使用的对象是DecimalFormat

imageType

int

1

导出类型 1 从file读取 2 是从数据库中读取 默认是文件 同样导入也是一样的

suffix

String

""

文字后缀,如% 90 变成90%

isWrap

boolean

true

是否换行 即支持\n

mergeRely

int[]

{}

合并单元格依赖关系,比如第二列合并是基于第一列 则{0}就可以了

mergeVertical

boolean

fasle

纵向合并内容相同的单元格

fixedIndex

int

-1

对应excel的列,忽略名字

isColumnHidden

boolean

false

导出隐藏列

@ExcelTarget

限定一个到处实体的注解,以及一些通用设置,作用于最外面的实体

@ExcelEntity

标记是不是导出excel 标记为实体类,一遍是一个内部属性类,标记是否继续穿透,可以自定义内部id

@ExcelCollection

一对多的集合注解,用以标记集合是否被数据以及集合的整体排序


DEMO

在实战之前请看一份的DEMO代码,寻找灵感。

  • 无需处理的例如id信息。
  • 需要处理的普通字段信息,带必须判断,否则报错。
  • 前缀后缀 suffix/prefix
  • 需要处理的是/否,男/女等简单判断信息。
  • 需要处理的日期格式。
 @Data
 public class User implements java.io.Serializable {
    /**
     * id(不处理,无需id)
     */
    private String        id;
    /**
     * 姓名(必须)
     */
    @Excel(name = "姓名", width = 30, isImportField = "true_st")
    private String        name;
    /**
     * 性别
     */
    @Excel(name = "性别", replace = { "男_1", "女_2" }, suffix = "人", isImportField = "true_st")
    private int           gender;

    @Excel(name = "创建时间", databaseFormat = "yyyy年MM月dd日 HH:mm:ss", format = "yyyy-MM-dd", isImportField = "true_st", width = 20)
    private Date          createTime;


 }

导出实战

以下内容来自真实项目并做DEMO化处理。

实体类

isImportField = "true_st" 表示导入必须字段。
width ,具体什么是合适的宽度,这个可以自己在excel拖动一个单元格大小进行检查。
SpringBoot+EasyPOI实现快速excel导入导出

import cn.afterturn.easypoi.excel.annotation.Excel;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;

import java.io.Serializable;
import java.util.Date;

/**
 * @description 个人证书
 * @author zhengkai.blog.csdn.net
 * @date 2020-07-29
 */
@Data
public class CertPerson implements Serializable {

    private static final long serialVersionUID = 1L;

    @TableId(type = IdType.AUTO)
    /**
     * id
     */
    private Integer certId;

    /**
     * 证书
     */
    @Excel(name = "证书编码", width = 30 ,isImportField = "true_st")
    private String certNumber;

    /**
     * 姓名
     */
    @Excel(name = "姓名", width = 10 ,isImportField = "true_st")
    private String certName;

    /**
     * 身份证号码
     */
    @Excel(name = "证件号", width = 30 ,isImportField = "true_st")
    private String personId;

    /**
     * 颁发日期
     */
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "GMT+8")
    @Excel(name = "发证时间", databaseFormat = "yyyy年MM月dd日", format = "yyyy-MM-dd", isImportField = "true_st", width = 20)
    private Date certValidateStart;

    /**
     * 认证课程
     */
    @Excel(name = "课程名称", width = 60,isImportField = "true_st")
    private String certLesson;

    /**
     * 工作单位
     */
    @Excel(name = "单位", width = 60,isImportField = "true_st")
    private String certCompany;

    /**
     * 备注
     */
    @Excel(name = "备注", width = 20)
    private String certText;

    public CertPerson() {
    }

}

Controller方面

  • storageService.getPathString()为项目用到的封装方法,获取要项目保存文件的目录供上传和下载使用。
  • ReturnT为返回封装方法,根据自己项目修改
  • 查询所需导出数据后使用ExcelExportUtil.exportExcel进行Workbook生成
  • 使用FilreOutputSteam写入Workbook对象到FilePath具体路径
/**
 * excel导出
 * by zhengkai.blog.csdn.net
 */
@PostMapping("/export")
public ReturnT export(){
    QueryWrapper<CertPerson> queryWrapper = new QueryWrapper<CertPerson>();
    queryWrapper.orderByDesc("cert_validate_start");
    List<CertPerson> pageList = certPersonMapper.selectList(queryWrapper);
    Workbook workbook = ExcelExportUtil.exportExcel(
            new ExportParams("证书查询系统","个人证书"),CertPerson.class, pageList);
    try {
        FileOutputStream fos = new FileOutputStream(storageService.getPathString()+"person_download.xls");
        workbook.write(fos);
        fos.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return ReturnT.SUCCESS("person_download.xls");
}

UI交互方面

点击后台进行生成,生成后插入新的a标签,点击标签弹出进行下载。
SpringBoot+EasyPOI实现快速excel导入导出
SpringBoot+EasyPOI实现快速excel导入导出

$.ajax({
    type: 'POST',
    url: '${request.contextPath}/certPerson/export?token='+layui.data('token').token,
    data:result,
    dataType: "json",
    contentType: "application/json",
    success: function (responseData) {
        if (responseData.code === 200) {
            $("#exportArea").html('<a href="${request.contextPath}/file/files/'+responseData.msg+'"><i class="layui-icon layui-icon-download-circle"></i>点击下载excel</a>');
            $("#exportArea").attr("class","layui-btn layui-btn-normal layui-btn-sm data-export-btn");
        } else {
            layer.msg(responseData.msg, function () {
            });
        }
    }
});

导出效果

SpringBoot+EasyPOI实现快速excel导入导出

导入实战

为了方便测试,我们省略了上传环节,直接复制刚才生成的person_download.xls到person_upload.xls作为用户上传后的文件,后台直接读取该文件实现解析。

导入的基础跟导出一样都是需要对应
SpringBoot+EasyPOI实现快速excel导入导出

/**
 * excel导入
 * by zhengkai.blog.csdn.net
 */
@PostMapping("/import")
 public ReturnT importExcel(){
     ImportParams params = new ImportParams();
     params.setTitleRows(1);
     params.setHeadRows(1);
     long start = new Date().getTime();
     List<CertPerson> list = ExcelImportUtil.importExcel(
             new File(storageService.getPathString()+"person_upload.xls"),
             CertPerson.class, params);
     //输出导入信息到控制台,执行导入业务
     log.info(JSON.toJSONString(list));
     //省略导入业务,根据自身项目需要进行调整
     return ReturnT.SUCCESS("person_cert_export.xls");
 }

检查输出的内容,控制台会把所有数据打印成json。
SpringBoot+EasyPOI实现快速excel导入导出