5、基于EasyExcel的导入导出

一、Apach POI处理Excel的方式:

传统Excel操作或者解析都是利用Apach POI进行操作,POI中处理Excel有以下几种方式:

1、HSSFWorkbook:

HSSFWorkbook用来处理.xls后缀的Excel,即适用于Excel2003以前(包括2003)的版本。因为其最大只能处理65535行的数据,所以现在已经很少使用了

2、XSSFWorkbook:

XSSFWorkbook是现在处理Excel比较常见的方式。其适用于.xlsx后缀的Excel,即Excel2007后的版本。能够最多处理104万行数据。但是其在读取/处理Excel时会一口气将Excel内容写入到内存,因此在处理的Excel文件较大时可能打爆内存,造成OOM异常(内存溢出)。

3、SXSSFWorkbook:

SXSSFWorkbook相当于是XSSFWorkbook的改良版本,在初始化SXSSFWorkbook实例时,需要填写一个缓冲行数参数(默认100行),当读入到内存中的数据超过该数值后,会像队列一样将最前面的数据保存到硬盘中,从而避免出现OOM。这么一看该方式简直完美啊,不过因为超过缓存行的数据都写到硬盘中了,所以如果你想要获取这块的内容(比如复制这块内容到另一个Excel中)就会发现取不到了,因为不在内存中,所以无法通过SXSSFWorkbook实例获取该部分内容。

二、Apach POI框架的不足:

1、使用步骤繁琐;

2、动态写出Excel操作非常麻烦;

3、对于新手来说,很难在短时间内上手;

4、读写时需要占用较大的内容,当数据量大时容器发生OOM;

基于上述原因,阿里开源出一款易上手,且比较节省内存的Excel操作框架:EasyExcel

三、Apach POI、EasyPoi与EasyExcel的区别:

1、POI 优点在于自由,但是迎来的就是复杂度,和大数据量时候性能的缺点

2、EasyPoi基于POI 的二次封装,解决了大部分的常用场景,简化了代码,但是特别复杂表格处理还是不行,而且性能的话和poi差不多,简单来说就是简化了Poi的操作,少些点代码,总体来说,easypoi和easyexcel都是基于apache poi进行二次开发的。

3、easypoi和easyexcel的不同点在于:

(1)、easypoi 在读写数据的时候,优先是先将数据写入内存,优点是读写性能非常高,但是当数据量很大的时候,会出现oom,当然它也提供了 sax 模式的读写方式,需要调用特定的方法实现。

(2)、easyexcel 基于sax模式进行读写数据,不会出现oom情况,程序有过高并发场景的验证,因此程序运行比较稳定,相对于 easypoi 来说,读写性能稍慢!

(3)、easypoi 与 easyexcel 还有一点区别在于,easypoi 对定制化的导出支持非常的丰富,如果当前的项目需求,并发量不大、数据量也不大,但是需要导出 excel 的文件样式千差万别,那么我推荐你用 easypoi;反之,使用 easyexcel !

四、EasyExcel的使用:

5、基于EasyExcel的导入导出

4.1、操作流程:

建工程——》改POM——》写YML——》业务类

4.1.1、添加依赖:

com.alibaba
            easyexcel
            2.2.7

4.1.2、写YML:

server:
  port: 8081

spring:
  application:
    name: demo    #项目名
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource    #当前数据源操作类型
    driver-class-name: org.gjt.mm.mysql.Driver    #mysql驱动包
    url: jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: 123456
    druid:
      test-while-idle: false  #关闭空闲检测

