SpringBoot整合POI实现Excel文件读写操作
1.环境准备
1、导入sql脚本:
create database if not exists springboot default charset utf8mb4;use springboot;create table if not exists `user`
(`id` bigint(20) primary key auto_increment comment '主键id',`username` varchar(255) not null comment '用户名',`sex` char(1) not null comment '性别',`phone` varchar(22) not null comment '手机号',`city` varchar(255) not null comment '所在城市',`position` varchar(255) not null comment '职位',`salary` decimal(18, 2) not null comment '工资:长度18位,保留2位小数'
) engine InnoDB comment '用户表';INSERT INTO `user` (`username`, `sex`, `phone`, `city`, `position`, `salary`) VALUES
('张三', '男', '13912345678', '北京', '软件工程师', 10000.00),
('李四', '女', '13723456789', '上海', '数据分析师', 12000.00),
('王五', '男', '15034567890', '广州', '产品经理', 15000.00),
('赵六', '女', '15145678901', '深圳', '前端工程师', 11000.00),
('刘七', '男', '15856789012', '成都', '测试工程师', 9000.00),
('陈八', '女', '13967890123', '重庆', 'UI设计师', 8000.00),
('朱九', '男', '13778901234', '武汉', '运维工程师', 10000.00),
('杨十', '女', '15089012345', '南京', '数据工程师', 13000.00),
('孙十一', '男', '15190123456', '杭州', '后端工程师', 12000.00),
('周十二', '女', '15801234567', '天津', '产品设计师', 11000.00);

