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);

image-20231001224214707

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 插件生成基础代码:

image-20231001224944713

① 配置数据库:

image-20231001224418894

image-20231001224520414

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

image-20231001224612743

image-20231001225559406

image-20231002165231209


2. POI


Excel报表的两种方式:

在企业级应用开发中,Excel报表是一种常见的报表需求,Excel报表开发一般分为两种形式:

  • 把Excel中的数据导入到系统中;(上传)

  • 通过Java代码生成Excel报表。(下载)


Excel版本:

目前世面上的Excel分为两个大版本:Excel2003 和 Excel2007及以上版本;

Excel2003是一个特有的二进制格式,其核心结构是复合文档类型的结构,存储数据量较小;Excel2007 的核心结构是 XML 类型的结构,采用的是基于 XML 的压缩方式,使其占用的空间更小,操作效率更高。

Excel 2003Excel 2007
后缀xlsxlsx
结构二进制格式,其核心结构是复合文档类型的结构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();}
}

image-20231004224921153


示例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("批量导入失败");}}
}

image-20231007062047348

image-20231007062527489

image-20231007062019296


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的官方文档非常全面,我就不一一赘述了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/153541.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

NSSCTF做题(7)

[第五空间 2021]pklovecloud 反序列化 <?php include flag.php; class pkshow { function echo_name() { return "Pk very safe^.^"; } } class acp { protected $cinder; public $neutron; …

《要么孤独 要么庸俗》 笔记

人往往比自己想象的更愚蠢 我的生存原则或意志行事原则是什么&#xff1f;尝试考察自己的生命年轮 一个明智的人不会被表面稳定现象欺骗&#xff0c;还能预测事物发展趋向 由于只能理解结果而不是原因&#xff0c;会错误的认为结果会一直持续下去 很多事情需要时间来兑现&#…

【高级语言程序设计】python函数式编程(一)

基础知识 Python函数式编程的主要内容包括以下几个方面&#xff1a; (1)函数作为一等公民&#xff1a;在函数式编程中&#xff0c;函数被视为一等公民&#xff0c;可以像其他数据类型一样被传递、赋值以及作为返回值。 (2)不可变数据&#xff1a;函数式编程鼓励使用不可变数据…

docker安装wiki

1.docker pull mediawiki 2.docker run -d --name mywiki -p 8666:80 mediawiki 访问ip:8666,就可以看到配置页面了 3.docker pull mysql docker run -d --name my-mysql -e MYSQL_ROOT_PASSWORD123456 -p 3307:3306 mysql 4.在配置页面链接ip:3307,连接数据库&#xff0c;接下…

C++QT-day3

#include <iostream> /*设计一个Per类&#xff0c;类中包含私有成员:姓名、年龄、* 指针成员身高、体重&#xff0c;再设计一个Stu类&#xff0c;* 类中包含私有成员:成绩、Per类对象p1&#xff0c;* 设计这两个类的构造函数、析构函数和拷贝构造函数。*/ using namespac…

二维码解码文字或者链接怎么做?二维码分解内容的方法

当需要提取出二维码中的文字或者链接时该如何处理呢&#xff1f;一般想要获取二维码中的文本/链接内容可以使用二维码解码&#xff08;二维码解码器在线-二维码图片解码-二维码转短链接生成器-机智熊二维码&#xff09;工具来处理&#xff0c;只需要上传二维码图片就可以自动识…

【git merge/rebase】详解合并代码、解决冲突

目录 1.概述 2.merge 3.rebase 4.merge和rabase的区别 5.解决冲突 1.概述 在实际开发中&#xff0c;一个项目往往是多个人一起协作的&#xff0c;头天下班前大家把代码交到远端仓库&#xff0c;第二天工作的第一件事情都是从服务器上拉最新的代码&#xff0c;保证代码版本…

CSS 布局案例: 2行、多行每行格数不定,最后一列对齐

布局期望的效果如下&#xff1a; 第二行最后一格与第一行最后一格对齐。每行格数不定。自动拉伸填充整个宽度 实现&#xff1a; 一开始打算用display:flex&#xff0c; 自动分散&#xff0c;但是第二行对齐第一行最后一格控制不了。 使用grid fr均分单位控制。 <!DOCTYPE…

智能AI创作系统ChatGPT详细搭建教程/AI绘画系统/支持GPT联网提问/支持Prompt应用/支持国内AI模型

一、智能AI创作系统 SparkAi创作系统是基于OpenAI很火的ChatGPT进行开发的Ai智能问答系统&#xff0c;支持OpenAI GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭建部署AI创作…

Scala第二十章节

Scala第二十章节 scala总目录 文档资料下载 章节目标 理解Akka并发编程框架简介掌握Akka入门案例掌握Akka定时任务代码实现掌握两个进程间通信的案例掌握简易版spark通信框架案例 1. Akka并发编程框架简介 1.1 Akka概述 Akka是一个用于构建高并发、分布式和可扩展的基于事…

途虎养车上市、京东养车“震虎”,如何突围汽车后市场?

“汽车后市场第一股”终于来了&#xff01; 赶在十一黄金周之前&#xff0c;途虎养车股份有限公司(09690.HK&#xff0c;下称“途虎养车”)于9月26日挂牌港交所&#xff0c;开盘价为28港元/股&#xff0c;与发行价持平&#xff1b;IPO首日报收29.50港元/股&#xff0c;涨幅5.3…

2023年中国烹饪机器人市场发展概况分析:整体规模较小,市场仍处于培育期[图]

烹饪机器人仍属于家用电器范畴&#xff0c;是烹饪小家电的进一步细分&#xff0c;它是烹饪小家电、人工智能和服务机器在厨房领域的融合。烹饪机器人是一种智能化厨房设备&#xff0c;可以根据预设的程序实现自动翻炒和烹饪&#xff0c;是多功能料理机和炒菜机结合的产物。 烹…

Android NFC开发详解:NFC读卡实例解析及总结

文章目录 前言一、什么是NFC&#xff1f;二、基础知识1.什么是NDEF&#xff1f;2.NFC技术的操作模式3.标签的技术类型4.实现方式的分类5.流程三、获取标签内容1.检查环境2.获取NFC标签2.1 Manifest中注册的方式获取Tag2.1 前台Activity捕获的方式获取Tag四、解析标签数据1. M1…

Tomcat 9.0.41在IDEA中乱码问题(IntelliJ IDEA 2022.1.3版本)

1. 乱码的产生是由于编码和解码的编码表不一致引起的。 2. 排查乱码原因 2.1 在idea中启动Tomcat时控制台乱码排查 Tomcat输出日志乱码: 首先查看IDEA控制台&#xff0c;检查发现默认编码是GBK。 再查看Tomcat日志&#xff08;conf文件下logging.properties&#xff09;的默…

安全性第一!OpenWRT配置SFTP远程文件传输,实现数据安全保护

文章目录 前言1. openssh-sftp-server 安装2. 安装cpolar工具3.配置SFTP远程访问4.固定远程连接地址 前言 本次教程我们将在OpenWRT上安装SFTP服务&#xff0c;并结合cpolar内网穿透&#xff0c;创建安全隧道映射22端口&#xff0c;实现在公网环境下远程OpenWRT SFTP&#xff…

在美国如何申请批准销售儿童玩具?提交哪些相关文件?需要的认证是?

在美国如何申请批准销售儿童玩具&#xff1f;提交哪些相关文件&#xff1f;需要的认证是&#xff1f;ASTM F963-17 ​在美国销售玩具 重要&#xff1a; 如果您要在亚马逊商城销售商品&#xff0c;则必须遵守适用于这些商品和商品信息的所有联邦、州和地方法律以及亚马逊政策。…

Flutter环境搭建及新建项目

一、下载安装压缩包 https://storage.flutter-io.cn/flutter_infra_release/releases/stable/windows/flutter_windows_3.10.6-stable.zip 二、解压缩 解压之后&#xff0c;将里面的flutter整体拿出来 三、配置环境变量 将flutter/bin全路径配置到系统环境变量里面 四、运行…

fatal: Not a git repository (or any parent up to mount point /home)解决方法

Git遇到一个问题&#xff1a; fatal: Not a git repository (or any parent up to mount point /home) Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set). 解决办法&#xff1a;git init 错误信息指出不是一个git仓库&#xff0c;或者它的父级目录…

轻松实现时间录入自由!如何在Microsoft Word中轻松插入格式化的日期和时间

在文档中插入当前日期和时间有几个原因。你可能希望将其插入信函或页眉或页脚中。无论是什么原因&#xff0c;Word都可以轻松地将日期和时间插入文档。 如果希望在打开或打印文档时自动更新日期和时间&#xff0c;可以将其作为自动更新的字段插入。该字段也可以随时手动更新。…