Springboot項目中使用EasyPOI操作Excel的詳細(xì)教程
1、EasyPOI簡介
上幾篇文章都介紹poi在導(dǎo)出導(dǎo)出excel、導(dǎo)出csv、word的功能,用起來感覺代碼有點(diǎn)過于繁瑣,目前開發(fā)市場上流行一種簡化POI開發(fā)的類庫:easyPOI。從名稱上就能發(fā)現(xiàn)就是為了簡化開發(fā)。
Excel的快速導(dǎo)入導(dǎo)出,Excel模板導(dǎo)出,Word模板導(dǎo)出,可以僅僅5行代碼就可以完成Excel的導(dǎo)入導(dǎo)出,修改導(dǎo)出格式簡單粗暴,快速有效。
Easypoi需要熟悉Poi的操作,它是為簡化poi的開發(fā),使用模板更便捷。
為誰而開發(fā)?
Easypoi的目標(biāo)不是替代poi,而是讓一個不懂導(dǎo)入導(dǎo)出的快速使用poi完成Excel和word的各種操作,而不是看很多api才可以完成這樣工作。
再次強(qiáng)調(diào)一下easyPOI完全替代不了POI!
需要的依賴
把項目中的poi的依賴去除
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-base</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-web</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-annotation</artifactId>
<version>4.1.0</version>
</dependency>或SpringBoot
<dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-spring-boot-starter</artifactId> <version>4.4.0</version> </dependency>
2、注解方式導(dǎo)出
2.1. 修改實(shí)體類,添加注解
其中主要用到的注解是@Excel注解,更詳細(xì)的說明請看這里 (按住ctrl點(diǎn)擊)
此處注意必須要有空構(gòu)造函數(shù),否則會報錯“對象創(chuàng)建錯誤”
package com.tigerhhzz.pojo;
import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.annotation.ExcelCollection;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.util.Date;
import java.util.List;
/**
* 員工
* @author Administrator
*/
@Data
@TableName(value="tb_user")
public class User {
@TableId(value = "id",type = IdType.AUTO)
@Excel(name = "編號", orderNum = "0", width = 5)
private Long id; //主鍵
@Excel(name = "員工名", orderNum = "1", width = 15,isImportField="true")
private String userName; //員工名
@Excel(name = "手機(jī)號", orderNum = "2", width = 15,isImportField="true")
private String phone; //手機(jī)號
@Excel(name = "省份名", orderNum = "3", width = 15,isImportField="true")
private String province; //省份名
@Excel(name = "城市名", orderNum = "4", width = 15,isImportField="true")
private String city; //城市名
@Excel(name = "工資", orderNum = "5", width = 10,type = 10,isImportField="true") //type=10表示會導(dǎo)出數(shù)字
private Integer salary; // 工資
@JsonFormat(pattern="yyyy-MM-dd")
@Excel(name = "入職日期", format = "yyyy-MM-dd",orderNum = "6", width = 15,isImportField="true")
private Date hireDate; // 入職日期
private String deptId; //部門id
@Excel(name = "出生日期", format = "yyyy-MM-dd",orderNum = "7", width = 15,isImportField="true")
private Date birthday; //出生日期
@Excel(name = "照片", orderNum = "10",width = 15,type = 2,isImportField="true",savePath = "F:\\idea-project\\easypoi-demo\\src\\main\\resources\\static\\user_photos")
private String photo; //一寸照片
@Excel(name = "現(xiàn)在居住地址", orderNum = "9", width = 30,isImportField="true")
private String address; //現(xiàn)在居住地址
//映射一對多關(guān)系
@TableField(exist = false) //非數(shù)據(jù)庫字段
@ExcelCollection(name = "資源列表", orderNum = "5")
private List<Resource> resourceList; //辦公用品
public List<Resource> getResources() {
return resourceList;
}
public void setResources(List<Resource> resources) {
this.resourceList = resources;
}
}2.2. UserController添加方法
@GetMapping(value = "/downLoadUserInfoWithEastPOI",name = "導(dǎo)出用戶詳細(xì)信息-使用EasyPoi")
public void downLoadUserInfoWithEastPOI(Long id,HttpServletRequest request,HttpServletResponse response) throws Exception{
userService.downLoadUserInfoWithEastPOI(id,request,response);
}2.3. UserService實(shí)現(xiàn)方法
void downLoadXlsxWithEayPoi(HttpServletResponse response) throws Exception;
2.4. 實(shí)現(xiàn)類
@Override
public void downLoadUserInfoWithEastPOI(Long id, HttpServletRequest request, HttpServletResponse response) throws Exception {
// 獲取模板的路徑
File rootPath = new File(ResourceUtils.getURL("classpath:").getPath()); //SpringBoot項目獲取根目錄的方式
File templatePath = new File(rootPath.getAbsolutePath(),"/excel_template/userInfoEasyPoi.xlsx");
// 讀取模板文件
TemplateExportParams params = new TemplateExportParams(templatePath.getPath(),true);
// 查詢用戶,轉(zhuǎn)成map
User user = userMapper.selectById(id);
Map<String, Object> map = EntityUtils.entityToMap(user);
ImageEntity userImage = new ImageEntity();
userImage.setType(ImageEntity.URL); // 設(shè)置類型為URL
// userImage.setHeight(64); //測試發(fā)現(xiàn) 這里設(shè)置了長度和寬度在合并后的單元格中沒有作用
// userImage.setWidth(380);
userImage.setRowspan(5);//向下合并三行
userImage.setColspan(3);//向右合并兩列
// userImage.setData(ImageConverter.jpgToBytes(rootPath+user.getPhoto()));
userImage.setUrl(user.getPhoto());
map.put("photo", userImage);
Workbook workbook = ExcelExportUtil.exportExcel(params, map);
// 導(dǎo)出的文件名稱
String filename="用戶詳細(xì)信息數(shù)據(jù).xlsx";
// 設(shè)置文件的打開方式和mime類型
ServletOutputStream outputStream = response.getOutputStream();
response.setHeader( "Content-Disposition", "attachment;filename=" + new String(filename.getBytes(),"ISO8859-1"));
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
workbook.write(outputStream);
}3、注解方式導(dǎo)入
有導(dǎo)出就應(yīng)該有導(dǎo)入,Excel導(dǎo)入時需要的參數(shù)類ImportParams常用設(shè)置說明
- 讀取指定的sheet 比如要讀取上傳得第二個sheet 那么需要把startSheetIndex = 1 就可以了
- 讀取幾個sheet 比如讀取前2個sheet,那么 sheetNum=2 就可以了
- 讀取第二個到第五個sheet 設(shè)置 startSheetIndex = 1 然后sheetNum = 4
- 讀取全部的sheet sheetNum 設(shè)置大點(diǎn)就可以了
- 保存Excel 設(shè)置 needVerfiy = true,默認(rèn)保存的路徑為upload/excelUpload/Test/yyyyMMddHHmss 保存名稱上傳時間五位隨機(jī)數(shù) 如果自定義路徑 修改下saveUrl 就可以了,同時saveUrl也是圖片上傳時候的保存的路徑
- 判斷一個Excel是不是合法的Excel importFields 設(shè)置下值,就是表示表頭必須至少包含的字段,如果缺一個就是不合法的excel,不導(dǎo)入
- 圖片的導(dǎo)入
有圖片的導(dǎo)出就有圖片的導(dǎo)入,導(dǎo)入的配置和導(dǎo)出是一樣的,但是需要設(shè)置保存路徑 1.設(shè)置保存路徑saveUrl 默認(rèn)為"upload/excelUpload" 可以手動修改 ImportParams 修改下就可以了
3.1.修改實(shí)體類,表明哪些需要導(dǎo)入
package com.tigerhhzz.pojo;
import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.annotation.ExcelCollection;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.util.Date;
import java.util.List;
/**
* 員工
* @author Administrator
*/
@Data
@TableName(value="tb_user")
public class User {
@TableId(value = "id",type = IdType.AUTO)
@Excel(name = "編號", orderNum = "0", width = 5)
private Long id; //主鍵
@Excel(name = "員工名", orderNum = "1", width = 15,isImportField="true")
private String userName; //員工名
@Excel(name = "手機(jī)號", orderNum = "2", width = 15,isImportField="true")
private String phone; //手機(jī)號
@Excel(name = "省份名", orderNum = "3", width = 15,isImportField="true")
private String province; //省份名
@Excel(name = "城市名", orderNum = "4", width = 15,isImportField="true")
private String city; //城市名
@Excel(name = "工資", orderNum = "5", width = 10,type = 10,isImportField="true") //type=10表示會導(dǎo)出數(shù)字
private Integer salary; // 工資
@JsonFormat(pattern="yyyy-MM-dd")
@Excel(name = "入職日期", format = "yyyy-MM-dd",orderNum = "6", width = 15,isImportField="true")
private Date hireDate; // 入職日期
private String deptId; //部門id
@Excel(name = "出生日期", format = "yyyy-MM-dd",orderNum = "7", width = 15,isImportField="true")
private Date birthday; //出生日期
@Excel(name = "照片", orderNum = "10",width = 15,type = 2,isImportField="true",savePath = "F:\\idea-project\\easypoi-demo\\src\\main\\resources\\static\\user_photos")
private String photo; //一寸照片
@Excel(name = "現(xiàn)在居住地址", orderNum = "9", width = 30,isImportField="true")
private String address; //現(xiàn)在居住地址
//映射一對多關(guān)系
@TableField(exist = false) //非數(shù)據(jù)庫字段
@ExcelCollection(name = "資源列表", orderNum = "5")
private List<Resource> resourceList; //辦公用品
public List<Resource> getResources() {
return resourceList;
}
public void setResources(List<Resource> resources) {
this.resourceList = resources;
}
}3.2. UserController添加方法
@PostMapping(value = "/uploadExcelbyEasyPoi", name = "上傳用戶數(shù)據(jù)byEasyPoi")
public void uploadExcelbyEasyPoi(MultipartFile file) throws Exception{
userService.uploadExcelbyEasyPoi(file);
}
3.3. UserService實(shí)現(xiàn)方法
void uploadExcelbyEasyPoi(MultipartFile file) throws Exception;
3.4. 實(shí)現(xiàn)類
@Override
public void uploadExcelbyEasyPoi(MultipartFile file) throws Exception {
ImportParams importParams = new ImportParams();
importParams.setTitleRows(1); //有多少行的標(biāo)題
importParams.setHeadRows(2);//有多少行的頭
List<User> userList = ExcelImportUtil.importExcel(file.getInputStream(),User.class,importParams);
System.out.println(userList);
for (User user : userList) {
user.setId(null);
userMapper.insert(user);
}
}4、模板方式導(dǎo)出數(shù)據(jù)
模板是處理復(fù)雜Excel的簡單方法,復(fù)雜的Excel樣式,可以用Excel直接編輯,完美的避開了代碼編寫樣式的雷區(qū),同時指令的支持,也提了模板的有效性。
采用的寫法是{{}}代表表達(dá)式,然后根據(jù)表達(dá)式里面的數(shù)據(jù)取值
- 關(guān)于樣式問題
easypoi不會改變excel原有的樣式
- 需求:導(dǎo)出用戶的詳細(xì)信息,這個功能我們做過,今天我們使用easyPOI的方式再做一次
- 制作模板
這個模板和我們做的userInfo2.xlsx模板一樣,只是這個變量使用了{(lán){}}包起來了

