有天上飛的概念,就要有落地的實現java
概念十遍不如代碼一遍,朋友,但願你把文中全部的代碼案例都敲一遍web
先贊後看,養成習慣面試
SpringBoot 圖文教程系列文章目錄數據庫
上一篇文章中簡單介紹了Poi的使用方式,可是用Poi去寫代碼着實繁瑣了一些,假如你要實現的是複雜的需求,譬如:圖片導出,多表數據導出,模板導出,大數據量導出等等,用最原生的Poi就不是很好的選擇了。api
難道要本身封裝工具類了嗎?bash
no no 輪子雖好,最好是別人寫好的。因此從這篇文章開始介紹兩個優秀的Poi工具 Easypoi 和 阿里開源的 EasyExcel。網絡
EasyPoi 是對poi封裝的一個工具庫,封裝好了一些常見的Excel操做app
接下來咱們一塊兒來將以上的功能實現出來xss
最基本的導入導出,要導出的數據的實體類以下:
public class Teacher {
/**
* 老師的主鍵
*/
private Integer teacherId;
/**
* 名字
*/
private String teacherName;
/**
* 頭像圖片地址
*/
private String teacherImage;
/**
* 老師的狀態 0表明正常 1表明刪除
*/
private Integer teacherStatus;
}
複製代碼省略get set
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-base</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-web</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-annotation</artifactId>
<version>3.2.0</version>
</dependency>
複製代碼
咱們要導出的數據的實體類是Teacher 因此須要給Teacher加 Easypoi的註解
EasyPoi是註解式開發,全部的註解詳情見官方文檔,可是若是要完成的需求是最簡單的導入導出的話,@Excel
一個註解就足夠了。
@Excel
這個是必須使用的註解,若是需求簡單隻使用這一個註解也是能夠的,涵蓋了經常使用的Excel需求,須要你們熟悉這個功能,主要分爲基礎,圖片處理,時間處理,合併處理幾塊
@Excel 的官方api easypoi.mydoc.io/#text_18690…
添加好註解的實體類以下:
EasyPoi 是註解式開發,對Excel全部的定義,樣式也好,日期格式化也好,都是在實體類的註解中定義
/**
* easypoi導出
*/
@Test
public void test4() throws IOException {
// 模擬數據
List<Teacher> list = new ArrayList<>();
list.add(new Teacher(1,"李老師","hhh.jpg",1));
list.add(new Teacher(2,"李老師","hhh.jpg",1));
list.add(new Teacher(3,"李老師","hhh.jpg",1));
list.add(new Teacher(4,"李老師","hhh.jpg",1));
list.add(new Teacher(5,"李老師","hhh.jpg",1));
list.add(new Teacher(6,"李老師","hhh.jpg",1));
/**
* 導出參數對象
* 參數1 標題
* 參數2 表的名字
*/
ExportParams exportParams = new ExportParams("全部老師數據","teacher");
/**
* exportExcel 導出Excel文件
* 參數1 導出參數對象
* 參數2 要導出的實體類的類對象
* 參數3 要導出的數據 須要一個集合 數據庫查詢出來的老師對象的集合
*
* 返回值就是封裝好的文件對象
*/
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, Teacher.class, list);
workbook.write(new FileOutputStream("/Users/lubingyang/Desktop/teachers.xls"));
}
複製代碼
導出以後的Excel以下:
關於導入 沒有須要單獨定義的配置 只要可以導出就可以直接寫導入的代碼
/**
* easypoi導入
*/
@Test
public void test5() throws Exception {
FileInputStream inputStream = new FileInputStream("/Users/lubingyang/Desktop/teachers.xls");
/**
* ImportParams 導入參數對象
* 定義標題欄和表頭數據
*/
ImportParams importParams = new ImportParams();
importParams.setTitleRows(1);
importParams.setHeadRows(1);
/**
* importExcel 導入方法
* 參數1 流 讀取要導入的文件
* 參數2 要導入的實體類的類對象 上師對象的類對象
* 參數3 導入參數對象
*
* 返回值 導入數據 直接封裝爲集合對象
*/
List<Teacher> teachers = ExcelImportUtil.importExcel(inputStream, Teacher.class, importParams);
for (Teacher teacher : teachers) {
System.out.println(teacher);
}
}
複製代碼
經過官方文檔很容易找到以下內容
![]()
根據文檔修改實體類
執行導出代碼 能夠獲得以下效果
修改實體類
修改完以後能夠直接導出
根據測試,若是圖片地址字段存儲的是相對路徑,最好處理爲網絡絕對絕對路徑或者本地絕對路徑
在實體類的註解上須要設置圖片導入以後的保存路徑
api
![]()
在增長一個實體類 Student ,在Teacher類中有一個學生集合,導出Teacher的同時須要將Student的數據也導出,對應的數據庫操做通常都是連表查詢,那麼這樣的數據怎麼導出到Excel呢?
針對 Teacher 類集合屬性的導入導出,須要給該屬性加註解 @ExcelConllection
官方文檔地址:easypoi.mydoc.io/#text_19784…
@Test
public void test4() throws IOException {
List<Student> students = new ArrayList<>();
students.add(new Student("hh","男"));
students.add(new Student("hh","男"));
// 模擬數據
List<Teacher> list = new ArrayList<>();
list.add(new Teacher(1,"李老師","/Users/lubingyang/Desktop/hhh.jpg",1,students));
list.add(new Teacher(6,"李老師","/Users/lubingyang/Desktop/hhh.jpg",1,students));
/**
* 導出參數對象
* 參數1 標題
* 參數2 表的名字
*/
ExportParams exportParams = new ExportParams("全部老師數據","teacher");
/**
* exportExcel 導出Excel文件
* 參數1 導出參數對象
* 參數2 要導出的實體類的類對象
* 參數3 要導出的數據 須要一個集合 數據庫查詢出來的老師對象的集合
*
* 返回值就是封裝好的文件對象
*/
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, Teacher.class, list);
workbook.write(new FileOutputStream("/Users/lubingyang/Desktop/teachers.xls"));
}
複製代碼
效果以下
關於百萬數據導出 推薦使用 阿里開源的 EasyExcel 官方介紹能夠將內存控制在kb
大數據導出是當咱們的導出數量在幾萬,到上百萬的數據時,一次從數據庫查詢這麼多數據加載到內存,而後寫入會對咱們的內存和CPU都產生壓力,這個時候須要咱們像分頁同樣處理導出,分段寫入Excel緩解壓力
EasyPoi提供的是兩個方法 強制使用 xssf版本的Excel
/**
* @param entity
* 表格標題屬性
* @param pojoClass
* Excel對象Class
* @param dataSet
* Excel對象數據List
*/
public static Workbook exportBigExcel(ExportParams entity, Class<?> pojoClass,
Collection<?> dataSet) {
ExcelBatchExportServer batachServer = ExcelBatchExportServer
.getExcelBatchExportServer(entity, pojoClass);
return batachServer.appendData(dataSet);
}
public static void closeExportBigExcel() {
ExcelBatchExportServer batachServer = ExcelBatchExportServer.getExcelBatchExportServer(null,
null);
batachServer.closeExportBigExcel();
}
複製代碼
思路
- 分頁讀取數據
- 將每次讀取到的數據寫入Excel
準備一個百萬數據的用戶表
![]()
@Test
public void test10() throws IOException {
Date start = new Date();
// 查詢數據庫 用戶表總條數
Integer userCount = userDao.selectCount(null);
// 計算總頁數
Integer pageCount = userCount / 200000 + 1;
List<CmfzUser> users = null;
Workbook workbook = null;
ExportParams params = new ExportParams("大數據測試", "測試");
// 查詢測試 頁數 每次查詢20w條數據
for (int i = 1; i <= pageCount; i++) {
System.out.println(i);
users = userDao.selectPage(new Page<>(i, 200000), null).getRecords();
// 經過 EasyPoi 的大數據導出方法 導出
workbook = ExcelExportUtil.exportBigExcel(params, CmfzUser.class, users);
users.clear();
}
Date end = new Date();
System.out.println(new Date().getTime() - start.getTime());
workbook.write(new FileOutputStream("/Users/lubingyang/Desktop/hhhh.xlsx"));
}
複製代碼
執行的總時間爲:
Tips:
- 時間問題沒作詳細的性能測試 官方有相關的測試:easypoi.mydoc.io/#text_20298…
- 數據庫查詢使用MybatisPlus 若是有興趣 能夠看個人相關文章 SpringBoot 集成 MybatisPlus
- 百萬數據用 xssf 不如使用 CSV 和 SXSSF( POI針對大數據量的導出,專門提供了一個類)
模板是處理複雜Excel的簡單方法,複雜的Excel樣式,能夠用Excel直接編輯,完美的避開了代碼編寫樣式的雷區,同時指令的支持,也提了模板的有效性。
EasyPoi支持的指令以及做用
空格分割
三目運算 {{test ? obj:obj2}}
n: 表示 這個cell是數值類型 {{n:}}
le: 表明長度{{le:()}} 在if/else 運用{{le:() > 8 ? obj1 : obj2}}
fd: 格式化時間 {{fd:(obj;yyyy-MM-dd)}}
fn: 格式化數字 {{fn:(obj;###.00)}}
fe: 遍歷數據,建立row
!fe: 遍歷數據不建立row
$fe: 下移插入,把當前行,下面的行所有下移.size()行,而後插入
#fe: 橫向遍歷
v_fe: 橫向遍歷值
!if: 刪除當前列 {{!if:(test)}}
單引號表示常量值 '' 好比'1' 那麼輸出的就是 1
&NULL& 空格
]] 換行符 多行遍歷導出
sum: 統計數據
複製代碼
採用的寫法是{{}}表明表達式,而後根據表達式裏面的數據取值
示例代碼所用模板文件地址:
![]()
@Test
public void fe_map() throws Exception {
// 讀取模板文件
TemplateExportParams params = new TemplateExportParams(
"/Users/k/Desktop/專項支出用款申請書_map.xls");
// 模擬要寫入模板的數據
Map<String, Object> map = new HashMap<String, Object>();
map.put("date", "2014-12-25");
map.put("money", 2000000.00);
map.put("upperMoney", "貳佰萬");
map.put("company", "執筆潛行科技有限公司");
map.put("bureau", "財政局");
map.put("person", "JueYue");
map.put("phone", "1879740****");
List<Map<String, String>> listMap = new ArrayList<Map<String, String>>();
for (int i = 0; i < 4; i++) {
Map<String, String> lm = new HashMap<String, String>();
lm.put("id", i + 1 + "");
lm.put("zijin", i * 10000 + "");
lm.put("bianma", "A001");
lm.put("mingcheng", "設計");
lm.put("xiangmumingcheng", "EasyPoi " + i + "期");
lm.put("quancheng", "開源項目");
lm.put("sqje", i * 10000 + "");
lm.put("hdje", i * 10000 + "");
listMap.add(lm);
}
map.put("maplist", listMap);
// 導出模板
Workbook workbook = ExcelExportUtil.exportExcel(params, map);
FileOutputStream fos = new FileOutputStream("/Users/k/Desktop/專項支出用款申請書111_map.xls");
workbook.write(fos);
fos.close();
}
複製代碼
結果以下
Tips:經過EasyPoi 基本上已經能夠完成全部的Excel相關的工做
能夠關注相關文章 poi 和 EasyExcel 以及 Poi中文 API 文檔 「40種操做 Excel文件的姿式」
恭喜你完成了本章的學習,爲你鼓掌!若是本文對你有幫助,請幫忙點贊,評論,轉發,這對做者很重要,謝謝。
讓咱們再次回顧本文的學習目標
- 掌握SpringBoot中Easypoi的使用
要掌握SpringBoot更多的用法,請持續關注本系列教程。
歡迎關注本人公衆號:鹿老師的Java筆記,將在長期更新Java技術圖文教程和視頻教程,Java學習經驗,Java面試經驗以及Java實戰開發經驗。