# 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-准备工作
#### 工程结构

#### 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
```
#### 数据库脚本

```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 进行调用该接口

- 打开excel文件

### 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

- 查询数据库表中的数据
