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.pswp.cn/web/66497.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/66497.shtml
英文地址,請注明出處:http://en.pswp.cn/web/66497.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

下載文件,瀏覽器阻止不安全下載

背景&#xff1a; 在項目開發中&#xff0c;遇到需要下載文件的情況&#xff0c;文件類型可能是圖片、excell表、pdf、zip等文件類型&#xff0c;但瀏覽器會阻止不安全的下載鏈接。 效果展示&#xff1a; 下載文件的兩種方式&#xff1a; 一、根據接口的相對url&#xff0c;拼…

第15章:Python TDD應對貨幣類開發變化(二)

寫在前面 這本書是我們老板推薦過的&#xff0c;我在《價值心法》的推薦書單里也看到了它。用了一段時間 Cursor 軟件后&#xff0c;我突然思考&#xff0c;對于測試開發工程師來說&#xff0c;什么才更有價值呢&#xff1f;如何讓 AI 工具更好地輔助自己寫代碼&#xff0c;或許…

CSS 動畫相關屬性

定義和用法 一些 CSS 屬性可用于動畫制作&#xff0c;這意味著它們可用于過渡等效果中。 可設置動畫的屬性可以從一個值逐漸更改為另一個值&#xff0c;例如尺寸、數字、百分比和顏色。 瀏覽器支持 表格中的數字注明了完全支持 CSS 動畫的首個瀏覽器版本。 -webkit-、-moz…

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;其中一家銀行正在開發…

《探索煙霧目標檢測開源項目:技術與應用的深度剖析》

一、引言 在現代社會&#xff0c;火災猶如高懸的達摩克利斯之劍&#xff0c;時刻威脅著人們的生命財產安全。煙霧&#xff0c;作為火災發生的重要征兆&#xff0c;其及時、準確的檢測對于火災預防和控制起著舉足輕重的作用。煙霧目標檢測技術猶如敏銳的 “電子哨兵”&#xff…

Linux操作系統的靈魂,深度解析MMU內存管理

在計算機的奇妙世界里&#xff0c;我們每天使用的操作系統看似流暢自如地運行著各類程序&#xff0c;背后實則有著一位默默耕耘的 “幕后英雄”—— 內存管理單元&#xff08;MMU&#xff09;。它雖不常被大眾所熟知&#xff0c;卻掌控著計算機內存的關鍵命脈&#xff0c;是保障…

3.2 OpenAI 語言模型總覽:GPT 系列的演進與應用解析

OpenAI 語言模型總覽:GPT 系列的演進與應用解析 OpenAI 的語言模型,特別是 GPT(Generative Pre-trained Transformer)系列,代表了當前自然語言處理(NLP)技術的前沿。自從推出以來,這些模型不斷推進了文本生成、理解和交互的能力,成為了多個應用場景中的核心技術。本文…

【云嵐到家】-day02-客戶管理-認證授權

第二章 客戶管理 1.認證模塊 1.1 需求分析 1.基礎概念 一般情況有用戶交互的項目都有認證授權功能&#xff0c;首先我們要搞清楚兩個概念&#xff1a;認證和授權 認證: 就是校驗用戶的身份是否合法&#xff0c;常見的認證方式有賬號密碼登錄、手機驗證碼登錄等 授權:則是該用…

Thinkphp8 Apidoc 實際使用中遇到的問題解決

1. 接口去掉 Controller 問題: 正確的路徑應該是/api/login/register, 這塊controller有沒有地方配置的? 2. 自定義成功,錯誤消息有沒有辦法? 未完成, 待更新

2024春秋杯密碼題第一、二天WP

你是小哈斯? 題目內容&#xff1a; 年輕黑客小符參加CTF大賽&#xff0c;他發現這個小哈斯文件的內容存在高度規律性&#xff0c;并且文件名中有隱藏信息&#xff0c;他成功找到了隱藏的信息&#xff0c;并破解了挑戰。得意地說&#xff1a;“成功在于探索與質疑&#xff0c…

opencv對直方圖的計算和繪制

【歡迎關注編碼小哥&#xff0c;學習更多實用的編程方法和技巧】 1、直方圖的計算 cv::calcHist 是 OpenCV 中用于計算圖像直方圖的函數。它可以處理多通道圖像&#xff0c;并通過指定圖像、通道、掩膜、直方圖大小和范圍等參數來生成直方圖。 函數原型 void cv::calcHist(…

C++的auto_ptr智能指針:從誕生到被棄用的歷程

C作為一種功能強大的編程語言&#xff0c;為開發者提供了眾多便捷的特性和工具&#xff0c;其中智能指針是其重要特性之一。智能指針能夠自動管理內存&#xff0c;有效避免內存泄漏等常見問題。然而&#xff0c;并非所有智能指針都盡善盡美&#xff0c;auto_ptr便是其中的一個例…

游戲開發中常用的設計模式

目錄 前言一、工廠模式二、單例模式三、觀察者模式觀察者模式的優勢 四、狀態模式狀態模式的優勢 五、策略模式策略模式的優勢策略模式與狀態模式有什么區別呢? 六、組合模式七、命令模式八、裝飾器模式 前言 本文介紹了游戲開發中常用的設計模式&#xff0c;如工廠模式用于創…

C++并發編程之異常安全性增強

在并發編程中&#xff0c;異常安全是一個非常重要的方面&#xff0c;因為并發環境下的錯誤處理比單線程環境更加復雜。當多個線程同時執行時&#xff0c;異常不僅可能影響當前線程&#xff0c;還可能影響其他線程和整個程序的穩定性。以下是一些增強并發程序異常安全性的方法&a…

各語言鏡像配置匯總

鏡像配置匯總 Nodejs [ npm ]Python [ pip ] Nodejs [ npm ] // # 記錄日期&#xff1a;2025-01-20// 查詢當前使用的鏡像 npm get registry// 設置淘寶鏡像 npm config set registry https://registry.npmmirror.com/// 恢復為官方鏡像 npm config set registry https://regi…

Navicat Premium 數據可視化

工作區&#xff0c;數據源以及圖表 數據可視化是使用可視化組件&#xff08;例如圖表&#xff0c;圖形和地圖&#xff09;的信息和數據的圖形表示。 數據可視化工具提供了一種可訪問的方式&#xff0c;用于查看和理解數據中的趨勢&#xff0c;異常值和其他模式。 在Navicat中&…

linux通過web向mac遠程傳輸字符串,mac收到后在終端中直接打印。

要通過Web從Linux向Mac遠程傳輸字符串&#xff0c;并在Mac的終端中直接打印&#xff0c;可以使用以下方法。這里假設Linux作為服務器&#xff0c;Mac作為客戶端。 方法 1&#xff1a;使用Python的HTTP服務器 在Linux上啟動一個簡單的HTTP服務器&#xff0c;Mac通過curl獲取字符…

【系統分享01】Python+Vue電影推薦系統

大家好&#xff0c;作為一名老程序員&#xff0c;今天我將帶你一起走進電影推薦系統的世界&#xff0c;分享如何利用 Django REST Framework 和 Vue 搭建一套完整的電影推薦系統&#xff0c;結合 協同過濾算法&#xff0c;根據用戶評分與影片喜好&#xff0c;精準推送用戶可能喜…

Spring Boot+Vue

Spring BootVue 前后端分離是一種非常流行且高效的開發模式&#xff0c;以下是關于其相關方面的詳細介紹&#xff1a; 前端&#xff08;Vue&#xff09;部分 ? 項目搭建 ? 使用 Vue CLI 創建項目&#xff0c;它提供了豐富的插件和配置選項&#xff0c;能夠快速生成項目基礎…