mybatis:
  mapperLocations: classpath:mapper/*.xml    #resource目录下建mapper包,存放xml文件

4.2、EasyExcel的导出操作(单个与批量导出):

4.2.1、通用导出工具类ExportUtil:

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;

import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.util.List;

@Slf4j
public class ExportUtil {
    /**
     * 导出 Excel
     *
     * @param response  :响应
     * @param data      :导出的list集合
     * @param fileName  :Excel名(最好英文,无需后缀)
     * @param sheetName :sheet页名
     * @param clazz     :导出Excel实体类
     * @throws Exception
     */
    public static void writeExcel(HttpServletResponse response, Listextends Object> data, String fileName, String sheetName, Class clazz) throws Exception {
        //表头样式
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        //设置表头居中对齐
        headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        //内容样式
        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
        //设置内容靠左对齐
        contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.LEFT);
        HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);

        EasyExcel.write(getOutputStream(fileName, response), clazz)
                .excelType(ExcelTypeEnum.XLSX)//读取的文件类型
                .sheet(sheetName)//读取的sheet,可以是行号也可以是sheet名
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())//设置自动适应宽度
                .registerWriteHandler(horizontalCellStyleStrategy)//设置样式(或:registerWriteHandler(createStyleStrategy))
                .doWrite(data);
    }

    /**
     * 格式处理
     */
    private static OutputStream getOutputStream(String fileName, HttpServletResponse response) throws Exception {
        response.setContentType("application/vnd.ms-excel;charset=utf-8");
        response.setCharacterEncoding("utf8");
        response.addHeader("Content-disposition", "attachment;filename=" + fileName + ExcelTypeEnum.XLSX.getValue());
        return response.getOutputStream();
    }

    /**
     * 自定义样式
     */
    private static HorizontalCellStyleStrategy createStyleStrategy() {
        // 头的策略
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        // 背景设置为红色
        headWriteCellStyle.setFillForegroundColor(IndexedColors.LIGHT_CORNFLOWER_BLUE.getIndex());
        WriteFont headWriteFont = new WriteFont();
        headWriteFont.setFontHeightInPoints((short) 10);
        headWriteCellStyle.setWriteFont(headWriteFont);
        // 内容的策略
        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
        contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);  //底边框
        contentWriteCellStyle.setBorderLeft(BorderStyle.THIN);  //左边框
        contentWriteCellStyle.setBorderRight(BorderStyle.THIN);  //右边框
        contentWriteCellStyle.setBorderTop(BorderStyle.THIN);  //顶边框
        WriteFont contentWriteFont = new WriteFont();
        // 字体大小
        contentWriteFont.setFontHeightInPoints((short) 10);
        contentWriteCellStyle.setWriteFont(contentWriteFont);
        // 执行策略
        HorizontalCellStyleStrategy horizontalCellStyleStrategy =
                new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);

        return horizontalCellStyleStrategy;
    }
}

4.2.2、业务流程:

1、请求体:

import lombok.Data;

import java.util.List;

@Data
public class RequestVO {
    private String id;
    private List ids;
    private Boolean way;
}

2、控制类:

/**
     * 导出
     * 1、单个导出
     * 2、批量导出
     *
     * http://localhost:8081/v1/export-data
     * {
     *     "id":"xxx",
     *     "ids":["xxx","xxx"],
     *     "way":false
     * }
     * */
    @PostMapping("/export-data")
    public void exportList(
            @RequestBody RequestVO requestVO,
            HttpServletResponse response) {
        //导出方式:单个/批量
        if(true == requestVO.getWay()){
            requestVO.setId(null);
        }
        operateService.exportData(requestVO,response);
    }

3、业务类:

@Autowired
    private OperateMapper operateMapper;

    /**
     * 导出操作
     */
    @Override
    public void exportData(RequestVO requestVO, HttpServletResponse response) {
        //mysql查询
        List list = operateMapper.selectAllDemo(requestVO);
        //转换
        List exportList = new ArrayList<>();
        Optional.ofNullable(list).ifPresent(po -> {
            po.stream().forEach(p -> {
                ExportExcelVO exportExcelVO = ExportExcelVO.builder()
                        .uuid(p.getUuid())
                        .name(p.getName())
                        .status(p.getStatus())
                        .startTime(p.getStartTime())
                        .build();
                exportList.add(exportExcelVO);
            });
        });

        //导出
        try {
            writeExcel(response, exportList, "result", "表名", ExportExcelVO.class);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("错误信息Exception:", e);
        }
        log.info("执行完毕,导出成功");
    }

4、导出实体类:

import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.ContentRowHeight;
import com.alibaba.excel.annotation.write.style.HeadRowHeight;
import lombok.Builder;
import lombok.Data;

import java.io.Serializable;