2、创建springboot工程 (springboot版本为2.7.13)
3、引入依赖:
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-test</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.13</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.2</version></dependency>
</dependencies>
4、修改yml配置:
server:port: 8001# 数据库配置
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/springboot?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2b8&allowPublicKeyRetrieval=trueusername: rootpassword: 123456# mybatisplus配置
mybatis-plus:mmapper-locations: classpath:mapper/*.xml #mapper文件存放路径type-aliases-package: cn.z3inc.exceldemo.entity # 类型别名(实体类所在包)configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #配置标准sql输出
5、使用 MyBatisPlus 插件生成基础代码:

① 配置数据库:


② 使用代码生成器生成代码:



2. POI
Excel报表的两种方式:
在企业级应用开发中,Excel报表是一种常见的报表需求,Excel报表开发一般分为两种形式:
-
把Excel中的数据导入到系统中;(上传)
-
通过Java代码生成Excel报表。(下载)
Excel版本:
目前世面上的Excel分为两个大版本:Excel2003 和 Excel2007及以上版本;
Excel2003是一个特有的二进制格式,其核心结构是复合文档类型的结构,存储数据量较小;Excel2007 的核心结构是 XML 类型的结构,采用的是基于 XML 的压缩方式,使其占用的空间更小,操作效率更高。
| Excel 2003 | Excel 2007 | |
|---|---|---|
| 后缀 | xls | xlsx |
| 结构 | 二进制格式,其核心结构是复合文档类型的结构 | XML类型结构 |
| 单sheet数据量(sheet,工作表) | 表格共有65536行,256列 | 表格共有1048576行,16384列 |
| 特点 | 存储容量有限 | 基于xml压缩,占用空间小,操作效率高 |
Apache POI:
Apache POI(全称:Poor Obfuscation Implementation),是Apache软件基金会的一个开源项目,它提供了一组API,可以让Java程序读写 Microsoft Office 格式的文件,包括 word、excel、ppt等。
Apache POI是目前最流行的操作Microsoft Office的API组件,借助POI可以为工作提高效率,如 数据报表生成,数据批量上传,数据备份等工作。
官网地址:https://poi.apache.org/
POI针对Excel的API如下:
- Workbook:工作薄,Excel的文档对象,针对不同的Excel类型分为:HSSFWorkbook(2003)和XSSFWorkbook(2007);
- Sheet:Excel的工作单(表);
- Row:Excel的行;
- Cell:Excel的格子,单元格。
Java中常用的excel报表工具有:POI、easyexcel、easypoi等。
POI快速入门:
引入POI依赖:
<!--excel POI依赖-->
<dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>4.0.1</version>
</dependency>
<dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>4.0.1</version>
</dependency>
<dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml-schemas</artifactId><version>4.0.1</version>
</dependency>
示例1:批量写操作(大数据量时会出现内存异常问题)
写入excel文件步骤:
- 创建工作簿:workbook
- 创建工作表:sheet
- 创建行:row
- 创建列(单元格):cell
- 具体数据写入
package cn.z3inc.exceldemo.controller;import cn.z3inc.exceldemo.entity.User;
import cn.z3inc.exceldemo.service.IUserService;
import lombok.RequiredArgsConstructor;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;/*** <p>* 用户表 前端控制器* </p>** @author 白豆五* @since 2023-10-01*/
@CrossOrigin
@RestController
@RequiredArgsConstructor
@RequestMapping("/user")
public class UserController {private final IUserService userService;/*** 导出excel*/@RequestMapping("/export")public void exportExcel(HttpServletResponse response) throws IOException {// 1. 创建excel工作簿(workbook):excel2003使用HSSF,excel2007使用XSSF,excel2010使用SXSSF(大数据量)XSSFWorkbook workbook = new XSSFWorkbook();// 2. 创建excel工作表(sheet)Sheet sheet = workbook.createSheet("用户表");// 3. 在表中创建标题行(row): 表头Row titleRow = sheet.createRow(0); // 通过索引表示行,0表示第一行// 4. 在标题行中创建7个单元格 且 为每个单元格设置内容数据String[] titleArr = {"用户ID", "姓名", "性别", "电话", "所在城市", "职位", "薪资"};for (int i = 0; i < titleArr.length; i++) {Cell cell = titleRow.createCell(i); //设置单元格的位置,从0开始cell.setCellValue(titleArr[i]); // 为单元格填充数据}// 5. 查询所有用户数据List<User> userList = userService.list();// 6. 遍历用户list,获取每个用户,并填充每一行单元格的数据for (int i = 0; i < userList.size(); i++) {User user = userList.get(i);// 创建excel的行Row row = sheet.createRow(i+1); // 从第二行开始,索引为1// 为每个单元格填充数据row.createCell(0).setCellValue(user.getId());row.createCell(1).setCellValue(user.getUsername());row.createCell(2).setCellValue(user.getSex());row.createCell(3).setCellValue(user.getPhone());row.createCell(4).setCellValue(user.getCity());row.createCell(5).setCellValue(user.getPosition());row.createCell(6).setCellValue(user.getSalary().doubleValue());}// 7. 输出文件// 7.1 把excel文件写到磁盘上FileOutputStream outputStream = new FileOutputStream("d:/1.xlsx");workbook.write(outputStream); // 把excel写到输出流中outputStream.close(); // 关闭流// 7.2 把excel文件输出到浏览器上// 设置响应头信息response.setContentType("application/vnd.ms-excel");response.setHeader("Content-Disposition", "attachment; filename=1.xlsx");ServletOutputStream servletOutputStream = response.getOutputStream();workbook.write(servletOutputStream);servletOutputStream.flush(); // 刷新缓冲区servletOutputStream.close(); // 关闭流workbook.close();}
}

示例2:大数量写操作
/*** 大数据量批量导出excel:SXSSF(同样兼容XSSF)* 官方提供了SXSSF来解决大文件写入问题,它可以写入非常大量的数据,比如上百万条数据,并且写入速度更快,占用内存更少* SXSSF在写入数据时会将数据分批写入硬盘(会产生临时文件),而不是一次性将所有数据写入硬盘。* SXSSF通过滑动窗口限制内存读取的行数(默认100行,超过100行就会写入磁盘),而XSSF将文档中所有行加载到内存中。那些不在滑动窗口中的数据是不能访问的,因为它们已经被写到磁盘上了。这样可以节省大量内存空间 。*/
@RequestMapping("/export2")
public void exportExcel2(HttpServletResponse response) throws IOException {long star = System.currentTimeMillis();// 1. 创建excel工作簿(workbook):SXSSFWorkbookSXSSFWorkbook workbook = new SXSSFWorkbook();//默认窗口大小为100// 2. 创建excel工作表(sheet)Sheet sheet = workbook.createSheet("用户表");// 3. 在表中创建标题行(row): 表头Row titleRow = sheet.createRow(0); // 通过索引表示行,0表示第一行// 4. 在标题行中创建7个单元格 且 为每个单元格设置内容数据String[] titleArr = {"用户ID", "姓名", "性别", "电话", "所在城市", "职位", "薪资"};for (int i = 0; i < titleArr.length; i++) {Cell cell = titleRow.createCell(i); //设置单元格的位置,从0开始cell.setCellValue(titleArr[i]); // 为单元格填充数据}// 5. 查询所有用户数据List<User> userList = userService.list();// 6. 遍历用户list,获取每个用户,并填充每一行单元格的数据for (int i = 0; i < 65536; i++) {User user;if (i > userList.size() - 1) {user = userList.get(userList.size() - 1);} else {user = userList.get(i);}// 创建excel的行Row row = sheet.createRow(i + 1); // 从第二行开始,索引为1// 为每个单元格填充数据row.createCell(0).setCellValue(user.getId());row.createCell(1).setCellValue(user.getUsername());row.createCell(2).setCellValue(user.getSex());row.createCell(3).setCellValue(user.getPhone());row.createCell(4).setCellValue(user.getCity());row.createCell(5).setCellValue(user.getPosition());row.createCell(6).setCellValue(user.getPosition());}// 7. 输出文件// 7.1 把excel文件写到磁盘上FileOutputStream outputStream = new FileOutputStream("d:/2.xlsx");workbook.write(outputStream); // 把excel写到输出流中outputStream.close(); // 关闭流workbook.close();long end = System.currentTimeMillis();log.info("大数据量批量数据写入用时: {} ms", end - star);
}
经测试XSSF大概十秒左右输出excel文件,而SXSSF一秒左右输出excel文件。
示例:读取excel文件
读取excel文件步骤:(通过文件流读取)
- 获取工作簿
- 获取工作表(sheet)
- 获取行(row)
- 获取单元格(cell)
- 读取数据
// 读取excel文件
@RequestMapping("/upload")
public void readExcel(MultipartFile file) {InputStream is = null;XSSFWorkbook workbook = null;try {// 1. 创建excel工作簿(workbook)is = file.getInputStream();workbook = new XSSFWorkbook(is);// 2. 获取要解析的工作表(sheet)Sheet sheet = workbook.getSheetAt(0); // 获取第一个sheet// 3. 获取表格中的每一行,排除表头,从第二行开始User user;List<User> list = new ArrayList<>();for (int i = 1; i <= sheet.getLastRowNum(); i++) {Row row = sheet.getRow(i); // 获取第i行// 4. 获取每一行的每一列,并为user对象的属性赋值,添加到list集合中user = new User();user.setUsername(row.getCell(1).getStringCellValue());user.setSex(row.getCell(2).getStringCellValue());user.setPhone(row.getCell(3).getStringCellValue());user.setCity(row.getCell(4).getStringCellValue());user.setPosition(row.getCell(5).getStringCellValue());user.setSalary(new BigDecimal(row.getCell(6).getNumericCellValue()));list.add(user);}// 5. 批量保存userService.saveBatch(list);} catch (IOException e) {e.printStackTrace();throw new RuntimeException("批量导入失败");} finally {try {if (is != null) {is.close();}if (workbook != null) {workbook.close();}} catch (IOException e) {e.printStackTrace();throw new RuntimeException("批量导入失败");}}
}



3. EasyExcel
EasyExcel是一个基于Java的、快速、简洁、解决大文件内存溢出的Excel处理工具。他能让你在不用考虑性能、内存的等因素的情况下,快速完成Excel的读、写等功能。
官网地址:https://easyexcel.opensource.alibaba.com/
文档地址:https://easyexcel.opensource.alibaba.com/docs/current/
示例代码:https://github.com/alibaba/easyexcel/tree/master/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/demo
pom依赖:
<!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel -->
<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.2.1</version>
</dependency>
最后,EasyExcel的官方文档非常全面,我就不一一赘述了。
相关文章:
SpringBoot整合POI实现Excel文件读写操作
1.环境准备 1、导入sql脚本: create database if not exists springboot default charset utf8mb4;use springboot;create table if not exists user (id bigint(20) primary key auto_increment comment 主键id,username varchar(255) not null comment 用…...
从零开始的力扣刷题记录-第八十七天
力扣每日四题 129. 求根节点到叶节点数字之和-中等130. 被围绕的区域-中等437. 路径总和 III-中等376. 摆动序列-中等总结 129. 求根节点到叶节点数字之和-中等 题目描述: 给你一个二叉树的根节点 root ,树中每个节点都存放有一个 0 到 9 之间的数字。 …...
【1】c++设计模式——>UML类图的画法
UML介绍 UML:unified modeling language 统一建模语言 面向对象设计主要就是使用UML类图,类图用于描述系统中所包含的类以及他们之间的相互关系,帮助人们简化对系统的理解,他是系统分析和设计阶段的重要产物,也是系统编码和测试的…...
SAP UI5 指定 / 变更版本
SAP UI5 指定 / 变更版本 Currently, SAP Fiori tools support SAP Fiori elements and SAPUI5 freestyle projects with minimum SAPUI5 versions 1.65 or higher. In case there’s a need to test an existing projects with a lower SAPUI5 version, the following worka…...
SpringMVC中异常处理详解
单个控制器异常处理 // 添加ExceptionHandler,表示该方法是处理异常的方法,属性为处理的异常类ExceptionHandler({java.lang.NullPointerException.class,java.lang.ArithmeticException.class})public String exceptionHandle1(Exception ex, Model mo…...
PPT课件培训视频生成系统实现全自动化
前言 困扰全动自化的重要环节,AI语音合成功能,终于可以实现自动化流程,在此要感谢团队不懈的努力和韧性的精神! 实现原理 请参照我的文章《Craneoffice云PPT课件培训视频生成系统》 基本流程 演示视频 PPT全自动 总结 过去实…...
基于腾讯云的OTA远程升级
一、OTA OTA即over the air,是一种远程固件升级技术,它允许在设备已经部署在现场运行时通过网络远程更新其固件或软件。OTA技术有许多优点,比如我们手机系统有个地方做了优化,使用OTA技术我们就不用召回每部手机,直接通过云端就可…...
如何在VS2022中进行调试bug,调试的快捷键,debug与release之间有什么区别
什么是bug 在学习编程的过程中,应该都听说过bug吧,那么bug这个词究竟是怎么来的呢? 其实Bug的本意是“虫子”或者“昆虫”,在1947年9月9日,格蕾丝赫柏,一位为美国海军工作的电脑专家,也是最早…...
初识jmeter及简单使用
目录 1、打开页面: 2、添加线程组: 3、线程组中设置参数: 4、添加请求 5、添加一个http请求后,设置请求内容 6、添加察看结果树 7、执行,查看结果 一般步骤是:在测试计划下面新建一个线程组…...
Spring 在多线程环境下如何确保事务一致性
问题在现 如何解决异步执行 多线程环境下如何确保事务一致性 事务王国回顾 事务实现方式回顾 编程式事务 利用编程式事务解决问题 问题分析完了,那么如何解决问题呢? 小结 问题在现 我先把问题抛出来,大家就明白本文目的在于解决什…...
[Machine Learning] Learning with Noisy Data
文章目录 Probabilistic Perspective of NoiseBias and VarianceRobustness among Surrogate Loss FunctionsNMF Probabilistic Perspective of Noise 假设数据来源于一个确定的函数,叠加了高斯噪声。我们有: y h ( x ) ϵ y h(x) \epsilon yh(x)ϵ…...
C++中有哪些常用的标准库?
C中有许多常用的标准库,这些库提供了丰富的功能和工具,方便开发人员进行各种任务。以下是一些常见的C标准库: iostream:用于输入和输出操作,包括cin、cout和cerr等类和函数。algorithm:提供了许多常用的算…...
软考-信息安全工程师概述
本文为作者学习文章,按作者习惯写成,如有错误或需要追加内容请留言(不喜勿喷) 本文为追加文章,后期慢慢追加 2023年10月 信息考试大纲 通过本考试的合格人员能够掌握网络信息安全的基础知识和技术原理,…...
2023-2024年华为ICT网络赛道模拟题库
2023-2024年网络赛道模拟题库上线啦,全面覆盖网络,安全,vlan考点,都是带有解析 参赛对象及要求: 参赛对象:现有华为ICT学院及未来有意愿成为华为ICT学院的本科及高职院校在校学生。 参赛要求:…...
英特尔参与 CentOS Stream 项目
导读红帽官方发布公告欢迎英特尔参与进 CentOS Stream 项目,并表示 “这一举措不仅进一步深化了我们长期的合作关系,也构建在英特尔已经在 Fedora 项目中积极贡献的基础之上。” 目前,CentOS Stream 共包括以下特别兴趣小组(SIG&a…...
Centos 服务器 MySQL 8.0 快速开启远程访问
环境: MySQL 8.0(低版本会有些不同), Rocky Linux 9.0(CentOS) 直接上干货,相信大家看到这个文章的时候都已经安装完了。 1. 先从服务器上使用 root 进行登录(刚安装完默认只能本地…...
充电保护芯片TP4054国产替代完全兼容DP4054DP4054H 锂电充电芯片
■产品概述 DP4054H是-款完整的采用恒定电流/恒定电压单节锂离子电池充电管理芯片。其SOT小封装和较少的外部元件数目使其成为便携式应用的理想器件,DP4054H可 以适合USB电源和适配器电源工作。 由于采用了内部PMOSFET架构,加上防倒充电路,所以不需要外…...
Java Spring Boot中的爬虫防护机制
随着互联网的发展,爬虫技术也日益成熟和普及。然而,对于某些网站来说,爬虫可能会成为一个问题,导致资源浪费和安全隐患。本文将介绍如何使用Java Spring Boot框架来防止爬虫的入侵,并提供一些常用的防护机制。 引言&a…...
状态模式 行为型模式之六
1.定义 允许一个对象在其对象内部状态改变时改变它的行为。 2.组成结构 Context:定义客户感兴趣的接口;维护一个ConcreteState子类的实例,这个实例定义当前的状态。State:定义一个接口来封装Context的与特定状态相关的行为。Co…...
MPNet:旋转机械轻量化故障诊断模型详解python代码复现
目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...
(十)学生端搭建
本次旨在将之前的已完成的部分功能进行拼装到学生端,同时完善学生端的构建。本次工作主要包括: 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...
使用分级同态加密防御梯度泄漏
抽象 联邦学习 (FL) 支持跨分布式客户端进行协作模型训练,而无需共享原始数据,这使其成为在互联和自动驾驶汽车 (CAV) 等领域保护隐私的机器学习的一种很有前途的方法。然而,最近的研究表明&…...
【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...
uniapp中使用aixos 报错
问题: 在uniapp中使用aixos,运行后报如下错误: AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...
算法笔记2
1.字符串拼接最好用StringBuilder,不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...
MySQL JOIN 表过多的优化思路
当 MySQL 查询涉及大量表 JOIN 时,性能会显著下降。以下是优化思路和简易实现方法: 一、核心优化思路 减少 JOIN 数量 数据冗余:添加必要的冗余字段(如订单表直接存储用户名)合并表:将频繁关联的小表合并成…...
