5.3.EasyPOI導出
5.3.1.前言
easypoi功能如同名字easy,主打的功能就是容易,讓一個沒見接觸過poi的人員就可以方便的寫出Excel導出,Excel模板導出,Excel導入,Word模板導出,通過簡單的註解和模板語言(熟悉的表達式語法),完成以前複雜的寫法
5.3.2.EasyPoi的主要特點
1.設計精巧,使用簡單2.接口豐富,擴展簡單3.默認值多,write less do more4.spring mvc支持,web導出可以簡單明瞭
5.3.3.功能
Excel自適應xls和xlsx兩種格式,word只支持docx模式
1.Excel導入
註解導入
Map導入
大數據量導入sax模式
導入文件保存
文件校驗
字段校驗
2.Excel導出
註解導出
模板導出
html導出
3.Excel轉html
4.word導出
5.pdf導出
5.3.4.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
5.3.5.依賴jar包
-
1.easypoi-annotation 基礎註解包,作用與實體對象上,拆分後方便maven多工程的依賴管理
-
2.easypoi-base 導入導出的工具包,可以完成Excel導出,導入,Word的導出,Excel的導出功能
-
3.easypoi-web 耦合了spring-mvc 基於AbstractView,極大的簡化spring-mvc下的導出功能
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-base</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-web</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-annotation</artifactId>
<version>4.0.0</version>
</dependency>
5.3.6.Excel 註解版
Excel的導入導出是Easypoi的核心功能,前期基本也是圍繞這個打造的,主要分爲三種方式的處理,其中模板和Html目前只支持導出,因爲支持Map.class其實導入應該是怎樣都支持的
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 | 導入時創建對象使用 |
5.3.7. 對象定義
首先定義一個我們導出的對象,爲了節省篇幅,統一忽略getter,setter
public class User {
@Excel(name="ID", height = 20, width = 30)
private String id;
@Excel(name="名字")
private String name;
@Excel(name="年齡")
private Integer age;
@Excel(name="生日",format = "yyyy年MM月dd日",width = 20)
private Date bir;
}
5.3.8.生成Excel代碼如下:
public class TestEasyPoi {
@Test
public void testExport() throws Exception{
List<User> users = new ArrayList<User>();
users.add(new User("1", "小黃", 23, new Date()));
users.add(new User("2", "小劉", 26, new Date()));
users.add(new User("3", "小黑", 24, new Date()));
users.add(new User("4", "小張", 18, new Date()));
//參數:標題,表名,實體類類對象,導出的集合
Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("計算機一班學生","學生"),User.class, users);
workbook.write(new FileOutputStream(new File("E:/easypoi.xls")));
workbook.close();
}
}
5.3.9.一對多關係導出
學生實體(多)
@ExcelTarget(value = "student")
public class Student {
@Excel(name="ID")
private String id;
@Excel(name="學生姓名")
private String name;
@Excel(name="學生年齡")
private Integer age;
}
老師實體(一)
@ExcelTarget(value = "teacher")
public class Teacher {
@ExcelIgnore
private String id;
@Excel(name="老師姓名")
private String name;
@ExcelCollection(name="計算機學生")
private List<Student> students;
}
5.3.10.生成Excel代碼如下:
@Test
public void TestEasyPois() throws Exception{
//創建學生集合
List<Student> stus = new ArrayList<Student>();
stus.add(new Student("1", "小黃", 23));
stus.add(new Student("2", "小劉", 26));
stus.add(new Student("3", "小黑", 24));
stus.add(new Student("4", "小張", 18));
Teacher teacher = new Teacher("1","張超男",stus);
//創建老師集合
List<Teacher> teachers = new ArrayList<Teacher>();
teachers.add(teacher);
//參數:(一級標題,二級標題,表名),實體類類對象,導出的集合
Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("計算機一班學生","計算機","學生"),Teacher.class, teachers);
workbook.write(new FileOutputStream(new File("E:/easypoi.xls")));
//釋放資源
workbook.close();
}
這樣我們就完成了需求,效果如圖
但是名字沒有合併,不太美觀
給老師名字加了needMerge = true的屬性,就可以完成單元格的合併
@Excel(name="老師姓名",needMerge = true)
private String name;
如圖:
還可以多添加幾位老師,
Teacher teacher = new Teacher("1","張超男",stus);
Teacher teacher1 = new Teacher("2","張坤",stus);
//創建老師集合
List<Teacher> teachers = new ArrayList<Teacher>();
teachers.add(teacher);
teachers.add(teacher1);
效果如圖:
5.3.11.圖片的導出:
@Excel(name="頭像",type = 2 ,width = 40 , height = 20,imageType = 1)
private String headPic;
表示type =2 該字段類型爲圖片,imageType=1 (默認可以不填),表示從file讀取,字段類型是個字符串類型 可以用相對路徑也可以用絕對路徑,絕對路徑優先依次獲取
//創建學生集合
List<Student> stus = new ArrayList<Student>();
stus.add(new Student("1", "小黃", 23,"C:/Users/Administrator/Desktop/cmfzcode/cmfz_zhangcn/WebRoot/img/captcha.jpg"));
stus.add(new Student("2", "小劉", 26,"WebRoot/img/captcha.jpg"));
stus.add(new Student("3", "小黑", 24,"WebRoot/img/captcha.jpg"));
stus.add(new Student("4", "小張", 18,"WebRoot/img/captcha.jpg"));
5.4.EasyPoi導入
public class TestEasyPoiInput {
public static void main(String[] args) throws Exception {
//創建導入對象
ImportParams params = new ImportParams();
params.setTitleRows(1); //表格標題行數,默認0
params.setHeadRows(2); //表頭行數,默認1
//獲取導入數據
List<Teacher> teachers = ExcelImportUtil.importExcel(new FileInputStream(new File("D:/TestEasyPoi.xls")),Teacher.class, params);
for (Teacher teacher : teachers) {
System.out.println(teacher);
}
}
}
5.5.EasyPoi圖片導入
@Test
public void testEasyPoiPhotos() {
ImportParams params = new ImportParams();
params.setTitleRows(1);
params.setHeadRows(1);
try {
//導入 參數:對應實體,導入參數
List<Photo> photos = ExcelImportUtil.importExcel(new FileInputStream(new File("D://easypoiPhoto.xls")),Photo.class, params);
for (Photo photo : photos) {
System.out.println(photo);
}
} catch (Exception e) {
e.printStackTrace();
}
}
上傳路徑:設置保存路徑saveUrl 默認爲"upload/excelUpload"可以手動修改 ImportParams 修改下就可以 final修飾不能修改