Java操作Excel导入导出——POI、Hutool、EasyExcel
目录
一、POI导入导出
1.数据库导出为Excel文件
2.将Excel文件导入到数据库中
二、Hutool导入导出
1.数据库导出为Excel文件——属性名是列名
2.数据库导出为Excel文件——列名起别名
3.从Excel文件导入数据到数据库——属性名是列名
4.从Excel文件导入数据到数据库——列名改为属性名
三、EasyExcel
1.数据库导出数据到一个sheet中
2.数据库导出数据到多个sheet中
3.从Excel文件导入数据到数据库
4.读取大数据量Excel文件到数据库中
5.从页面上传Excel写入数据库
6.封装导出数据库到Excel工具类
一、POI导入导出
CREATE TABLE `test_student` (`id` int NOT NULL AUTO_INCREMENT PRIMARY KEY,`name` varchar(255) DEFAULT NULL,`age` int DEFAULT NULL
);
<dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>4.1.2</version>
</dependency>
1.数据库导出为Excel文件
@Test
void f1() {// 数据库导出为Excel文件List<TestStudent> list = testStudentService.list();// 导出的位置String path = "D:\\save\\stu1.xlsx";// 工作薄 workbook(Excel本身)->sheet页签工作表 -> 行->单元格try (XSSFWorkbook workbook = new XSSFWorkbook()) {// 新建 工作薄对象// 新建sheet对象XSSFSheet sheet = workbook.createSheet("test_stu");//创建行XSSFRow row0 = sheet.createRow(0);// 创建单元格row0.createCell(0).setCellValue("学生ID");row0.createCell(1).setCellValue("学生姓名");row0.createCell(2).setCellValue("学生年龄");for (int i = 0; i < list.size(); i++) {// 略过首行XSSFRow row = sheet.createRow(i + 1);TestStudent testStudent = list.get(i);row.createCell(0).setCellValue(testStudent.getId());row.createCell(1).setCellValue(testStudent.getName());row.createCell(2).setCellValue(testStudent.getAge());}//内容写出去workbook.write(new FileOutputStream(path));} catch (IOException e) {throw new RuntimeException(e);}
}
2.将Excel文件导入到数据库中
@Test
void f2() throws IOException {// 将Excel文件导入到数据库中ArrayList<TestStudent> stuList = new ArrayList<>();// 导入的源文件String path = "D:\\save\\stu1.xlsx";// 工作薄对象Workbook workbook = WorkbookFactory.create(new FileInputStream(path));// 工作表 sheetSheet sheet = workbook.getSheetAt(0);// 行int rows = sheet.getPhysicalNumberOfRows();// 行的头信息,第一行,可以不处理for (int i = 1; i < rows; i++) {Row row = sheet.getRow(i);TestStudent student = new TestStudent();// 第一个单元格,因为是主键,可以不要// 第二个单元格student.setName(row.getCell(1).getStringCellValue());// 第三个单元格student.setAge((int) row.getCell(2).getNumericCellValue());// 把组装好的 student对象,存入集合stuList.add(student);// 不能循环调用数据库// testStudentService.save(student);}// 存数据到 数据库// 批量调用testStudentService.saveBatch(stuList);
}

二、Hutool导入导出
Hutool官网:https://hutool.cn/
<dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.16</version>
</dependency>
1.数据库导出为Excel文件——属性名是列名
@Test
void f1() {List<TestStudent> list = testStudentService.list();String path = "D:\\save\\stu2.xlsx";// 属性名就是Excel的列名ExcelWriter writer = ExcelUtil.getWriter(path);writer.write(list);writer.close();
}
2.数据库导出为Excel文件——列名起别名
@Test
void f2() {List<TestStudent> list = testStudentService.list();String path = "D:\\save\\stu3.xlsx";ExcelWriter writer = ExcelUtil.getWriter(path);writer.addHeaderAlias("id", "学生ID");writer.addHeaderAlias("name", "学生姓名");writer.addHeaderAlias("age", "学生年龄");writer.write(list);writer.close();
}
3.从Excel文件导入数据到数据库——属性名是列名
@Test
void f3() {String path = "D:\\save\\stu2.xlsx";ExcelReader reader = ExcelUtil.getReader(path);List<TestStudent> list = reader.readAll(TestStudent.class);testStudentService.saveBatch(list);
}
4.从Excel文件导入数据到数据库——列名改为属性名
@Test
void f4() {String path = "D:\\save\\stu3.xlsx";ExcelReader reader = ExcelUtil.getReader(path);// Excel列名信息与 属性不一致时,使用别名的方式读取reader.addHeaderAlias("学生ID", "id");reader.addHeaderAlias("学生姓名", "name");reader.addHeaderAlias("学生年龄", "age");List<TestStudent> list = reader.readAll(TestStudent.class);testStudentService.saveBatch(list);
}

