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

使用场景

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

扫描二维码关注公众号,回复: 11879508 查看本文章

是否需要纵向合并单元格(用于含有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拖动一个单元格大小进行检查。
在这里插入图片描述

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标签,点击标签弹出进行下载。
在这里插入图片描述
在这里插入图片描述

$.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 () {
    
    
            });
        }
    }
});

导出效果

在这里插入图片描述

导入实战

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

导入的基础跟导出一样都是需要对应
在这里插入图片描述

/**
 * 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。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/moshowgame/article/details/109024214