EasyPOI 教程以及完整工具類的使用
因為專案的原因需要用到POI來操作Excel 文件,以前都是直接使用POI來操作的,但是最近聽到easypoi的存在,所以自己簡單的嘗試了下! 別說,他還真的挺好用的
Easypoi介紹
Easypoi 為誰而開發
- 不太熟悉poi的
- 不想寫太多重複太多的
- 只是簡單的匯入匯出的
- 喜歡使用模板的
都可以使用easypoi
Easypoi的目標是什麼 Easypoi的目標不是替代poi,而是讓一個不懂匯入匯出的快速使用poi完成Excel和word的各種操作,而不是看很多api才可以完成這樣工作
為什麼會寫Easypoi
以前的以前(歲月真TMD的快)我雖然寫了不少程式碼但還是很少寫poi,然後跳到一家公司之後就和業務人員聊上了,來這個需要個報表,這個報表樣式是這樣的,這個表頭是這樣的,就這樣我寫了大量的poi程式碼,每次都是大量的篇幅,copy to copy,無聊的一逼,然後加入了jeecg,jeecg中有一個小的工具類,雖然我也不知道是誰寫的,然是可以用註解搞定最簡單的匯出,突然豁然開朗,我可以完善,讓我從報表的苦海當中脫離出來,這樣我花了一週的時間做了第一個版本支援匯入匯出放到了jeecg,發現還是不錯的,慢慢的用的人越來越多,我就把這塊獨立出來了,再然後有人提出了模板,然後就加入了模板功能,提出了word的需求,加入了word的功能,後來工作忙了雖然沒再參與jeecg,但還是一直維持這easypoi的更新,根據見識的增長也不斷的重構這程式碼,直到現在
獨特的功能
- 基於註解的匯入匯出,修改註解就可以修改Excel
- 支援常用的樣式自定義
- 基於map可以靈活定義的表頭欄位
- 支援一堆多的匯出,匯入
- 支援模板的匯出,一些常見的標籤,自定義標籤
- 支援HTML/Excel轉換,如果模板還不能滿足使用者的變態需求,請用這個功能
- 支援word的匯出,支援圖片,Excel
使用
- 1.easypoi 父包--作用大家都懂得
- 2.easypoi-annotation 基礎註解包,作用與實體物件上,拆分後方便maven多工程的依賴管理
- 3.easypoi-base 匯入匯出的工具包,可以完成Excel匯出,匯入,Word的匯出,Excel的匯出功能
- 4.easypoi-web 耦合了spring-mvc 基於AbstractView,極大的簡化spring-mvc下的匯出功能
- 5.sax 匯入使用xercesImpl這個包(這個包可能造成奇怪的問題哈),word匯出使用poi-scratchpad,都作為可選包了
如果不使用spring mvc的便捷福利,直接引入easypoi-base 就可以了,easypoi-annotation
如果使用maven,請使用如下座標
<dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-base</artifactId> <version>3.1.0</version> </dependency> <dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-web</artifactId> <version>3.1.0</version> </dependency> <dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-annotation</artifactId> <version>3.1.0</version> </dependency>
註解
註解介紹
easypoi起因就是Excel的匯入匯出,最初的模板是實體和Excel的對應,model--row,filed--col 這樣利用註解我們可以和容易做到excel到匯入匯出 經過一段時間發展,現在註解有5個類分別是
- @Excel 作用到filed上面,是對Excel一列的一個描述
- @ExcelCollection 表示一個集合,主要針對一對多的匯出,比如一個老師對應多個科目,科目就可以用集合表示
- @ExcelEntity 表示一個繼續深入匯出的實體,但他沒有太多的實際意義,只是告訴系統這個物件裡面同樣有匯出的欄位
- @ExcelIgnore 和名字一樣表示這個欄位被忽略跳過這個導匯出
- @ExcelTarget 這個是作用於最外層的物件,描述這個物件的id,以便支援一個物件可以針對不同匯出做出不同處理
@Excel
這個是必須使用的註解,如果需求簡單隻使用這一個註解也是可以的,涵蓋了常用的Excel需求,需要大家熟悉這個功能,主要分為基礎,圖片處理,時間處理,合併處理幾塊,name_id是上面講的id用法,這裡就不累言了
屬性 | 型別 | 預設值 | 功能 |
---|---|---|---|
name |
String |
null |
列名,支援name_id |
needMerge |
boolean |
fasle |
是否需要縱向合併單元格(用於含有list中,單個的單元格,合併list建立的多個row) |
orderNum |
String |
"0" |
列的排序,支援name_id |
replace |
String[] |
{} |
值得替換 匯出是{a_id,b_id} 匯入反過來 |
savePath |
String |
"upload" |
匯入檔案儲存路徑,如果是圖片可以填寫,預設是upload/className/ IconEntity這個類對應的就是upload/Icon/ |
type |
int |
1 |
匯出型別 1 是文字 2 是圖片,3 是函式,10 是數字 預設是文字 |
width |
double |
10 |
列寬 |
height |
double |
10 |
列高,後期打算統一使用@ExcelTarget的height,這個會被廢棄,注意 |
isStatistics |
boolean |
fasle |
自動統計資料,在追加一行統計,把所有資料都和輸出 這個處理會吞沒異常,請注意這一點 |
isHyperlink |
boolean |
false |
超連結,如果是需要實現介面返回物件 |
isImportField |
boolean |
true |
校驗欄位,看看這個欄位是不是匯入的Excel中有,如果沒有說明是錯誤的Excel,讀取失敗,支援name_id |
exportFormat |
String |
"" |
匯出的時間格式,以這個是否為空來判斷是否需要格式化日期 |
importFormat |
String |
"" |
匯入的時間格式,以這個是否為空來判斷是否需要格式化日期 |
format |
String |
"" |
時間格式,相當於同時設定了exportFormat 和 importFormat |
databaseFormat |
String |
"yyyyMMddHHmmss" |
匯出時間設定,如果欄位是Date型別則不需要設定 資料庫如果是string 型別,這個需要設定這個資料庫格式,用以轉換時間格式輸出 |
numFormat |
String |
"" |
數字格式化,引數是Pattern,使用的物件是DecimalFormat |
imageType |
int |
1 |
匯出型別 1 從file讀取 2 是從資料庫中讀取 預設是檔案 同樣匯入也是一樣的 |
suffix |
String |
"" |
文字字尾,如% 90 變成90% |
isWrap |
boolean |
true |
是否換行 即支援\n |
mergeRely |
int[] |
{} |
合併單元格依賴關係,比如第二列合併是基於第一列 則{0}就可以了 |
mergeVertical |
boolean |
fasle |
縱向合併內容相同的單元格 |
fixedIndex |
int |
-1 |
對應excel的列,忽略名字 |
isColumnHidden |
boolean |
false |
匯出隱藏列 |
@ExcelTarget
限定一個到處實體的註解,以及一些通用設定,作用於最外面的實體
屬性 | 型別 | 預設值 | 功能 |
---|---|---|---|
value |
String |
null |
定義ID |
height |
double |
10 |
設定行高 |
fontSize |
short |
11 |
設定文字大小 |
@ExcelEntity
標記是不是匯出excel 標記為實體類,一遍是一個內部屬性類,標記是否繼續穿透,可以自定義內部id
屬性 | 型別 | 預設值 | 功能 |
---|---|---|---|
id |
String |
null |
定義ID |
@ExcelCollection
一對多的集合註解,用以標記集合是否被資料以及集合的整體排序
屬性 | 型別 | 預設值 | 功能 |
---|---|---|---|
id |
String |
null |
定義ID |
name |
String |
null |
定義集合列名,支援nanm_id |
orderNum |
int |
0 |
排序,支援name_id |
type |
Class<?> |
ArrayList.class |
匯入時建立物件使用 |
@ExcelIgnore
忽略這個屬性,多使用需迴圈引用中,無需多解釋吧^^
接下來就是實戰了:
首先是實體類:
接下來是工具類的編寫:
package com.example.easypoi.util;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
/**
* @Auther: lijiawei
* @Date: 2018/7/23 12:08
* @Description: Excle 檔案匯入匯出Util(easypoi)
*/
public class EasyPoiUtil {
/**
* 功能描述:複雜匯出Excel,包括檔名以及表名。建立表頭
*
* @author 李家威
* @date 2018/7/23 13:07
* @param list 匯出的實體類
* @param title 表頭名稱
* @param sheetName sheet表名
* @param pojoClass 對映的實體類
* @param isCreateHeader 是否建立表頭
* @param fileName
* @param response
* @return
*/
public static void exportExcel(List<?> list, String title, String sheetName, Class<?> pojoClass, String fileName, boolean isCreateHeader, HttpServletResponse response) {
ExportParams exportParams = new ExportParams(title, sheetName);
exportParams.setCreateHeadRows(isCreateHeader);
defaultExport(list, pojoClass, fileName, response, exportParams);
}
/**
* 功能描述:複雜匯出Excel,包括檔名以及表名,不建立表頭
*
* @author 李家威
* @date 2018/7/23 13:07
* @param list 匯出的實體類
* @param title 表頭名稱
* @param sheetName sheet表名
* @param pojoClass 對映的實體類
* @param fileName
* @param response
* @return
*/
public static void exportExcel(List<?> list, String title, String sheetName, Class<?> pojoClass, String fileName, HttpServletResponse response) {
defaultExport(list, pojoClass, fileName, response, new ExportParams(title, sheetName));
}
/**
* 功能描述:Map 集合匯出
*
* @author 李家威
* @date 2018/7/23 16:14
* @param list 實體集合
* @param fileName 匯出的檔名稱
* @param response
* @return
*/
public static void exportExcel(List<Map<String, Object>> list, String fileName, HttpServletResponse response) {
defaultExport(list, fileName, response);
}
/**
* 功能描述:預設匯出方法
*
* @author 李家威
* @date 2018/7/23 15:33
* @param list 匯出的實體集合
* @param fileName 匯出的檔名
* @param pojoClass pojo實體
* @param exportParams ExportParams封裝實體
* @param response
* @return
*/
private static void defaultExport(List<?> list, Class<?> pojoClass, String fileName, HttpServletResponse response, ExportParams exportParams) {
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, pojoClass, list);
if (workbook != null) {
downLoadExcel(fileName, response, workbook);
}
}
/**
* 功能描述:Excel匯出
*
* @author 李家威
* @date 2018/7/23 15:35
* @param fileName 檔名稱
* @param response
* @param workbook Excel物件
* @return
*/
private static void downLoadExcel(String fileName, HttpServletResponse response, Workbook workbook) {
try {
response.setCharacterEncoding("UTF-8");
response.setHeader("content-Type", "application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
workbook.write(response.getOutputStream());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 功能描述:預設匯出方法
*
* @author 李家威
* @date 2018/7/23 15:33
* @param list 匯出的實體集合
* @param fileName 匯出的檔名
* @param response
* @return
*/
private static void defaultExport(List<Map<String, Object>> list, String fileName, HttpServletResponse response) {
Workbook workbook = ExcelExportUtil.exportExcel(list, ExcelType.HSSF);
if (workbook != null) ;
downLoadExcel(fileName, response, workbook);
}
/**
* 功能描述:根據檔案路徑來匯入Excel
*
* @author 李家威
* @date 2018/7/23 14:17
* @param filePath 檔案路徑
* @param titleRows 表標題的行數
* @param headerRows 表頭行數
* @param pojoClass Excel實體類
* @return
*/
public static <T> List<T> importExcel(String filePath, Integer titleRows, Integer headerRows, Class<T> pojoClass) {
//判斷檔案是否存在
if (StringUtils.isBlank(filePath)) {
return null;
}
ImportParams params = new ImportParams();
params.setTitleRows(titleRows);
params.setHeadRows(headerRows);
List<T> list = null;
try {
list = ExcelImportUtil.importExcel(new File(filePath), pojoClass, params);
} catch (NoSuchElementException e) {
throw new RuntimeException("模板不能為空");
} catch (Exception e) {
e.printStackTrace();
}
return list;
}
/**
* 功能描述:根據接收的Excel檔案來匯入Excel,並封裝成實體類
*
* @author 李家威
* @date 2018/7/23 14:17
* @param file 上傳的檔案
* @param titleRows 表標題的行數
* @param headerRows 表頭行數
* @param pojoClass Excel實體類
* @return
*/
public static <T> List<T> importExcel(MultipartFile file, Integer titleRows, Integer headerRows, Class<T> pojoClass) {
if (file == null) {
return null;
}
ImportParams params = new ImportParams();
params.setTitleRows(titleRows);
params.setHeadRows(headerRows);
List<T> list = null;
try {
list = ExcelImportUtil.importExcel(file.getInputStream(), pojoClass, params);
} catch (NoSuchElementException e) {
throw new RuntimeException("excel檔案不能為空");
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
return list;
}
}
下面是測試類以及結果:
就此,easypoi 的工作就完成了 是不是很簡單