# easyexcel **Repository Path**: lidengpan/easyexcel ## Basic Information - **Project Name**: easyexcel - **Description**: easyexcel入门案例 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 3 - **Forks**: 5 - **Created**: 2021-03-01 - **Last Updated**: 2025-07-28 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 关于EasyExcel的使用说明v1.0 ## EasyExcel介绍 ### 1-概念: ​ EasyExcel是一个基于Java的简单、省内存的读写Excel的开源项目。在尽可能节约内存的情况下支持读写百M的Exce。 ​ EasyExcel是快速、简单避免OOM的java处理Excel工具。 官网地址:https://www.yuque.com/easyexcel/doc/easyexcel ### 2-Excel工具介绍 ​ Java解析、生成Excel比较有名的框架有Apache poi、jxl和EasyExcel。但Apache poi和jxl他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定程度的解决一些内存溢出的问题,但POI还是有一些缺陷,比如07版Excel解压缩以及解压后存储都是在内存中完成的,内存消耗依然很大。easyexcel重写了poi对07版Excel的解析,能够原本一个3M的excel用POI sax依然需要100M左右内存降低到KB级别,并且再大的excel不会出现内存溢出,03版依赖POI的sax模式。在上层做了模型转换的封装,让使用者更加简单方便 ### 3-EasyExcel核心功能 - 读任意大小的03、07版Excel不会OOM - 读Excel自动通过注解,把结果映射为java模型 - 读Excel支持多sheet - 读Excel时候是否对Excel内容做trim()增加容错 - 写小量数据的03版Excel(不要超过2000行) - 写任意大07版Excel不会OOM - 写Excel通过注解讲表头自动写入Excel - 写Excel可以自定义Excel样式 如:字体,加粗,表头颜色,数据内容颜色 - 写Excel到多个不同sheet - 写Excel时一个sheet可以写多个Table - 写Excel时候自定义是否需要写表头 ### 4-EasyExcel常用api介绍 常用API访问地址:https://www.yuque.com/easyexcel/doc/api ## EasyExcel入门 ​ 本案例是基于SpringBoot+EasyExcel来实现excel文档的上传(导入)和下载(导出)功能 ### 0-准备工作 #### 工程结构 ![输入图片说明](https://images.gitee.com/uploads/images/2021/0301/182826_e91b95ee_1447154.png "1614587853350.png") #### pom.xml依赖坐标 ```xml 4.0.0 org.example springboot-easyexcel 1.0-SNAPSHOT 8 8 org.springframework.boot spring-boot-starter-parent 2.3.2.RELEASE org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-test com.alibaba easyexcel 2.2.6 org.apache.poi poi 3.17 org.apache.poi poi-ooxml 3.17 org.mybatis.spring.boot mybatis-spring-boot-starter 1.3.1 mysql mysql-connector-java 5.1.6 org.projectlombok lombok 1.18.12 ``` #### 数据库脚本 ![输入图片说明](https://images.gitee.com/uploads/images/2021/0301/182859_3d579af5_1447154.png "1614584655915.png") ```sql /* Navicat MySQL Data Transfer Source Server : localhost_3306 Source Server Version : 50540 Source Host : localhost:3306 Source Database : db_easyexcel Target Server Type : MYSQL Target Server Version : 50540 File Encoding : 65001 Date: 2021-03-01 15:43:02 */ SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for tb_user -- ---------------------------- DROP TABLE IF EXISTS `tb_user`; CREATE TABLE `tb_user` ( `id` varchar(255) COLLATE utf8_bin NOT NULL, `name` varchar(255) COLLATE utf8_bin DEFAULT NULL, `age` int(4) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; -- ---------------------------- -- Records of tb_user -- ---------------------------- INSERT INTO `tb_user` VALUES ('0005', '猪悟能', '12'); INSERT INTO `tb_user` VALUES ('0006', '唐僧', '13'); INSERT INTO `tb_user` VALUES ('0007', '沙悟净', '14'); INSERT INTO `tb_user` VALUES ('0008', '孙悟空', '15'); ``` #### application.yml文件 ```yml server: port: 8080 spring: datasource: url: jdbc:mysql://127.0.0.1:3306/db_easyexcel?useUnicode=true&zeroDateTimeBehavior=convertToNull&autoReconnect=true&characterEncoding=utf-8 driver-class-name: com.mysql.jdbc.Driver username: root password: root ``` #### pojo对象实体 ```java package com.itheima.easyexcel.pojo; import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.metadata.BaseRowModel; import lombok.Data; /** * 实体类 */ @Data public class TbUser { @ExcelProperty(value = "ID",index = 0) public String id; @ExcelProperty(value = "姓名",index = 1) public String name; @ExcelProperty(value = "年龄",index = 2) public Integer age; } ``` > @ExcelProperty注解参考常用API ### 1-写Excel操作 #### 需求分析: ​ 从数据库中提取全部数据,然后以流的方式导入(写入)到excel中,最终在浏览上下载生成后缀为xls的excel文件 #### mapper接口 ```java package com.itheima.easyexcel.mapper; import com.itheima.easyexcel.pojo.TbUser; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Select; import java.util.List; public interface UserMapper { //查询 @Select("select * from tb_user") public List findAll(); } ``` #### service接口及实现类 ```java //接口 public interface IUserService{ //导出 public void excelExport(HttpServletResponse response) throws IOException; } //实现类 @Service public class UserServiceImpl implements IUserService { @Autowired private UserMapper userMapper; //写操作 @Override public void excelExport(HttpServletResponse response) throws IOException { //1.获取数据库表中的所有数据 List userList = userMapper.findAll(); //2.定义导出文件名称 String fileName="用户名单"; //3.设置响应对象 response.setContentType("application/vnd.ms-excel;charset=utf-8"); response.setCharacterEncoding("utf-8"); response.setHeader("Content-disposition","attachment;filename="+new String(fileName.getBytes("gb2312"),"ISO8859-1")+".xls"); //4.输出流和写入流 ServletOutputStream out = response.getOutputStream(); //写流,指定具体执行的class类 ExcelWriter excelWriter = EasyExcel.write(out, TbUser.class).build(); //设置sheet WriteSheet writeSheet=EasyExcel.writerSheet("sheet1").build(); //执行写的过程 excelWriter.write(userList,writeSheet); //写流完成,会自动关闭流 excelWriter.finish(); } ``` #### controller类 ```java @RestController @RequestMapping("/api/user") public class UserController { @Autowired public IUserService iUserService; //导出excel文件,下载文件 @GetMapping("/excelExport") public void excelExport(HttpServletResponse response) throws Exception { //调接口 iUserService.excelExport(response); } } ``` #### 测试 - 启动工程 - 在浏览器上输入请求地址: http://localhost:8080/api/user/excelExport 进行调用该接口 ![输入图片说明](https://images.gitee.com/uploads/images/2021/0301/182923_68e4bcf3_1447154.png "1614588436782.png") - 打开excel文件 ![输入图片说明](https://images.gitee.com/uploads/images/2021/0301/182935_24c60020_1447154.png "1614588483721.png") ### 2-读Excel操作 #### 需求分析: ​ 以文件流的方式,读取excel文件中的数据,然后把数据提取出来,存储到数据库表中 #### mapper接口 ```java public interface UserMapper { //新增 @Insert("insert into tb_user(id,name,age)values(#{id},#{name},#{age})") public void save(TbUser tbUser); } ``` #### ExcelListener监听类 ps:该监听类,不可以交给spring来管理,必须使用new的方式管理 ```java public class ExcelListener extends AnalysisEventListener { //空的集合 private List datas = new ArrayList<>(); //存储数据库的条数界限 private static final int BATCH_COUNT = 3000; //mapper接口 private UserMapper userDao; public ExcelListener(UserMapper userDao){ this.userDao = userDao; } //默认初始化执行 @Override public void invoke(TbUser user, AnalysisContext analysisContext) { //数据存储到datas,供批量处理,或后续自己业务逻辑处理。 datas.add(user); //达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM if(datas.size() >= BATCH_COUNT){ saveData(); // 存储完成清理datas datas.clear(); } } private void saveData() { for(TbUser user : datas){ userDao.save(user); } } public List getDatas() { return datas; } public void setDatas(List datas) { this.datas = datas; } /** * 所有数据解析完成了 都会来调用 */ @Override public void doAfterAllAnalysed(AnalysisContext analysisContext) { saveData();//确保所有数据都能入库 } } ``` #### service接口及实现类 ```java //接口 public interface IUserService{ //导入 public void excelImport(MultipartFile file) throws Exception; } //实现类 @Service public class UserServiceImpl implements IUserService { @Autowired private UserMapper userMapper; //导出文件 @Override public void excelImport(MultipartFile file) throws Exception { if(!file.getOriginalFilename().equals("用户名单.xls") && !file.getOriginalFilename().equals("用户名单.xlsx") ){ return; } InputStream inputStream = new BufferedInputStream(file.getInputStream()); //实例化实现了AnalysisEventListener接口的类 ExcelListener excelListener = new ExcelListener(userMapper); //设置读取数据的工具类 ExcelReader excelReader = EasyExcel.read(inputStream, TbUser.class, excelListener).build(); //设置读取的sheet ReadSheet readSheet = EasyExcel.readSheet(0).build(); //执行读过程 excelReader.read(readSheet); //读流完成,会自动关闭流 excelReader.finish(); } } ``` #### controller类 ```java @RestController @RequestMapping("/api/user") public class UserController { @Autowired public IUserService iUserService; //导入文件,上传 @PostMapping("/excelImport") public String excelImport(MultipartFile file) throws Exception { iUserService.excelImport(file); return "导入成功"; } } ``` #### 测试 - 启动工程 - 在postman中进行测试,请求地址 http://localhost:8080/api/user/excelImport ![输入图片说明](https://images.gitee.com/uploads/images/2021/0301/182952_d83166e6_1447154.png "1614589174126.png") - 查询数据库表中的数据 ![输入图片说明](https://images.gitee.com/uploads/images/2021/0301/183002_ced57612_1447154.png "1614589212841.png")