• <noscript id="e0iig"><kbd id="e0iig"></kbd></noscript>
  • <td id="e0iig"></td>
  • <option id="e0iig"></option>
  • <noscript id="e0iig"><source id="e0iig"></source></noscript>
  • EasyExcel讀寫Excel

    標簽: excel  

    轉載,侵刪
    原文鏈接:https://mp.weixin.qq.com/s/T_xBuoYgj1NuM7_yHe084Q

    最近讀者小 H 在知識星球中給阿粉發來私信:

    阿粉,最近我在負責公司報表平臺開發,需要導出報表到 Excel 中。每次使用 POI 開發,都要寫長長的一坨代碼,好幾次因為沒加入判空判斷,導致生成失敗。想跟你請教下有沒有更加高效一點讀寫 Excel 方法?

    ps:知識星球匯集一片大神,感興趣的同學可以加入知識星球,有任何問題都會有大神及時解答。

    使用過 poi 的開發同學可能都有此體會,每次都要寫一坨代碼,最后的代碼如下面一樣:
    在這里插入圖片描述
    這樣的代碼是不是又臭又長?當字段數量多的時候,一不小心還容易寫錯。阿粉還記得當初使用 poi 導出一個二十多字段的 excel,不斷復制粘貼,行號一不小心就寫錯了,那叫個一個心酸。

    今天阿粉就來推薦一個阿里開源的項目『EasyExcel』,帶大家徹底告別上面又長又臭的代碼,徹底解決這個問題。在這里插入圖片描述

    EasyExcel

    EasyExcel 是一個阿里出品的開源項目 ,看名字就能看出這個項目是為了讓你更加簡單的操作 Excel。另外 EasyExcel 還解決了poi 內存溢出問題,修復了一些并發情況下一些 bug。

    github 地址:https://github.com/alibaba/easyexcel
    在這里插入圖片描述
    截止阿粉寫文章時,已有 13.6k star 數據,可見這個項目還是深受大家歡迎。

    廢話不多說,我們直接進入源碼實戰環節。

    首先我們需要引入 EasyExcel pom 依賴:

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>easyexcel</artifactId>
        <version>2.1.6</version>
    </dependency>
    

    這里建議大家使用 2.0 以上的正式版本,不要再使用 1.0 的老版本,兩者使用 API 差別很大。另外 beta 版本可能會存在某些 bug,大家謹慎使用。

    普通方式

    一行代碼生成 Excel

    // 寫法1
    String fileName = "temp/" + "test" + System.currentTimeMillis() + ".xlsx";
    EasyExcel.write(fileName)
            .head(head())// 設置表頭
            .sheet("模板")// 設置 sheet 的名字
            // 自適應列寬
            .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
            .doWrite(dataList());// 寫入數據
    

    生成 excel 代碼特別簡單,這里使用鏈式語句,一行代碼直接搞定生成代碼。代碼中再也不用我們指定行號,列號了。

    上面代碼中使用自適應列寬的策略。

    下面我們來看下表頭與標題如何生成。

    創建表頭
    /**
     * 創建表頭,可以創建復雜的表頭
     *
     * @return
     */
    private static List<List<String>> head() {
        List<List<String>> list = new ArrayList<List<String>>();
        // 第一列表頭
        List<String> head0 = new ArrayList<String>();
        head0.add("第一列");
        head0.add("第一列第二行");
        // 第二列表頭
        List<String> head1 = new ArrayList<String>();
        head1.add("第一列");
        head1.add("第二列第二行");
        // 第三列
        List<String> head2 = new ArrayList<String>();
        head2.add("第一列");
        head2.add("第三列第二行");
        list.add(head0);
        list.add(head1);
        list.add(head2);
        return list;
    }
    

    上面每個 List 代表一列的數據,集合內每個數據將會順序寫入這列每一行。如果每一列的相同行數的內容相同,將會自動合并單元格。通過這個規則,我們創建復雜的表頭。

    最終創建表頭如下:
    在這里插入圖片描述

    寫入表體數據
    private static List dataList() {
        List<List<Object>> list = new ArrayList<List<Object>>();
        for (int i = 0; i < 10; i++) {
            List<Object> data = new ArrayList<Object>();
            data.add("點贊+" + i);
            // date 將會安裝 yyyy-MM-dd HH:mm:ss 格式化
            data.add(new Date());
            data.add(0.56);
            list.add(data);
        }
        return list;
    }
    

    表體數據然后也是使用 List<List>,但是與表頭規則不一樣。

    每個 List 代表一行的數據,數據將會按照順序寫入每一列中。

    集合中數據 EasyExcel 將會按照默認的格式化轉換輸出,比如 date 類型數據就將會按照 yyyy-MM-dd HH:mm:ss 格式化。

    如果需要轉化成其他格式,建議直接將數據格式化成字符串加入 List,不要通過 EasyExcel 轉換。

    最終效果如下:
    在這里插入圖片描述
    看完這個是不是想立刻體驗一下?等等,上面使用方式還是有點繁瑣,使用 EasyExcel 還可以更快。我們可以使用注解方式,無需手動設置表頭與表體。

    在這里插入圖片描述

    注解方式

    注解方式生成 Excel 代碼如下:

    String fileName = "temp/annotateWrite" + System.currentTimeMillis() + ".xlsx";
    // 這里 需要指定寫用哪個class去寫,然后寫到第一個sheet,名字為模板 然后文件流會自動關閉
    // 如果這里想使用03 則 傳入excelType參數即可
    EasyExcel
            .write(fileName, DemoData.class)
            .sheet("注解方式")
            .registerWriteHandler(createTableStyle())// Excel 表格樣式
            .doWrite(data());
    

    這里代碼與上面大體一致,只不過這里需要在 write 方法傳入 DemoData 數據類型。EasyExcel 會根據 DemoData 類型自動生成表頭。

    下面我們來看下 DemoData這個類到底內部到底是啥樣?

    @ContentRowHeight(30)// 表體行高
    @HeadRowHeight(20)// 表頭行高
    @ColumnWidth(35)// 列寬
    @Data
    public class DemoData {
        /**
         * 單獨設置該列寬度
         */
        @ColumnWidth(50)
        @ExcelProperty("字符串標題")
        private String string;
        /**
         * 年月日時分秒格式
         */
        @DateTimeFormat("yyyy年MM月dd日HH時mm分ss秒")
        @ExcelProperty(value = "日期標題")
        private Date date;
        /**
         * 格式化百分比
         */
        @NumberFormat("#.##%")
        @ExcelProperty("數字標題")
        private Double doubleData;
        @ExcelProperty(value = "枚舉類",converter = DemoEnumConvert.class)
        private DemoEnum demoEnum;
        /**
         * 忽略這個字段
         */
        @ExcelIgnore
        private String ignore;
    }
    

    DemoData 就是一個普通的 POJO 類,上面使用 ExayExcel 相關注解,ExayExcel 將會通過反射讀取字段類型以及相關注解,然后直接生成 Excel 。

    ExayExcel 提供相關注解類,直接定義 Excel 的數據模型:

    • @ExcelProperty 指定當前字段對應excel中的那一列,內部 value 屬性指定表頭列的名稱
    • @ExcelIgnore 默認所有字段都會和excel去匹配,加了這個注解會忽略該字段
    • @ContentRowHeight 指定表體行高
    • @HeadRowHeight 指定表頭行高
    • @ColumnWidth 指定列的寬度

    另外 ExayExcel 還提供幾個注解,自定義日期以及數字的格式化轉化。

    • @DateTimeFormat
    • @NumberFormat

    另外我們可以自定義格式化轉換方案,需要實現 Converter 類相關方法即可。

    public class DemoEnumConvert implements Converter<DemoEnum> {
        @Override
        public Class supportJavaTypeKey() {
            return DemoEnum.class;
        }
    
        @Override
        public CellDataTypeEnum supportExcelTypeKey() {
            return CellDataTypeEnum.STRING;
        }
    
        /**
         * excel 轉化為 java 類型,excel 讀時將會被調用
         * @param cellData
         * @param contentProperty
         * @param globalConfiguration
         * @return
         * @throws Exception
         */
        @Override
        public DemoEnum convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
            return null;
        }
    
        /**
         * java 類型轉 excel 類型,excel 寫時將會被調用
         * @param value
         * @param contentProperty
         * @param globalConfiguration
         * @return
         * @throws Exception
         */
        @Override
        public CellData convertToExcelData(DemoEnum value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
            return new CellData(value.getDesc());
        }
    }
    

    最后我們還需要在 @ExcelProperty 注解上使用 converter 指定自定義格式轉換方案。

    使用方式如下:

    @ExcelProperty(value = "枚舉類",converter = DemoEnumConvert.class)
    private DemoEnum demoEnum;
    

    最后我們運行一下,看下 Excel 實際效果如何:
    在這里插入圖片描述
    怎么樣,效果還是可以吧。
    在這里插入圖片描述
    對了,默認的樣式表格樣式可不是這樣,這個效果是因為我們在 registerWriteHandler 方法中設置自定義的樣式,具體代碼如下:

    /***
     * 設置 excel 的樣式
     * @return
     */
    private static WriteHandler createTableStyle() {
        // 頭的策略
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        // 背景設置為紅色
        headWriteCellStyle.setFillForegroundColor(IndexedColors.PINK.getIndex());
        // 設置字體
        WriteFont headWriteFont = new WriteFont();
        headWriteFont.setFontHeightInPoints((short) 20);
        headWriteCellStyle.setWriteFont(headWriteFont);
        // 內容的策略
        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
        // 這里需要指定 FillPatternType 為FillPatternType.SOLID_FOREGROUND 不然無法顯示背景顏色.頭默認了 FillPatternType所以可以不指定
        contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
        // 背景綠色
        contentWriteCellStyle.setFillForegroundColor(IndexedColors.LEMON_CHIFFON.getIndex());
    
        WriteFont contentWriteFont = new WriteFont();
        // 字體大小
        contentWriteFont.setFontHeightInPoints((short) 20);
        contentWriteCellStyle.setWriteFont(contentWriteFont);
        // 設置邊框的樣式
        contentWriteCellStyle.setBorderBottom(BorderStyle.DASHED);
        contentWriteCellStyle.setBorderLeft(BorderStyle.DASHED);
        contentWriteCellStyle.setBorderRight(BorderStyle.DASHED);
        contentWriteCellStyle.setBorderTop(BorderStyle.DASHED);
    
        // 這個策略是 頭是頭的樣式 內容是內容的樣式 其他的策略可以自己實現
        HorizontalCellStyleStrategy horizontalCellStyleStrategy =
                new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
        return horizontalCellStyleStrategy;
    }
    

    使用注意點

    poi 沖突問題

    理論上當前 easyexcel兼容支持 poi 的3.17,4.0.1,4.1.0所有較新版本,但是如果項目之前使用較老版本的 poi,由于 poi 內部代碼調整,某些類已被刪除,這樣直接運行時很大可能會拋出以下異常:

    • NoSuchMethodException

    • ClassNotFoundException

    • NoClassDefFoundError

    所以使用過程中一定要注意統一項目中的 poi 的版本。

    非注解方式自定義行高列寬

    非注解方式自定義行高以及列寬比較麻煩,暫時沒有找到直接設置的入口。查了一遍 github 相關 issue,開發人員回復需要實現 WriteHandler 接口,自定義表格樣式。

    總結

    本文主要給各位小伙伴們安利 EasyExcel 強大的功能,介紹 EasyExcel 兩種生成 excel 方式,以及演示相關的示例代碼。EasyExcel 除了寫之外,當然還支持快讀讀取 Excel 的功能,這里就不再詳細介紹。Github 上相關文檔例子非常豐富,大家可以自行參考。

    Github 文檔地址:https://alibaba-easyexcel.github.io/index.html

    版權聲明:本文為qq_37834380原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
    本文鏈接:https://blog.csdn.net/qq_37834380/article/details/106224092

    智能推薦

    HTML中常用操作關于:頁面跳轉,空格

    1.頁面跳轉 2.空格的代替符...

    freemarker + ItextRender 根據模板生成PDF文件

    1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...

    電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!

    Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...

    requests實現全自動PPT模板

    http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...

    猜你喜歡

    Linux C系統編程-線程互斥鎖(四)

    互斥鎖 互斥鎖也是屬于線程之間處理同步互斥方式,有上鎖/解鎖兩種狀態。 互斥鎖函數接口 1)初始化互斥鎖 pthread_mutex_init() man 3 pthread_mutex_init (找不到的情況下首先 sudo apt-get install glibc-doc sudo apt-get install manpages-posix-dev) 動態初始化 int pthread_...

    統計學習方法 - 樸素貝葉斯

    引入問題:一機器在良好狀態生產合格產品幾率是 90%,在故障狀態生產合格產品幾率是 30%,機器良好的概率是 75%。若一日第一件產品是合格品,那么此日機器良好的概率是多少。 貝葉斯模型 生成模型與判別模型 判別模型,即要判斷這個東西到底是哪一類,也就是要求y,那就用給定的x去預測。 生成模型,是要生成一個模型,那就是誰根據什么生成了模型,誰就是類別y,根據的內容就是x 以上述例子,判斷一個生產出...

    styled-components —— React 中的 CSS 最佳實踐

    https://zhuanlan.zhihu.com/p/29344146 Styled-components 是目前 React 樣式方案中最受關注的一種,它既具備了 css-in-js 的模塊化與參數化優點,又完全使用CSS的書寫習慣,不會引起額外的學習成本。本文是 styled-components 作者之一 Max Stoiber 所寫,首先總結了前端組件化樣式中的最佳實踐原則,然后在此基...

    基于TCP/IP的網絡聊天室用Java來實現

    基于TCP/IP的網絡聊天室實現 開發工具:eclipse 開發環境:jdk1.8 發送端 接收端 工具類 運行截圖...

    19.vue中封裝echarts組件

    19.vue中封裝echarts組件 1.效果圖 2.echarts組件 3.使用組件 按照組件格式整理好數據格式 傳入組件 home.vue 4.接口返回數據格式...

    精品国产乱码久久久久久蜜桃不卡