SpringBoot圖文教程10—Excel模板匯出|百萬資料匯出|圖片匯出「easypoi」

鹿小洋的Java筆記發表於2020-03-05

有天上飛的概念,就要有落地的實現

  • 概念十遍不如程式碼一遍,朋友,希望你把文中所有的程式碼案例都敲一遍

  • 先贊後看,養成習慣

SpringBoot 圖文教程系列文章目錄

  1. SpringBoot圖文教程1「概念+案例 思維導圖」「基礎篇上」
  2. SpringBoot圖文教程2—日誌的使用「logback」「log4j」
  3. SpringBoot圖文教程3—「‘初戀’情結」整合Jsp
  4. SpringBoot圖文教程4—SpringBoot 實現檔案上傳下載
  5. SpringBoot圖文教程5—SpringBoot 中使用Aop
  6. SpringBoot圖文教程6—SpringBoot中過濾器的使用
  7. SpringBoot圖文教程7—SpringBoot攔截器的使用姿勢這都有
  8. SpringBoot圖文教程8 — SpringBoot整合MBG「程式碼生成器」
  9. SpringBoot圖文教程9—SpringBoot 匯入匯出 Excel 「Apache Poi」

前言

上一篇文章中簡單介紹了Poi的使用方式,但是用Poi去寫程式碼著實繁瑣了一些,假如你要實現的是複雜的需求,譬如:圖片匯出,多表資料匯出,模板匯出,大資料量匯出等等,用最原生的Poi就不是很好的選擇了。

難道要自己封裝工具類了嗎?

no no 輪子雖好,最好是別人寫好的。所以從這篇文章開始介紹兩個優秀的Poi工具 Easypoi 和 阿里開源的 EasyExcel。

EasyPoi

EasyPoi 是對poi封裝的一個工具庫,封裝好了一些常見的Excel操作

  • 最基本的匯入匯出
  • 圖片的匯入匯出
  • 多表資料的匯入匯出
  • 大批量資料的匯入匯出
  • 模板的匯出

接下來我們一起來將以上的功能實現出來

官網地址:easypoi.mydoc.io/#category_5…

最基本的匯入匯出

最基本的匯入匯出,要匯出的資料的實體類如下:

public class Teacher {
    /**
     * 老師的主鍵
     */

    private Integer teacherId;
    /**
     * 名字
     */

    private String teacherName;
    /**
     * 頭像圖片地址
     */

    private String teacherImage;
    /**
     * 老師的狀態 0代表正常 1代表刪除
     */

    private Integer teacherStatus;
}
複製程式碼

省略get set

1.匯入依賴

<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>
複製程式碼

2.給要匯出資料實體類加註解

我們要匯出的資料的實體類是Teacher 所以需要給Teacher加 Easypoi的註解
EasyPoi是註解式開發,所有的註解詳情見官方文件,但是如果要完成的需求是最簡單的匯入匯出的話,@Excel一個註解就足夠了。

@Excel
這個是必須使用的註解,如果需求簡單隻使用這一個註解也是可以的,涵蓋了常用的Excel需求,需要大家熟悉這個功能,主要分為基礎,圖片處理,時間處理,合併處理幾塊

@Excel 的官方api easypoi.mydoc.io/#text_18690…

新增好註解的實體類如下:

3.直接使用 EasyPoi 中的工具類匯入匯出

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();
    }
複製程式碼

思路

  1. 分頁讀取資料
  2. 將每次讀取到的資料寫入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:

  1. 時間問題沒做詳細的效能測試 官方有相關的測試:easypoi.mydoc.io/#text_20298…
  2. 資料庫查詢使用MybatisPlus 如果有興趣 可以看我的相關文章 SpringBoot 整合 MybatisPlus
  3. 百萬資料用 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<StringObject> map = new HashMap<StringObject>();
        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<StringString>> listMap = new ArrayList<Map<StringString>>();
        for (int i = 0; i < 4; i++) {
            Map<StringString> lm = new HashMap<StringString>();
            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實戰開發經驗。

相關文章