- 第二步:放到項目中

- 第三步:改寫UserController中導(dǎo)出用戶信息的方法
@GetMapping(value = "/downLoadUserInfoWithEastPOI",name = "導(dǎo)出用戶詳細(xì)信息-使用EasyPoi")
public void downLoadUserInfoWithEastPOI(Long id,HttpServletRequest request,HttpServletResponse response) throws Exception{
userService.downLoadUserInfoWithEastPOI(id,request,response);
}- 第四步:完成UserService中的方法
void downLoadUserInfoWithEastPOI(Long id, HttpServletRequest request, HttpServletResponse response) throws Exception;
- 第五步:實(shí)現(xiàn)類方法
@Override
public void downLoadUserInfoWithEastPOI(Long id, HttpServletRequest request, HttpServletResponse response) throws Exception {
// 獲取模板的路徑
File rootPath = new File(ResourceUtils.getURL("classpath:").getPath()); //SpringBoot項目獲取根目錄的方式
File templatePath = new File(rootPath.getAbsolutePath(),"/excel_template/userInfoEasyPoi.xlsx");
// 讀取模板文件
TemplateExportParams params = new TemplateExportParams(templatePath.getPath(),true);
// 查詢用戶,轉(zhuǎn)成map
User user = userMapper.selectById(id);
Map<String, Object> map = EntityUtils.entityToMap(user);
ImageEntity userImage = new ImageEntity();
userImage.setType(ImageEntity.URL); // 設(shè)置類型為URL
// userImage.setHeight(64); //測試發(fā)現(xiàn) 這里設(shè)置了長度和寬度在合并后的單元格中沒有作用
// userImage.setWidth(380);
userImage.setRowspan(5);//向下合并三行
userImage.setColspan(3);//向右合并兩列
// userImage.setData(ImageConverter.jpgToBytes(rootPath+user.getPhoto()));
userImage.setUrl(user.getPhoto());
map.put("photo", userImage);
Workbook workbook = ExcelExportUtil.exportExcel(params, map);
// 導(dǎo)出的文件名稱
String filename="用戶詳細(xì)信息數(shù)據(jù).xlsx";
// 設(shè)置文件的打開方式和mime類型
ServletOutputStream outputStream = response.getOutputStream();
response.setHeader( "Content-Disposition", "attachment;filename=" + new String(filename.getBytes(),"ISO8859-1"));
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
workbook.write(outputStream);
}5、導(dǎo)出CSV
csv的導(dǎo)出基本上和excel的導(dǎo)出一致,大體參數(shù)也是一致的
CsvExportParams 的參數(shù)描述如下:
| 屬性 | 類型 | 默認(rèn)值 | 功能 |
|---|---|---|---|
| encoding | String | UTF8 | 文件編碼 |
| spiltMark | String | , | 分隔符 |
| textMark | String | “ | 字符串識別,可以去掉,需要前后一致 |
| titleRows | int | 0 | 表格頭,忽略 |
| headRows | int | 1 | 標(biāo)題 |
| exclusions | String[] | 0 | 忽略的字段 |
需求:改寫之前使用OpenCSV導(dǎo)出csv文件
第一步:修改UserController方法
@GetMapping(value = "/downLoadCSV",name = "導(dǎo)出用戶數(shù)據(jù)到CSV文件中")
public void downLoadCSV(HttpServletResponse response) throws Exception{
// userService.downLoadCSV(response);
userService.downLoadCSVWithEasyPOI(response);
}第二步:完成UserService方法
public void downLoadCSVWithEasyPOI(HttpServletResponse response) throws Exception {
ServletOutputStream outputStream = response.getOutputStream();
// 文件名
String filename="百萬數(shù)據(jù).csv";
// 設(shè)置兩個頭 一個是文件的打開方式 一個是mime類型
response.setHeader( "Content-Disposition", "attachment;filename=" + new String(filename.getBytes(),"ISO8859-1"));
response.setContentType("application/csv");
// 創(chuàng)建一個用來寫入到csv文件中的writer
CsvExportParams params = new CsvExportParams();
// 設(shè)置忽略的列
params.setExclusions(new String[]{"照片"}); //這里寫表頭 中文
List<User> list = userMapper.selectAll();
CsvExportUtil.exportCsv(params, User.class, list, outputStream);
}說明:從上述的代碼中你會發(fā)現(xiàn),如果需要導(dǎo)出幾百萬數(shù)據(jù)時不可能全部加載到一個List中的,所以easyPOI的方式導(dǎo)出csv是支持不了太大的數(shù)據(jù)量的,如果導(dǎo)出幾百萬條數(shù)據(jù)還是得選擇OpenCSV方式導(dǎo)出。
到此這篇關(guān)于Springboot項目中使用EasyPOI操作Excel(詳細(xì)教程系列4/4)的文章就介紹到這了,更多相關(guān)Springboot使用EasyPOI操作Excel內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot+EasyPOI實(shí)現(xiàn)百萬級數(shù)據(jù)導(dǎo)出Excel實(shí)戰(zhàn)指南
- SpringBoot整合EasyPoi實(shí)現(xiàn)復(fù)雜多級表頭Excel導(dǎo)出的完整方案
- SpringBoot集成EasyPoi實(shí)現(xiàn)Excel模板導(dǎo)出成PDF文件
- SpringBoot+EasyPOI輕松實(shí)現(xiàn)Excel和Word導(dǎo)出PDF
- SpringBoot+EasyPoi實(shí)現(xiàn)excel導(dǎo)出功能
- SpringBoot+easypoi實(shí)現(xiàn)數(shù)據(jù)的Excel導(dǎo)出
相關(guān)文章
解決idea2020 maven無法自動導(dǎo)包的問題
這篇文章主要介紹了解決idea2020 maven無法自動導(dǎo)包的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-02-02
Spring Boot項目如何使用外部application.yml配置文件啟動JAR包
文章介紹了SpringBoot項目通過指定外部application.yml配置文件啟動JAR包的方法,包括設(shè)置spring.config.location參數(shù)、打包注意事項及路徑格式要求,強(qiáng)調(diào)外部配置優(yōu)先級和覆蓋機(jī)制,提供Linux/Windows啟動示例,需要的朋友跟隨小編一起學(xué)習(xí)吧2025-08-08
老生常談Java中instanceof關(guān)鍵字的理解
java 中的instanceof 運(yùn)算符是用來在運(yùn)行時指出對象是否是特定類的一個實(shí)例。這篇文章主要介紹了老生常談Java中instanceof關(guān)鍵字的理解,需要的朋友可以參考下2018-10-10
Java8如何利用Lambda快速生成map、多層嵌套map
這篇文章主要介紹了Java8如何利用Lambda快速生成map、多層嵌套map問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-09-09
SpringMVC獲取請求參數(shù)和域?qū)ο蠊蚕頂?shù)據(jù)的示例代碼
這篇文章主要給大家介紹了SpringMVC獲取請求參數(shù)和域?qū)ο蠊蚕頂?shù)據(jù)的示例代碼,文中通過代碼示例給大家介紹的非常詳細(xì),具有一定的參考價值,需要的朋友可以參考下2023-12-12
基于JVM 調(diào)優(yōu)的技巧總結(jié)分析
本篇文章是對JVM 調(diào)優(yōu)的技巧進(jìn)行了總結(jié)和分析。需要的朋友參考下2013-05-05
Java中實(shí)現(xiàn)在一個方法中調(diào)用另一個方法
下面小編就為大家分享一篇Java中實(shí)現(xiàn)在一個方法中調(diào)用另一個方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-02-02
SpringBoot實(shí)現(xiàn)微信支付接口調(diào)用及回調(diào)函數(shù)(商戶參數(shù)獲取)
本文詳細(xì)介紹了使用SpringBoot實(shí)現(xiàn)微信支付接口調(diào)用及回調(diào)函數(shù)的步驟,提供了代碼實(shí)現(xiàn)的具體步驟和工具類的創(chuàng)建,感興趣的朋友跟隨小編一起看看吧2024-11-11

