<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
在後端管理系統的開發中,經常有需要匯出當前表格資料的功能
,有些前端表格元件可以直接做到,但是不夠靈活。因為前端拿到的資料始終是經過處理的,如果想拿到原版資料,必須後端處理。如下圖:
除了使用Apache POI包,還有沒有其他的選擇?當然有! 這裡我給大家推薦一款非常簡單且容易上手的開源元件:Alibaba EasyExcel
首先放出官網地址,歡迎大家star(目前已經24K): https://alibaba-easyexcel.github.io/docs/current/
EasyExcel是一個基於Java的簡單、省記憶體的讀寫Excel的開源專案。在儘可能節約記憶體的情況下支援讀寫百M的Excel。
64M記憶體20秒讀取75M(46W行25列)的Excel(3.0.2+版本)
Alibaba EasyExcel的核心類是EasyExcel
類
/** * 最簡單的讀 * <p>1. 建立excel對應的實體物件 參照{@link DemoData} * <p>2. 由於預設一行行的讀取excel,所以需要建立excel一行一行的回撥監聽器,參照{@link DemoDataListener} * <p>3. 直接讀即可 */ @Test public void simpleRead() { String fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx"; // 這裡 需要指定讀用哪個class去讀,然後讀取第一個sheet 檔案流會自動關閉 EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).sheet().doRead(); }
/** * 最簡單的寫 * <p>1. 建立excel對應的實體物件 參照{@link com.alibaba.easyexcel.test.demo.write.DemoData} * <p>2. 直接寫即可 */ @Test public void simpleWrite() { String fileName = TestFileUtil.getPath() + "write" + System.currentTimeMillis() + ".xlsx"; // 這裡 需要指定寫用哪個class去讀,然後寫到第一個sheet,名字為模板 然後檔案流會自動關閉 // 如果這裡想使用03 則 傳入excelType引數即可 EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data()); }
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.1</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>SpringBoot-easyexcel</artifactId> <version>0.0.1-SNAPSHOT</version> <name>SpringBoot-easyexcel</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- 一般easyexcel都會和lombok搭配使用 --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.12</version> </dependency> <!-- 最新版 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>3.1.1</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
package com.example.springbooteasyexcel.controller; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.ExcelWriter; import com.alibaba.excel.write.metadata.WriteSheet; import com.example.springbooteasyexcel.data.Mock; import com.example.springbooteasyexcel.sheet.CitySheet; import com.example.springbooteasyexcel.sheet.CompanySheet; import com.example.springbooteasyexcel.sheet.UserSheet; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.net.URLEncoder; @RestController @RequestMapping("/export") public class ExportController { /** * @param response * @url <a>http://localhost:8080/export/test1</a> * 在Excel中寫入單個sheet */ @RequestMapping("/test1") public void test1(HttpServletResponse response) { //從HttpServletResponse中獲取OutputStream輸出流 try { // 設定響應型別 response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); // 設定編碼格式 response.setCharacterEncoding("utf-8"); // 設定URLEncoder.encode 防止中文亂碼 String fileName = URLEncoder.encode("使用者資訊表", "UTF-8").replaceAll("\+", "%20"); // 設定響應頭 response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx"); // 寫出Excel EasyExcel.write(response.getOutputStream(), UserSheet.class).inMemory(true).sheet("使用者資訊表").doWrite(Mock.userList()); } catch (IOException e) { throw new RuntimeException("資料或檔案損壞,無法下載"); } } /** * 在Excel中寫入多個sheet * * @url <a>http://localhost:8080/export/test2</a> */ @RequestMapping("/test2") public void test2(HttpServletResponse response) throws Exception { // 設定響應型別 response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); // 設定編碼格式 response.setCharacterEncoding("utf-8"); // 設定URLEncoder.encode 防止中文亂碼 String fileName = URLEncoder.encode("資訊表", "UTF-8").replaceAll("\+", "%20"); // 設定響應頭 response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx"); // 多個sheet的輸出需要使用ExcelWriter類,這裡想要下載成功,需要輸出到OutputStream中 try (ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).inMemory(true).build()) { // 建立使用者資訊表的sheet,寫入使用者資訊資料,1代表sheet的位置是第一個 WriteSheet userInfoSheet = EasyExcel.writerSheet(0, "使用者資訊表").head(UserSheet.class).build(); excelWriter.write(Mock.userList(), userInfoSheet); // 建立城市資訊表的sheet,寫入城市資訊資料,2代表sheet的位置是第二個 WriteSheet cityInfoSheet = EasyExcel.writerSheet(1, "城市資訊表").head(CitySheet.class).build(); excelWriter.write(Mock.cityList(), cityInfoSheet); // 建立公司資訊表的sheet,寫入公司資訊資料,3代表sheet的位置是第三個 WriteSheet companyInfoSheet = EasyExcel.writerSheet(2, "公司資訊表").head(CompanySheet.class).build(); excelWriter.write(Mock.companyList(), companyInfoSheet); } } }
以下資料均來自於網路,如有侵權,請聯絡刪除
package com.example.springbooteasyexcel.data; import com.alibaba.excel.enums.CellDataTypeEnum; import com.alibaba.excel.metadata.data.RichTextStringData; import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.write.metadata.style.WriteFont; import com.example.springbooteasyexcel.sheet.CitySheet; import com.example.springbooteasyexcel.sheet.CompanySheet; import com.example.springbooteasyexcel.sheet.UserSheet; import org.apache.poi.ss.usermodel.IndexedColors; import java.util.ArrayList; import java.util.Calendar; import java.util.List; public class Mock { public static List<UserSheet> userList() { List<UserSheet> list = new ArrayList<>(10); list.add(UserSheet.builder().userId(001L).userName("張三").userPhone("11112223123").userEmail("zhansan@163.com").userAddress("北京朝陽區").gender(buildCellData("男")).registerTime(Calendar.getInstance().getTime()).build()); list.add(UserSheet.builder().userId(002L).userName("李四").userPhone("11112223123").userEmail("lisi@qq.com").userAddress("南京玄武門").gender(buildCellData("女")).registerTime(Calendar.getInstance().getTime()).build()); list.add(UserSheet.builder().userId(003L).userName("王五").userPhone("11112223123").userEmail("wangwu@google.com").userAddress("杭州未來科技城").gender(buildCellData("男")).registerTime(Calendar.getInstance().getTime()).build()); list.add(UserSheet.builder().userId(004L).userName("趙六").userPhone("11112223123").userEmail("zhaoliu@baidu.com").userAddress("上海徐家彙").gender(buildCellData("女")).registerTime(Calendar.getInstance().getTime()).build()); return list; } private static WriteCellData<String> buildCellData(String gender) { // 設定單個單元格多種樣式 WriteCellData<String> cellData = new WriteCellData<>(); // 設定單個單元格的填充型別 cellData.setType(CellDataTypeEnum.RICH_TEXT_STRING); RichTextStringData richTextStringData = new RichTextStringData(); cellData.setRichTextStringDataValue(richTextStringData); richTextStringData.setTextString(gender); WriteFont writeFont = new WriteFont(); if ("男".equalsIgnoreCase(gender)) { //設定顏色為紅色 writeFont.setColor(IndexedColors.RED.getIndex()); } else if ("女".equalsIgnoreCase(gender)) { //設定顏色為綠色 writeFont.setColor(IndexedColors.GREEN.getIndex()); } //應用顏色字型 richTextStringData.applyFont(writeFont); return cellData; } public static List<CitySheet> cityList() { List<CitySheet> list = new ArrayList<>(10); list.add(CitySheet.builder().cityName("杭州市").cityDesc("杭州市一般指杭州。 杭州,簡稱「杭」,古稱臨安、錢塘,浙江省轄地級市、省會、副省級市、特大城市、國務院批覆確定的浙江省經濟、文化、科教中心,長江三角洲中心城市之一,環杭州灣大灣區核心城市、G60科創走廊中心城市。").build()); list.add(CitySheet.builder().cityName("合肥市").cityDesc("合肥市一般指合肥。 合肥,簡稱「廬」或「合」,古稱廬州、廬陽、合淝,安徽省轄地級市、省會,是合肥都市圈中心城市,國務院批覆確定的中國長三角城市群副中心城市,全國四大科教基地、現代製造業基地和綜合交通樞紐。").build()); list.add(CitySheet.builder().cityName("武漢市").cityDesc("武漢市一般指武漢。 武漢,簡稱「漢」,別稱江城,是湖北省省會,中部六省唯一的副省級市,超大城市,中國中部地區的中心城市,全國重要的工業基地、科教基地和綜合交通樞紐,聯勤保障部隊機關駐地。").build()); list.add(CitySheet.builder().cityName("深圳市").cityDesc("深圳市一般指深圳。 深圳,簡稱「深」,別稱鵬城,廣東省轄地級市,是廣東省副省級市,國家計劃單列市,超大城市,國務院批覆確定的中國經濟特區、全國性經濟中心城市、國際化城市、科技創新中心、區域金融中心、商貿物流中心。").build()); return list; } public static List<CompanySheet> companyList() { List<CompanySheet> list = new ArrayList<>(10); list.add(CompanySheet.builder().companyName("阿里巴巴").companyBoss("馬雲").companyBase("杭州市").companyDesc("阿里巴巴集團經營多項業務,另外也從關聯公司的業務和服務中取得經營商業生態系統上的支援。業務和關聯公司的業務包括:淘寶網、天貓、聚划算、全球速賣通、阿里巴巴國際交易市場、1688、阿里媽媽、阿里雲、螞蟻集團 [408] 、菜鳥網路等。").build()); list.add(CompanySheet.builder().companyName("位元組跳動").companyBoss("張一鳴").companyBase("北京市").companyDesc("位元組跳動的全球化佈局始於2015年 [3] ,「技術出海」是位元組跳動全球化發展的核心戰略 [4] ,其旗下產品有今日頭條、西瓜視訊、抖音、頭條百科、皮皮蝦、懂車帝、悟空問答等。").build()); list.add(CompanySheet.builder().companyName("騰訊").companyBoss("馬化騰").companyBase("深圳市").companyDesc("社交和通訊服務QQ及微信/WeChat、社群網路平臺QQ空間、騰訊遊戲旗下QQ遊戲平臺、入口網站騰訊網、騰訊新聞使用者端和網路視訊服務騰訊視訊等。").build()); list.add(CompanySheet.builder().companyName("百度").companyBoss("李彥宏").companyBase("北京市").companyDesc("百度(Baidu)是擁有強大網際網路基礎的領先AI公司。百度願景是:成為最懂使用者,並能幫助人們成長的全球頂級高科技公司。").build()); return list; } }
package com.example.springbooteasyexcel.sheet; import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.write.style.ColumnWidth; import lombok.Builder; import lombok.Data; @Data @Builder public class CitySheet { @ExcelProperty(value = "城市名稱", index = 0) @ColumnWidth(10) private String cityName; @ExcelProperty(value = "城市介紹", index = 1) @ColumnWidth(60) private String cityDesc; }
package com.example.springbooteasyexcel.sheet; import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.write.style.ColumnWidth; import lombok.Builder; import lombok.Data; @Data @Builder public class CompanySheet { @ExcelProperty(value = "公司名稱", index = 0) @ColumnWidth(10) private String companyName; @ExcelProperty(value = "公司創始人", index = 1) @ColumnWidth(10) private String companyBoss; @ExcelProperty(value = "公司總基地", index = 2) @ColumnWidth(10) private String companyBase; @ExcelProperty(value = "公司簡介", index = 3) @ColumnWidth(50) private String companyDesc; }
package com.example.springbooteasyexcel.sheet; import com.alibaba.excel.annotation.ExcelIgnore; import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.write.style.ColumnWidth; import com.alibaba.excel.metadata.data.WriteCellData; import lombok.Builder; import lombok.Data; import java.util.Date; @Data @Builder public class UserSheet { @ExcelProperty(value = "使用者ID", index = 0) @ColumnWidth(10) private Long userId; @ExcelProperty(value = "使用者名稱稱", index = 1) @ColumnWidth(10) private String userName; @ExcelProperty(value = {"基本資訊", "手機號碼"}, index = 2) @ColumnWidth(20) private String userPhone; @ExcelProperty(value = {"基本資訊", "電子郵箱"}, index = 3) @ColumnWidth(20) private String userEmail; @ExcelProperty(value = {"基本資訊", "地址"}, index = 4) @ColumnWidth(20) private String userAddress; @ExcelProperty(value = "註冊時間", index = 5) @ColumnWidth(20) private Date registerTime; @ExcelProperty(value = "性別,男:紅色/女:綠色") @ColumnWidth(30) private WriteCellData<String> gender; /** * 忽略這個欄位 */ @ExcelIgnore private Integer age; }
package com.example.springbooteasyexcel; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class SpringBootEasyexcelApplication { public static void main(String[] args) { SpringApplication.run(SpringBootEasyexcelApplication.class, args); } }
@ExcelProperty
、@ColumnWidth
、@ExcelIgnore
。 (1)@ExcelProperty
不僅確定表頭,還可以合併行,用法如下:@ExcelProperty(value = {"基本資訊", "手機號碼"}, index = 2) @ColumnWidth(20) private String userPhone; @ExcelProperty(value = {"基本資訊", "電子郵箱"}, index = 3) @ColumnWidth(20) private String userEmail; @ExcelProperty(value = {"基本資訊", "地址"}, index = 4) @ColumnWidth(20) private String userAddress;
效果如下:
@ColumnWidth
主要是控制列寬@ExcelIgnore
忽略不需要輸出的欄位 3、寫有兩種形式 (1)寫到檔案/** * 最簡單的寫 * <p> * 1. 建立excel對應的實體物件 參照{@link DemoData} * <p> * 2. 直接寫即可 */ @Test public void simpleWrite() { // 注意 simpleWrite在資料量不大的情況下可以使用(5000以內,具體也要看實際情況),資料量大參照 重複多次寫入 // 寫法1 JDK8+ // since: 3.0.0-beta1 String fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx"; // 這裡 需要指定寫用哪個class去寫,然後寫到第一個sheet,名字為模板 然後檔案流會自動關閉 // 如果這裡想使用03 則 傳入excelType引數即可 EasyExcel.write(fileName, DemoData.class) .sheet("模板") .doWrite(() -> { // 分頁查詢資料 return data(); }); // 寫法2 fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx"; // 這裡 需要指定寫用哪個class去寫,然後寫到第一個sheet,名字為模板 然後檔案流會自動關閉 // 如果這裡想使用03 則 傳入excelType引數即可 EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data()); // 寫法3 fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx"; // 這裡 需要指定寫用哪個class去寫 try (ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).build()) { WriteSheet writeSheet = EasyExcel.writerSheet("模板").build(); excelWriter.write(data(), writeSheet); } }
(2)寫到Web流,這裡的ContentType和CharacterEncoding不要亂碼,否則很容易亂碼或者檔案損壞
/** * 檔案下載(失敗了會返回一個有部分資料的Excel) * <p> * 1. 建立excel對應的實體物件 參照{@link DownloadData} * <p> * 2. 設定返回的 引數 * <p> * 3. 直接寫,這裡注意,finish的時候會自動關閉OutputStream,當然你外面再關閉流問題不大 */ @GetMapping("download") public void download(HttpServletResponse response) throws IOException { // 這裡注意 有同學反應使用swagger 會導致各種問題,請直接用瀏覽器或者用postman response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setCharacterEncoding("utf-8"); // 這裡URLEncoder.encode可以防止中文亂碼 當然和easyexcel沒有關係 String fileName = URLEncoder.encode("測試", "UTF-8").replaceAll("\+", "%20"); response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx"); EasyExcel.write(response.getOutputStream(), DownloadData.class).sheet("模板").doWrite(data()); }
到此這篇關於SpringBoot整合EasyExcel實現Excel表格匯出功能的文章就介紹到這了,更多相關SpringBoot整合EasyExcel內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45