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

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

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

相关文章

下载文件,浏览器阻止不安全下载

背景&#xff1a; 在项目开发中&#xff0c;遇到需要下载文件的情况&#xff0c;文件类型可能是图片、excell表、pdf、zip等文件类型&#xff0c;但浏览器会阻止不安全的下载链接。 效果展示&#xff1a; 下载文件的两种方式&#xff1a; 一、根据接口的相对url&#xff0c;拼…

SD/MMC驱动开发

一、介绍 MMC的全称是”MultiMediaCard”――所以也通常被叫做”多媒体卡”&#xff0c;是一种小巧大容量的快闪存储卡,特别应用于移动电话和数字影像及其他移动终端中。MMC存贮卡只有7pin&#xff0c;可以支持MMC和SPI两种工作模式。 SD卡&#xff0c;数字安全记忆卡&#xf…

Elasticsearch:Jira 连接器教程第一部分

作者&#xff1a;来自 Elastic Gustavo Llermaly 将我们的 Jira 内容索引到 Elaasticsearch 中以创建统一的数据源并使用文档级别安全性进行搜索。 在本文中&#xff0c;我们将回顾 Elastic Jira 原生连接器的一个用例。我们将使用一个模拟项目&#xff0c;其中一家银行正在开发…

Linux操作系统的灵魂,深度解析MMU内存管理

在计算机的奇妙世界里&#xff0c;我们每天使用的操作系统看似流畅自如地运行着各类程序&#xff0c;背后实则有着一位默默耕耘的 “幕后英雄”—— 内存管理单元&#xff08;MMU&#xff09;。它虽不常被大众所熟知&#xff0c;却掌控着计算机内存的关键命脉&#xff0c;是保障…

【云岚到家】-day02-客户管理-认证授权

第二章 客户管理 1.认证模块 1.1 需求分析 1.基础概念 一般情况有用户交互的项目都有认证授权功能&#xff0c;首先我们要搞清楚两个概念&#xff1a;认证和授权 认证: 就是校验用户的身份是否合法&#xff0c;常见的认证方式有账号密码登录、手机验证码登录等 授权:则是该用…

Thinkphp8 Apidoc 实际使用中遇到的问题解决

1. 接口去掉 Controller 问题: 正确的路径应该是/api/login/register, 这块controller有没有地方配置的? 2. 自定义成功,错误消息有没有办法? 未完成, 待更新

C++的auto_ptr智能指针:从诞生到被弃用的历程

C作为一种功能强大的编程语言&#xff0c;为开发者提供了众多便捷的特性和工具&#xff0c;其中智能指针是其重要特性之一。智能指针能够自动管理内存&#xff0c;有效避免内存泄漏等常见问题。然而&#xff0c;并非所有智能指针都尽善尽美&#xff0c;auto_ptr便是其中的一个例…

游戏开发中常用的设计模式

目录 前言一、工厂模式二、单例模式三、观察者模式观察者模式的优势 四、状态模式状态模式的优势 五、策略模式策略模式的优势策略模式与状态模式有什么区别呢? 六、组合模式七、命令模式八、装饰器模式 前言 本文介绍了游戏开发中常用的设计模式&#xff0c;如工厂模式用于创…

Navicat Premium 数据可视化

工作区&#xff0c;数据源以及图表 数据可视化是使用可视化组件&#xff08;例如图表&#xff0c;图形和地图&#xff09;的信息和数据的图形表示。 数据可视化工具提供了一种可访问的方式&#xff0c;用于查看和理解数据中的趋势&#xff0c;异常值和其他模式。 在Navicat中&…

【系统分享01】Python+Vue电影推荐系统

大家好&#xff0c;作为一名老程序员&#xff0c;今天我将带你一起走进电影推荐系统的世界&#xff0c;分享如何利用 Django REST Framework 和 Vue 搭建一套完整的电影推荐系统&#xff0c;结合 协同过滤算法&#xff0c;根据用户评分与影片喜好&#xff0c;精准推送用户可能喜…

【大数据2025】MapReduce