@HeadRowHeight(value = 35) // 设置表头行高
@ContentRowHeight(value = 25) // 设置内容行高
//@ColumnWidth(value = 50) // 设置列宽
@Data
@Builder
public class ExportExcelVO implements Serializable {

    @ExcelProperty(value = {"编号"},order = 1)
    private String uuid;

    @ExcelProperty(value = {"基本信息","详情","名字"},order = 2)
    private String name;

    @ExcelProperty(value = {"基本信息","详情","状态"},order = 3)
    private String status;

    @ExcelProperty(value = {"基本信息","操作时间","时间"},order = 4)
    @DateTimeFormat("yyyy-MM-dd")   //时间格式
    private String startTime;

}

5、SQL语句:

    

6、导出样本:

5、基于EasyExcel的导入导出

4.3、EasyExcel的导入操作(模板下载与数据导入):

4.3.1、通用导入工具类ImportUtil:

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

@Slf4j
public class ImportUtil {
    /**
     * 导入 Excel
     *
     * @param multipartFile excel文件
     * @param clazz         数据类型的class对象
     * @param
     * @return
     */
    public static  List importExcel(MultipartFile multipartFile, Class clazz) throws Exception {
        List list = new ArrayList<>();
        InputStream inputStream = multipartFile.getInputStream();

        EasyExcel.read(inputStream, clazz, new AnalysisEventListener() {
            //每解析一行就会调用一次,data数据表示解析出来一行的数据
            @Override
            public void invoke(T data, AnalysisContext context) {
                list.add(data);
            }

            //当全部数据读取完成后调用该方法
            @Override
            public void doAfterAllAnalysed(AnalysisContext context) {
                log.info("解析完成");
            }
        }).sheet().doRead();
        return list;
    }
}

4.3.2、业务流程:

1、控制类:

@Autowired
    private OperateService operateService;

    /**
     * 导入模板下载
     * http://localhost:8081/v1/download
     * */
    @GetMapping("/download")
    public void downloadTemplate(HttpServletResponse response) {
        operateService.importTemplate(response);
    }

    /**
     * 导入
     * http://localhost:8081/v1/import-data
     */
    @PostMapping(value="/import-data")
    public Response> importExcel(@RequestParam(value = "file") MultipartFile file)  {
        List list = operateService.importData(file);
        return Response.success(list);
    }

2、业务类:

/**
     * 导入模板下载
     */
    @Override
    public void importTemplate(HttpServletResponse response) {
        List importExcelVO = new ArrayList<>();
        try {
            //相当导出 Excel操作
            writeExcel(response, importExcelVO, "importTemplate", "表名", ImportExcelVO.class);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("错误信息Exception:", e);
        }
        log.info("执行完毕,导出成功");
    }

    /**
     * 导入操作
     */
    @Override
    public List importData(MultipartFile file) {
        List list = new ArrayList<>();
        try {
            //获取数据
            list = importExcel(file, ImportExcelVO.class);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //数据操作:
        for (ImportExcelVO importExcelVO :
                list) {
            log.info("输出:" + importExcelVO);
        }
        return list;
    }

4、导入实体类:

@HeadRowHeight(value = 35) // 设置表头行高
@ContentRowHeight(value = 25) // 设置内容行高
//@ColumnWidth(value = 50) // 设置列宽
@Data
public class ImportExcelVO implements Serializable {

    @ExcelProperty(value = {"编号"},order = 1)
    private String uuid;

    @ExcelProperty(value = {"基本信息","详情","名字"},order = 2)
    private String name;

    @ExcelProperty(value = {"基本信息","详情","状态"},order = 3)
    private String status;

    @ExcelProperty(value = {"基本信息","操作时间","时间"},order = 4)
    @DateTimeFormat("yyyy-MM-dd")   //时间格式
    private String startTime;

}

五、参考:

参考

Original: https://www.cnblogs.com/Iven-L/p/16560278.html
Author: 爱文(Iven)
Title: 5、基于EasyExcel的导入导出

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/575717/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 第17章 触发器

    第17章 触发器 在实际开发中,我们经常会遇到这样的情况:有 2 个或者多个相互关联的表,如 &#x5546;&#x54C1;&#x4FE1;&#x…

    数据库 2023年6月6日
    0122
  • MySQL高可用安装

    MySQL HA部署 环境准备 创建本地yum源 确认关闭 SELinux 防火墙设置 MySQL安装 使用 root 用户操作创建相关的用户组和用户 上传/解压介质 设置自启动 …

    数据库 2023年5月24日
    0104
  • MySQL45讲之InnoDB刷脏策略

    本文介绍 InnoDB 的刷脏控制策略,它是如何控制刷脏速率的,以及一些相关参数。 了解 MySQL 的刷脏策略有什么意义? 当一条正确的 SQL 执行时偶尔延迟较高,无法复现场景…

    数据库 2023年5月24日
    074
  • Java8Stream流2

    上期对stream流大致总结了一下,后面又做了一些练习,大家可以参考一下。 首先需要建一个 Product的实体类,后面会用到 @Data @AllArgsConstructor …

    数据库 2023年6月11日
    079
  • jdbc-实现用户登录业务(存在sql注入)

    package com.cqust; import java.sql.Connection;import java.sql.DriverManager;import java.sq…

    数据库 2023年5月24日
    080
  • openpyxl使用总结

    设置表头单元格的颜色 fill = PatternFill("solid", fgColor=’FF000000′) font = Font(color=’00…

    数据库 2023年6月9日
    081
  • mybatis order by concat用法

    由于项目中用到了一个关联查询,关联的表中都有id字段,在排序时,使用${id},获取值时,一直报 Column ‘id’ in order clause i…

    数据库 2023年6月11日
    079
  • 计算机组成原理——计算篇

    计算机组成原理 —— 计算篇 进制运算的基础 定义: 常用的进制 为什么计算机经常使用 8 进制 &16 进制 1024 不同进制表达方式 二进制运算的基础 正整数N,基数…

    数据库 2023年6月16日
    078
  • 牛客SQL刷题第三趴——SQL大厂面试真题

    结果保留两位小数,并按播放进度倒序排序。 解题思路: 1、播放进度结算 ①、时间差函数,timestampdiff(unit,char(begin-end)) ②、判断,if或者用…

    数据库 2023年6月16日
    072
  • iptables快速入门

    iptables简介 在生产实践过程中,为了保证生产安全,通常需要进行数据加密,例如通过网络层面上将应用隔离成内网和公网应用,内网再分成生产、测试、开发、DMZ等区域,然后进行不同…

    数据库 2023年6月14日
    0102
  • [LeetCode]26. 删除排序数组中的重复项

    给定一个排序数组,你需要在 原地 删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。 不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额…

    数据库 2023年6月9日
    0121
  • 教师节我用Python做了个学生点名系统送给老师当礼物,这回毕业稳了

    今年教师节前夕,我特意用Python做了个学生点名系统,非常好用,送给各科老师、辅导员当节日礼物,老师们都喜滋滋,说平常逃课就原谅我了,我心想,这次毕业应该不是问题了~ 本文背景 …

    数据库 2023年6月14日
    084
  • 多商户商城系统功能拆解22讲-平台端分销商品

    多商户商城系统,也称为B2B2C(BBC)平台电商模式多商家商城系统。可以快速帮助企业搭建类似拼多多/京东/天猫/淘宝的综合商城。 多商户商城系统支持商家入驻加盟,同时满足平台自营…

    数据库 2023年6月14日
    098
  • ArrayList扩容机制

    1.构造函数 有三种 说第一种无参构造,默认初始容量为10 2.add函数 /** * 将指定的元素追加到此列表的末尾。 */ public boolean add(E e) { …

    数据库 2023年6月16日
    091
  • jdbc-使用工具类

    package com.cqust; import com.cqust.utils.JDBCUtil; import java.sql.Connection;import java…

    数据库 2023年6月11日
    067
  • 当我用Python做了个自动工作汇报的脚本后,每天都闲的只能摸鱼

    哈喽兄弟们 之前经常编写Python脚本来进行数据处理、数据传输和模型训练。随着数据量和数据复杂性的增加,运行脚本可能需要一些时间。在等待数据处理完成时可以同时做一些其他工作。 为…

    数据库 2023年6月14日
    074
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球