一、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的使用:

4.1、操作流程:

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

4.1.1、添加依赖:

        <!-- easyexcel 依赖 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.2.7</version>
</dependency>

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, List<? extends 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<String> 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<BasicDemo> list = operateMapper.selectAllDemo(requestVO);
//转换
List<ExportExcelVO> 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语句:

    <select id="selectAllDemo" resultMap="BaseResultMap" parameterType="java.lang.String">
select
<include refid="Base_Column_List"/>
from page_demo
where 1=1
<if test="id neq null and id != ''">
AND uuid = #{id}
</if>
<if test="ids != null and ids.size()!=0">
AND uuid in
<foreach collection="ids" item="item" index="index" open="(" separator=","
close=")">
#{item}
</foreach>
</if>
</select>

6、导出样本:

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 <T>
* @return
*/
public static <T> List<T> importExcel(MultipartFile multipartFile, Class<T> clazz) throws Exception {
List<T> list = new ArrayList<>();
InputStream inputStream = multipartFile.getInputStream(); EasyExcel.read(inputStream, clazz, new AnalysisEventListener<T>() {
//每解析一行就会调用一次,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<List<ImportExcelVO>> importExcel(@RequestParam(value = "file") MultipartFile file) {
List<ImportExcelVO> list = operateService.importData(file);
return Response.success(list);
}

2、业务类:

    /**
* 导入模板下载
*/
@Override
public void importTemplate(HttpServletResponse response) {
List<ImportExcelVO> 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<ImportExcelVO> importData(MultipartFile file) {
List<ImportExcelVO> 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; }

五、参考:

参考

5、基于EasyExcel的导入导出的更多相关文章

  1. 使用Layui、Axios、Springboot(Java) 实现EasyExcel的导入导出(浏览器下载)

    实现EasyExcel的导入导出(浏览器下载) 实现三个按钮的功能,但是却花费了一天的时间包括总结. 使用到的技术:springboot layui axios EasyExcel mybatis-p ...

  2. 使用VUE+SpringBoot+EasyExcel 整合导入导出数据

    使用VUE+SpringBoot+EasyExcel 整合导入导出数据 创建一个普通的maven项目即可 项目目录结构 1 前端 存放在resources/static 下 index.html &l ...

  3. PowerDesigner数据库设计PDM基于Excel的导入导出总结

    经常用到pdm来管理代码,一两张表,手写一下还凑合,一旦表多了,就慌了.于是,开始学习用vbs进行Excel的来快速导入导出操作PDM就变得很紧急了,搜罗了网络上的很多vbs脚本,各有各的优点,但对于 ...

  4. easyExcel用于导入导出

    1.添加依赖: <!-- 现在已经更新到1.1.2-beta5 --> <dependency> <groupId>com.alibaba</groupId& ...

  5. Java实现导入导出Excel:POI和EasyExcel

    文章与CSDN同步,欢迎访问:https://blog.csdn.net/qq_40280582/article/details/107300081 代码地址:https://gitee.com/il ...

  6. SpringCloud微服务实战——搭建企业级开发框架(三十):整合EasyExcel实现数据表格导入导出功能

      批量上传数据导入.数据统计分析导出,已经基本是系统必不可缺的一项功能,这里从性能和易用性方面考虑,集成EasyExcel.EasyExcel是一个基于Java的简单.省内存的读写Excel的开源项 ...

  7. Excel基于POI导入导出的Annotation化之路(一)

    Excel在web项目里的使用变得越来越广泛,特别是和线下耦合度较高的业务,Excel导入导出变得非常频繁,尽管很多人写了诸多的工具方法,但是终究没有解决一个问题:有效的控制字段英文名称和实际表头名称 ...

  8. C#中缓存的使用 ajax请求基于restFul的WebApi(post、get、delete、put) 让 .NET 更方便的导入导出 Excel .net core api +swagger(一个简单的入门demo 使用codefirst+mysql) C# 位运算详解 c# 交错数组 c# 数组协变 C# 添加Excel表单控件(Form Controls) C#串口通信程序

    C#中缓存的使用   缓存的概念及优缺点在这里就不多做介绍,主要介绍一下使用的方法. 1.在ASP.NET中页面缓存的使用方法简单,只需要在aspx页的顶部加上一句声明即可:  <%@ Outp ...

  9. Java基于注解和反射导入导出Excel

    代码地址如下:http://www.demodashi.com/demo/11995.html 1. 构建项目 使用Spring Boot快速构建一个Web工程,并导入与操作Excel相关的POI包以 ...

随机推荐

  1. Go实现优雅关机与平滑重启

    前言 优雅关机就是服务端关机命令发出后不是立即关机,而是等待当前还在处理的请求全部处理完毕后再退出程序,是一种对客户端友好的关机方式.而执行Ctrl+C关闭服务端时,会强制结束进程导致正在访问的请求出 ...

  2. P8548 小挖的买花 方法记录

    原题链接 小挖的买花 题目背景 小挖喜欢买花,但是 ta 太懒了!所以这个任务全权交给了你. 题目描述 花店里只有 \(n\) 株花,每一株花都有三个属性:价格 \(cost_i\).美丽度 \(be ...

  3. Vue3解决ElementPlus Drawer或弹出对话框不生效的问题

    第一时间检查你是否还在使用 :visible.sync="drawer" 来绑定事件框的隐藏和显示,vue3.0 已经更改为通过 v-model 来绑定事件框的显示与隐藏.

  4. day48-JDBC和连接池04

    JDBC和连接池04 10.数据库连接池 10.1传统连接弊端分析 传统获取Connection问题分析 传统的 JDBC 数据库连接使用DriverManager来获取,每次向数据库建立连接的时候都 ...

  5. git-secret:在 Git 存储库中加密和存储密钥(下)

    在之前的文章中(点击此处查看上一篇文章),我们了解了如何识别包含密钥的文件,将密钥添加到 .gitignore ,通过 git-secret 进行加密,以及将加密文件提交到存储库.在本篇文章中,将带你 ...

  6. LcdTools如何导出内置画面为bmp图片

    运行LcdTools,先设置好图片所需分辨率参数,点击"画面设置"栏,修改下图所示参数 点击"画面设置"栏,在"画面资源"栏找到需要导出的画 ...

  7. 9_Vue事件修饰符

    概述 首先需要理解下什么是事件修饰符 常用事件修饰符 案例1_阻止默认行为发生 我这里有一个a标签 这个标签呢我会给它配置一个点击事件 点击事件输出一句话,那么效果是这样的 代码 <body&g ...

  8. 驱动开发:内核监控FileObject文件回调

    本篇文章与上一篇文章<驱动开发:内核注册并监控对象回调>所使用的方式是一样的都是使用ObRegisterCallbacks注册回调事件,只不过上一篇博文中LyShark将回调结构体OB_O ...

  9. CSS 动画一站式指南

    CSS 动画一站式指南 目录 CSS 动画一站式指南 1. CSS 动画 1.1 变换 1.1.1 变换属性介绍 1.1.2 变换动画实践 1.2 过渡 1.2.1 过渡属性介绍 1.2.2 过渡动画 ...

  10. day09-Tomcat01

    Tomcat01 1.WEB开发介绍 WEB,在英文中WEB表示网/网络资源,它用于表示WEB服务器(主机)供浏览器访问的资源 WEB服务器(主机)上供外界访问的Web资源为: 静态web资源(如ht ...