三、EasyExcel
官网:https://easyexcel.opensource.alibaba.com/
<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.2.1</version>
</dependency>
@Data
@AllArgsConstructor
@NoArgsConstructor
public class TestStudent extends Model<TestStudent> {@TableId(type = IdType.AUTO)@ExcelProperty("学生ID")private Integer id;@ExcelProperty("学生姓名")private String name;@ExcelProperty("年龄")private Integer age;
}

1.数据库导出数据到一个sheet中
@Test
void f1() {// 数据库导出为Excel文件String path = "D:\\save\\stu4.xlsx";List<TestStudent> list = testStudentService.list();EasyExcel.write(path, TestStudent.class).sheet(0, "学生信息").doWrite(list);
}
2.数据库导出数据到多个sheet中
@Test
void f2() {// 数据库导出为Excel文件String path = "D:\\save\\stu5.xlsx";try (ExcelWriter excelWriter = EasyExcel.write(path, TestStudent.class).build()) {long count = testStudentService.count();long num = count % 100 == 0 ? count / 100 : count / 100 + 1;for (int i = 0; i < num; i++) {WriteSheet writeSheet = EasyExcel.writerSheet(i, "学生信息" + i).build();List<TestStudent> pageList = testStudentService.pageList(i + 1, 100);excelWriter.write(pageList, writeSheet);}} catch (Exception e) {throw new RuntimeException(e);}
}
3.从Excel文件导入数据到数据库
@Test
void f3() {String path = "D:\\save\\stu4.xlsx";EasyExcel.read(path,TestStudent.class,new PageReadListener<TestStudent>(list->{// 自带的分页读取,每次 只读取100条数据,防止数据量过大导致内存溢出testStudentService.saveBatch(list);})).sheet().doRead();
}
4.读取大数据量Excel文件到数据库中
@Test
void f4() {String path = "D:\\save\\stu10.xlsx";EasyExcel.read(path, TestStudent.class, new ReadListener<TestStudent>() {private static final int saveSize = 10000;private List<TestStudent> saveList = ListUtils.newArrayListWithCapacity(saveSize);// 每次读取一条,执行一次invoke方法@Overridepublic void invoke(TestStudent testStudent, AnalysisContext analysisContext) {saveList.add(testStudent);if (saveList.size() >= saveSize) {// 保存数据saveData();// 清空集合,重置集合saveList = ListUtils.newArrayListWithCapacity(saveSize);}}// 当所有的数据都读取完成时,会执行invoke方法,但是此时数据还未保存到数据库,所以需要执行doAfterAllAnalysed方法@Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {// 执行完了所有的方法,还有一些没凑够saveSize的数据,所以需要执行saveData方法进行存储saveData();}private void saveData() {testStudentService.saveBatch(saveList);}}).sheet().doRead();
}
5.从页面上传Excel写入数据库
后端接口:
@RestController
@RequestMapping("/upload")
public class UploadController {@ResourceTestStudentService testStudentService;@PostMapping("/test1")public R upload1(MultipartFile file) throws IOException {// 该方法每次自动存100条数据到数据库EasyExcel.read(file.getInputStream(),TestStudent.class,new PageReadListener<TestStudent>(list -> {testStudentService.saveBatch(list);})).sheet().doRead();return R.ok("上传成功");}
}
前端页面:Student.vue
<template><div class="common-layout"><el-container><el-header><Top/></el-header><el-container><el-aside><Menu/></el-aside><el-main><el-row><el-col><el-upload ref="uploadRef" class="upload-demo"action="http://localhost:8081/upload/test1":auto-upload="false":with-credentials="true":on-success="ups"><template #trigger> <!--#trigger用于自定义触发上传、弹出对话框或其他交互操作的按钮或元素--><el-button type="primary">选择文件</el-button></template><el-button class="ml-4" type="success" @click="submitUpload">点击上传</el-button><template #tip> <!--#tip用于插入提示信息或其他额外内容--><div class="el-upload__tip"></div></template></el-upload></el-col></el-row><el-table :data="stuList" stripe style="width: 100%"><el-table-column prop="id" label="学生ID" width="180"/><el-table-column prop="name" label="学生姓名" width="180"/><el-table-column prop="age" label="学生年龄"/></el-table></el-main></el-container></el-container></div>
</template><script setup>
import {ref, reactive, onMounted} from "vue";
import axios from '@/plugins/axios.js'
import {ElMessage} from 'element-plus'
import LoginUser from "@/stores/LoginUser.js";
import router from "@/router/index.js";
import Top from "@/components/Top.vue";
import Menu from "@/components/Menu.vue";const uploadRef = ref([])
let submitUpload = () => {uploadRef.value.submit()
}
let ups = (response, file, fileList) => {console.log(response)if (response.code === 200) {ElMessage.success(response.msg)query()} else {ElMessage.error(response.msg)}
}
let stuList = ref([])
let query = () => {let param = {"pageNum": 1,"pageSize": 10}axios.get("/test/stu/page", param).then(result => {if (result.code === 200) {stuList.value = result.data}})
}
onMounted(() => {query()
})
</script><style scoped></style>
路由:
import {createRouter, createWebHistory} from 'vue-router'
import HomeView from '../views/HomeView.vue'
import LoginView from '../views/LoginView.vue'
import TaskList from '../views/task/TaskList.vue'
import Student from '../views/test/Student.vue'const router = createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes: [{path: '/',name: 'home',component: HomeView,}, {path: '/login',name: 'login',component: LoginView,}, {path: '/task/list',name: 'taskList',component: TaskList}, {path: '/test',name: 'test',children: [{path: 'student',name: 'student',component: Student,}]}],
})export default router
导出数据库到Excel后端接口:
@RestController
@RequestMapping("/export")
public class ExportController {@ResourceHttpServletResponse response;@Resourceprivate TestStudentService testStudentService;@GetMapping("/stu/excel")public void exportStuExcel() throws IOException {//获取 需要导出的信息List<TestStudent> list = testStudentService.list();// 设置导出的文件名// 这行代码将编码后的字符串中的所有 + 替换为 %20,这样可以确保文件名在下载时不会被错误地解释为空格。String fileName = URLEncoder.encode("学生信息表", "UTF-8").replaceAll("\\+", "%20");// 设置响应头信息// response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");// response.setCharacterEncoding("utf-8");response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);// 使用 filename* 参数可以正确处理包含非 ASCII 字符的文件名。response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename*=utf-8''" + fileName + ".xlsx");/* attachment:指示浏览器将文件作为附件下载。filename*=utf-8'':使用 filename* 参数来支持非 ASCII 字符,utf-8 表示编码格式,'' 表示语言标签(通常为空)。fileName + ".xlsx":拼接编码后的文件名和文件扩展名。*/// response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");// 这行代码使用 EasyExcel 将 list 中的数据写入 Excel 文件,并将其输出到 response.getOutputStream()。EasyExcel.write(response.getOutputStream(), TestStudent.class).sheet("数据1").doWrite(list);// 不需要手动关闭 response.getOutputStream(),EasyExcel 会自动处理。// response.getOutputStream().close();}
}
前端页面:
<el-col><a href="http://localhost:8081/export/stu/excel">导出全部数据</a>
</el-col>
6.封装导出数据库到Excel工具类
@Component
public class ExportUtil<T> {@ResourceHttpServletResponse response;public void expExcel(String fileName, List<T> list, Class<T> tClass){try {fileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");// 设置响应头信息// response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");// response.setCharacterEncoding("utf-8");response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);// 使用 filename* 参数可以正确处理包含非 ASCII 字符的文件名。response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename*=utf-8''" + fileName + ".xlsx");/* attachment:指示浏览器将文件作为附件下载。filename*=utf-8'':使用 filename* 参数来支持非 ASCII 字符,utf-8 表示编码格式,'' 表示语言标签(通常为空)。fileName + ".xlsx":拼接编码后的文件名和文件扩展名。*/// response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");// 这行代码使用 EasyExcel 将 list 中的数据写入 Excel 文件,并将其输出到 response.getOutputStream()。EasyExcel.write(response.getOutputStream(), tClass).sheet("数据1").doWrite(list);}catch (IOException e){throw new RuntimeException(e);}}
}
/*** 使用工具类导出数据库到Excel*/
@Resource
ExportUtil<TestStudent> exportUtil;
@GetMapping("/stu/excel2")
public void exportStuExcel2(){exportUtil.expExcel("学生信息表", testStudentService.list(), TestStudent.class);
}相关文章:
Java操作Excel导入导出——POI、Hutool、EasyExcel
目录 一、POI导入导出 1.数据库导出为Excel文件 2.将Excel文件导入到数据库中 二、Hutool导入导出 1.数据库导出为Excel文件——属性名是列名 2.数据库导出为Excel文件——列名起别名 3.从Excel文件导入数据到数据库——属性名是列名 4.从Excel文件导入数据到数据库…...
BUUCTF_Web([GYCTF2020]Ezsqli)
1.输入1 ,正常回显。 2.输入1 ,报错false,为字符型注入,单引号闭合。 原因: https://mp.csdn.net/mp_blog/creation/editor/145170456 3.尝试查询字段,回显位置,数据库,都是这个。…...
微软宣布Win11 24H2进入新阶段!设备将自动下载更新
快科技1月19日消息,微软于1月16日更新了支持文档,宣布Windows 11 24H2进入新阶段。 24H2更新于2024年10月1日发布,此前为可选升级,如今微软开始在兼容的Windows 11设备上自动下载并安装24H2版本。 微软表示:“运行Wi…...
SpringBoot:解决前后端请求跨域问题(详细教程)
文章目录 一、前言二、解决方式 2.1 使用 CrossOrigin 注解(简单方便,适用于单个或少量接口)2.2 全局配置跨域(适用于整个项目中大量接口都需要跨域的情况)2.3 使用过滤器来处理跨域(更底层的实现方式&…...
Android-V lmkd 中的那些属性值
源码基于:Android V 相关博文: Android lmkd 机制详解(一) Android lmkd 机制详解(二) Android lmkd 机制从R到T 1. 汇总 属性名说明默认值 ro.lmk.debug 启动 lmkd 的debug 模式,会打印一…...
PageHelper快速使用
依赖 <!--分页插件PageHelper--> <dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>1.4.7</version> </dependency>示例 /** * 封装分页结果…...
图像处理基础(3):均值滤波器及其变种
均值滤波器可以归为低通滤波器,是一种线性滤波器,其输出为邻域模板内的像素的简单平均值,主要用于图像的模糊和降噪。 均值滤波器的概念非常的直观,使用滤波器窗口内的像素的平均灰度值代替图像中的像素值,这样的结果就…...
力扣刷题心得_JAVA
数学 > 数组 > 链表 > 字符串 > 哈希表 > 双指针 > 递归 > 栈 > 队列 > 树 //一般力扣中传入的参数和新建的对象作为返回值,都不列入空间复杂度中 //但是面试的时候要和面试官商量好,灵活定义空间复杂度 //当然最好是就在传入的对象作为返回值,(在原…...
音乐播放器实现:前端HTML,CSS,JavaScript综合大项目
音乐播放器实现:前端HTML,CSS,JavaScript综合大项目 项目概述项目视图效果一、侧边栏相关代码(一)HTML代码(二)css代码 二、登录页面(一)HTML代码(二)css代码…...
Unity编辑器缩放设置
Unity默认界面UI字体太小了,可以设置一下缩放 打开首选项, UI Scaling 设置成125%或者更大 ,然后重启...
ChatGPT大模型极简应用开发-CH1-初识 GPT-4 和 ChatGPT
文章目录 1.1 LLM 概述1.1.1 语言模型和NLP基础1.1.2 Transformer及在LLM中的作用1.1.3 解密 GPT 模型的标记化和预测步骤 1.2 GPT 模型简史:从 GPT-1 到 GPT-41.2.1 GPT11.2.2 GPT21.2.3 GPT-31.2.4 从 GPT-3 到 InstructGPT1.2.5 GPT-3.5、Codex 和 ChatGPT1.2.6 …...
Golang学习笔记_27——单例模式
Golang学习笔记_24——泛型 Golang学习笔记_25——协程Golang学习笔记_25——协程 Golang学习笔记_26——通道 文章目录 单例模式1. 介绍2. 应用场景3. 实现3.1 饿汉式3.2 懒汉模式 源码 单例模式 1. 介绍 单例模式是一种创建型设计模式,它确保一个类只有一个实例…...
хорошо哈拉少wordpress俄语主题
хорошо哈拉少wordpress俄语主题 wordpress俄文网站模板,推荐做俄罗斯市场的外贸公司建俄语独立站使用。 演示 https://www.jianzhanpress.com/?p7360...
[数据结构与算法]js实现二叉树
DFS 与 BFS dfs 递归 本质通过栈结构 bfs 层序遍历 通过队列结构 function permute(nums) {let res [];let cur []; // 记录当前内容let visted {}; //记录访问过的节点let len nums.length;function dfs(nth) {//递归终止条件if (nth len) {res.push([...cur]);return …...
MySQL程序之:连接到服务器的命令选项
本节介绍大多数MySQL客户端程序支持的选项,这些选项控制客户端程序如何建立与服务器的连接、连接是否加密以及连接是否压缩。这些选项可以在命令行或选项文件中给出。 连接建立的命令选项 本节介绍控制客户端程序如何建立与服务器的连接的选项。 表6.4连接建立选…...
python3GUI--仿崩坏三二次元登录页面(附下载地址) By:PyQt5
文章目录 一.前言二.预览三.实现方案1.实现原理1.PyQt52. 具体实现 2.UI设计1.UI组件化、模块化2.UI设计风格思路 3.项目代码结构4.使用方法3.代码分享1.支持跳转网页的QLabel组件2.三角形ICON按钮 四.总结 大小:33.3 …...
阿里云 Serverless 助力盟主直播:高并发下的稳定性和成本优化
在直播场景中,阿里云 Serverless 应用引擎 SAE 提供的无缝弹性伸缩与极速部署能力,确保直播间高并发时的流畅体验,降低了我们的运营成本,简化了运维流程。结合阿里云云原生数据库 PolarDB 的 Serverless 能力,实现了数…...
Unity 学习指南与资料分享
Unity学习资料 Unity学习资料 Unity学习资料 Unity 作为一款强大的跨平台游戏开发引擎,在游戏开发及实时 3D 内容创作领域占据着重要地位。它功能丰富、易于上手,支持多平台发布,为开发者提供了广阔的创作空间。下面为你带来全面的 Unity 学…...
Android SystemUI——CarSystemBar视图解析(十一)
前面文章我们已经把 CarSystemBar 从启动到构建视图,再到将视图添加到 Window 的流程分析完毕,我们知道默认情况下在车载系统中只显示顶部栏和底部栏视图的。这里我们在前面文章的基础上以顶部栏为例具体解析其视图的结构。 一、顶部栏解析 通过《CarSystemBar车载状态栏》这…...
.NET周刊【1月第1期 2025-01-05】
国内文章 3款.NET开源、功能强大的通讯调试工具,效率提升利器! https://www.cnblogs.com/Can-daydayup/p/18631410 本文介绍了三款功能强大的.NET开源通讯调试工具,旨在提高调试效率。这些工具包括LLCOM,提供串口调试和自动化处…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...
相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...
Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...
安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖
在Vuzix M400 AR智能眼镜的助力下,卢森堡罗伯特舒曼医院(the Robert Schuman Hospitals, HRS)凭借在无菌制剂生产流程中引入增强现实技术(AR)创新项目,荣获了2024年6月7日由卢森堡医院药剂师协会࿰…...
毫米波雷达基础理论(3D+4D)
3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文: 一文入门汽车毫米波雷达基本原理 :https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...
【Linux】自动化构建-Make/Makefile
前言 上文我们讲到了Linux中的编译器gcc/g 【Linux】编译器gcc/g及其库的详细介绍-CSDN博客 本来我们将一个对于编译来说很重要的工具:make/makfile 1.背景 在一个工程中源文件不计其数,其按类型、功能、模块分别放在若干个目录中,mak…...
go 里面的指针
指针 在 Go 中,指针(pointer)是一个变量的内存地址,就像 C 语言那样: a : 10 p : &a // p 是一个指向 a 的指针 fmt.Println(*p) // 输出 10,通过指针解引用• &a 表示获取变量 a 的地址 p 表示…...
Python 高效图像帧提取与视频编码:实战指南
Python 高效图像帧提取与视频编码:实战指南 在音视频处理领域,图像帧提取与视频编码是基础但极具挑战性的任务。Python 结合强大的第三方库(如 OpenCV、FFmpeg、PyAV),可以高效处理视频流,实现快速帧提取、压缩编码等关键功能。本文将深入介绍如何优化这些流程,提高处理…...
自然语言处理——文本分类
文本分类 传统机器学习方法文本表示向量空间模型 特征选择文档频率互信息信息增益(IG) 分类器设计贝叶斯理论:线性判别函数 文本分类性能评估P-R曲线ROC曲线 将文本文档或句子分类为预定义的类或类别, 有单标签多类别文本分类和多…...
人工智能 - 在Dify、Coze、n8n、FastGPT和RAGFlow之间做出技术选型
在Dify、Coze、n8n、FastGPT和RAGFlow之间做出技术选型。这些平台各有侧重,适用场景差异显著。下面我将从核心功能定位、典型应用场景、真实体验痛点、选型决策关键点进行拆解,并提供具体场景下的推荐方案。 一、核心功能定位速览 平台核心定位技术栈亮…...