MapReduce 基础介绍 起源与发展&#xff1a;是 2004 年 10 月谷歌发表的 MAPREDUCE 论文的开源实现&#xff0c;最初用于大规模网页数据并行处理&#xff0c;现成为 Hadoop 核心子项目之一&#xff0c;是面向批处理的分布式计算框架。基本原理&#xff1a;分为 map 和 reduce …

主从复制

简述mysql 主从复制原理及其工作过程&#xff0c;配置一主两从并验证。 主从原理&#xff1a;MySQL 主从同步是一种数据库复制技术&#xff0c;它通过将主服务器上的数据更改复制到一个或多个从服务器&#xff0c;实现数据的自动同步。 主从同步的核心原理是将主服务器上的二…

【博客之星评选】2024年度前端学习总结

故事的开端...始于2024年第一篇前端技术博客 那故事的终末...也该结束于陪伴了我一整年的前端知识了 踏入 2025 年&#xff0c;满心激动与自豪&#xff0c;我成功闯进了《2024 年度 CSDN 博客之星总评选》的 TOP300。作为一名刚接触技术写作不久的萌新&#xff0c;这次能走到这…

《TikTok停服:信息安全警钟长鸣》

一、TikTok 停服事件回顾 2025 年 1 月 18 日晚&#xff0c;TikTok 通知美国用户&#xff0c;由于美官方禁令于 19 日起生效&#xff0c;TikTok 软件将暂时对用户停止服务。这一消息犹如一颗重磅炸弹&#xff0c;瞬间在全球范围内掀起轩然大波。美国用户对此猝不及防&#xff0…

图论DFS:黑红树

我的个人主页 {\large \mathsf{{\color{Red} 我的个人主页} } } 我的个人主页 往 {\color{Red} {\Huge 往} } 往 期 {\color{Green} {\Huge 期} } 期 文 {\color{Blue} {\Huge 文} } 文 章 {\color{Orange} {\Huge 章}} 章 DFS 算法&#xff1a;记忆化搜索DFS 算法&#xf…

C++,设计模式,【目录篇】

文章目录 1. 简介2. 设计模式的分类2.1 创建型模式&#xff08;Creational Patterns&#xff09;&#xff1a;2.2 结构型模式&#xff08;Structural Patterns&#xff09;&#xff1a;2.3 行为型模式&#xff08;Behavioral Patterns&#xff09;&#xff1a; 3. 使用设计模式…

项目实战--网页五子棋(游戏大厅)(3)

我们的游戏大厅界面主要需要包含两个功能&#xff0c;一是显示用户信息&#xff0c;二是匹配游戏按钮 1. 页面实现 hall.html <!DOCTYPE html> <html lang"ch"> <head><meta charset"UTF-8"><meta name"viewport"…

大模型UI:Gradio全解11——Chatbot:融合大模型的聊天机器人(4)

大模型UI&#xff1a;Gradio全解11——Chatbot&#xff1a;融合大模型的聊天机器人&#xff08;4&#xff09; 前言本篇摘要11. Chatbot&#xff1a;融合大模型的多模态聊天机器人11.4 使用Blocks创建自定义聊天机器人11.4.1 简单聊天机器人演示11.4.2 立即响应和流式传输11.4.…

STM32 FreeRTOS内存管理简介

在使用 FreeRTOS 创建任务、队列、信号量等对象时&#xff0c;通常都有动态创建和静态创建的方式。动态方式提供了更灵活的内存管理&#xff0c;而静态方式则更注重内存的静态分配和控制。 如果是1的&#xff0c;那么标准 C 库 malloc() 和 free() 函数有时可用于此目的&#…

【Linux系统编程】—— 深度解析进程等待与终止:系统高效运行的关键

文章目录 进程创建再次认识fork()函数fork()函数返回值 写时拷贝fork常规⽤法以及调用失败的原因 进程终⽌进程终止对应的三种情况进程常⻅退出⽅法_exit函数exit函数return退出 进程等待进程等待的必要性进程等待的⽅法 进程创建 再次认识fork()函数 fork函数初识&#xff1…