我去,還在這樣讀寫 excel 這也太低效了吧!

2020-12-16 Java技術架構

作者:樓下小黑哥

前言

博文地址:studyidea.cn/easyexcel

最近讀者小 H 給小黑哥發來私信:

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

使用過 poi 的開發同學可能都有此體會,每次都要寫一坨代碼,最後的代碼如下面一樣:

這樣的代碼是不是又臭又長?當欄位數量多的時候,一不小心還容易寫錯。小黑哥還記得當初使用 poi 導出一個二十多欄位的 excel,不斷複製粘貼,行號一不小心就寫錯了,那叫個一個心酸。

今天小黑哥就來推薦一個阿里開源的項目『EasyExcel』,帶大家徹底告別上面又長又臭的代碼,徹底解決這個問題。

EasyExcel

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

github 地址:github.com/alibaba/eas…

截止小黑哥寫文章時,已有 13.6kstar 數據,可見這個項目還是深受大家歡迎。

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

首先我們需要引入 EasyExcelpom 依賴:

<dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>2.1.6</version></dependency>這裡建議大家使用 2.0 以上的正式版本,不要再使用 1.0 的老版本,兩者使用 API 差別很大。另外 beta 版本可能會存在某些 bug,大家謹慎使用。

普通方式

一行代碼生成 Excel

// 寫法1String 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<String> 代表一列的數據,集合內每個數據將會順序寫入這列每一行。如果每一列的相同行數的內容相同,將會自動合併單元格。通過這個規則,我們創建複雜的表頭。

最終創建表頭如下:

寫入表體數據

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<Object>>,但是與表頭規則不一樣。

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

集合中數據 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)// 列寬@Datapublic 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 內部代碼調整,某些類已被刪除,這樣直接運行時很大可能會拋出以下異常:

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

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

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

總結

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

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

相關焦點

  • 《學子讀寫》,沒有你的日子我失去了方向
    隨著年歲的增長,特別是今年我三十而立,挫敗感自卑感越來越強烈,總覺得看的書太少許多不懂不會,原來自己也沒有三頭六臂。以前的我是這樣嗎?小時候的我胖嘟嘟,人都喜歡逗我,我也嘴大話多有「人來瘋」症,骨子裡的樂觀隨大嗓門大笑臉肆意橫行得意忘形。
  • Excel 是表格,歪果仁說 you excel me 難道是「你表格我」?
    首字母大寫的 Word 和 Excel 是專有名詞,但如果是小寫,這兩個單詞的意思就很豐富啦!大家都知道 word 有「單詞」的意思,那你知道 excel 的含義嗎?比如老外常說的 You excel me,可千萬不能理解成「你表格了我」。那 excel 到底是什麼意思呢?今天就為你揭秘它的真正含義↓↓excel是什麼意思?
  • 孩子的老師長這樣,這也是我堅持,送孩子去上學的原因吧!
    1、別看這是一個成年人,翻車的本事讓你難以想像!2、好傢夥,新娘子這是慘遭逼婚了吧!3、說實話,這麼大的蛋糕,我還是第一次見。4、蒙眼蹦極,你永遠不知道你蹦的是個啥玩意5、狗狗這是讓主人摸自己嗎?這小尾巴搖的老歡了。6、不就是一個捧花嗎,伴娘不至於這樣拼吧?
  • 你的詞彙量許多年了還在原地嗎?背單詞要「聽說讀寫」同步進行哦
    01.為什麼學了這麼久單詞量還在原地關於背單詞的方法,眾說紛紜。一個時期以來,可謂是百花齊放,百家爭鳴。特別是在信息傳播高度發達的今天。隨著電腦,電視和手機的普及。今天,不論是學習資料,還是學習辦法,真是鋪天蓋地。
  • Excel圖表製作難?這款excel圖表工具插件免費用
    有時候表格數據太多,做出來的圖表會變得非常複雜,本應該是一眼就能看明白的圖表,這時也是變成了累贅,反而不如直接去看表格更為直觀。但是這段時間一直在翻找有效的圖表工具,不論是百度還是知乎,基本上都是用Excel圖表製作的,各類大牛的教材,實在讓人膜拜,我也自己動手用Excel,做了一些試試,感覺跟大咖的圖表效果一比,天壤之別。我深深的感覺到,知識真是個好東西...要練成大咖的模樣,我不知道需要經過多久才能得達到....
  • 這3個威力無窮的Excel技巧,一般人我不告訴他
    負責演示的你,操作excel表格是手忙腳亂,還是得心應手。就在於你是否掌握下面幾個excel技巧。1. 隱藏工具欄excel2007開始,工具欄佔用了上面四分之一的屏幕。如果你想在屏幕上顯示更多的excel數據,只需要點擊「功能區最小化」命令,即可隱藏工具欄。
  • 手機如何打開Excel查看office文檔?
    比如如何用手機打開word,如何用手機編輯word,excel文檔等。這裡小編給大家提供兩種方式,一種是下載app,另一種是利用小程序。應用市場office其次,我們可以利用小程序,直接查看編輯word,excel,PowerPoint等office文檔。
  • excel實用教程,用excel給你孩子製作一份100以內加減乘除算術題
    hello,大家好,前面一直在給大家分享excel在工作中的一些實用小技巧,相比大家也有所收穫了,excel能給我們的工作帶來巨大的方便,能給我們原本枯燥無味的工作任務帶來一些很有意思的事情。一直沒有跟大家提到如何將excel的一些小技巧應用到生活中來,今天讓我來給大家分享一個非常實用的excel小技巧,這個技巧在生活中非常實用,尤其是對於家裡有小孩的朋友。今天我要大家用excel製作上圖這樣的100以內加減乘除算術題,各位家長準備好了,身邊如果沒有電腦的可以拿紙和筆記一下。
  • pdf轉格式APP讓人眼花繚亂,這款excel轉PDF小程序很良心
    pdf轉格式APP等工具,是我們無論在日常工作中還是學習中都是經常要使用到的,就像我自己之前遇到的把excel轉化成pdf的時候,總是少一頁,或者一頁只有一點,如果你也遇到這樣的情況,可能是pdf轉格式APP沒有找對,市面上的這類
  • Excel是做什麼的如何使用Excel?
    Excel作為我們工作中經常會使用到的辦公軟體,很多辦公小白是剛接觸不久的,對此還比較陌生,excel作為一種作電子試算表程序(進行數字和預算運算的軟體程序)。在我們工作的時候進行製作表格,統計數據等,能夠起到很重道的作用。
  • 外國人說「You excel me」,你可千萬別理解成「你表格我」!賊尷尬~
    聽到老外對你說「You excel me」 什麼?「你表格我」 這是神馬意思 今天就為你揭秘它的真正所指意思 Excel=超越,勝過 第二種是戰勝、超越的意思,如果老外說「you excel me」,言外之意就是「你戰勝了我,是你比較強」的意思。
  • You excel me 可別翻譯成你表格我!是在誇你呢
    除了名詞表格外 還可以做動詞 有這樣兩個意思 1.超越,勝過 to be superior to (another or others) 所以You excel
  • 「讀寫困難」愛因斯坦,達文西的經歷告訴我們,讀寫障礙可能是隱藏...
    為了喚起伊桑的自信心,尼庫巴老師在課堂中和孩子們講述愛迪生等名人小時候也存在著讀寫障礙,甚至無法識字,交流困難,也都曾被周邊的人當成弱智,而老師自己也曾是。這一番話拉近了伊桑跟尼庫巴老師的距離,他也在尼庫巴老師的幫助下,慢慢開始接納並分析那些會「跳舞」的字母,逐漸克服了讀寫障礙。
  • 一個參數一張Excel表,玩轉Pandas的read_excel()表格讀取
    作者 | 黃偉呢來源 | 數據分析與統計學之美我覺得很有必要講述這個文章,進行數據處理的第一步就是Python數據讀取。但是你可能沒想到,在進行數據讀取的同時,我們其實可以配合相關參數做很多事兒,這對於後續的數據處理都是極其有幫助。
  • 歪果仁跟你說「You excel me」是什麼意思?「你表格我」?賊尷尬~
    「excel」對於我們來說是再熟悉不過了誰沒有過一段被表格折磨的歲月穩住~ 但是但是!聽到老外對你說「You excel me」什麼?「你表格我」 這是神馬意思!
  • 修改900個excel文件名,你需要多久?我雙擊一下就搞定了
    Hello,大家好,今天跟大家分享下我們如何批量的更改excel的名稱,這個也是一個粉絲提問到的問題。他們公司要做員工調查,採用的excel問卷的方式,填寫完畢後需要將文件命名為地區加名稱,可是由於經理通知時候僅僅要求將文件命名為自己的姓名,現在統計的時候分不清具體的地區,所以經理要求要將區域加上,一個一個的更改有將近900個員工,還需要一個一個的查找及其耗費時間,問我有沒有什麼簡單的方法,最簡單的方法就是利用excel配合bat命令來更改,操作也不難,下面就讓我們開一起操作下
  • 讀寫障礙的學生,成為世界名人,小學是關鍵期
    九十年代我剛工作,根本沒聽說過「讀寫障礙」這個詞。那時曾教過兩個學困 生。現在想想應屬於讀寫障礙的學生。羅同學,從 一年級學拼音就發現他,對b、d、p、q 很難分清。這四個字母的區別是一年級學生的教學難點,運用多種方法辨認,反覆拼讀,引導學生區分。大部分人都能認清拼讀,還有一小部分人,在幾周的複習過程中,也掌握了。
  • 早做完,不加班,巧用POWER QUERY完成Excel報表數據合併
    答案是有的,今天我們就用Excel中的POWER QUERY插件幫我們去完成這樣的工作。使用POWER QUERY有一定的限制條件,他需要在office2010以及高級的版本上才能安裝使用,POWER QUERY下載地址,可以用百度搜索POWER QUERY,在微軟官網下載相對應的版本。
  • 一分鐘系列——excel技巧集錦
    要學渣菌來說的話,excel的用途大致可以分為:數據記錄,數據整理,數據分析,數據組織。當然肯定還有許許多多的其他用途就不歸類了,用來作圖,用來背單詞,用來做資源管理器。。。學渣菌之所以要多此一舉的將excel用途劃分為這四個部分是有一丟丟原因的。至於是什麼原因咱就先不說。
  • excel if函數同時滿足多個條件:明白這2點,就能隨心所欲!
    辦公絕招經常使用函數的小夥伴們都知道excel if函數是我們工作中經常用到的函數,那麼excel if函數怎麼實現滿足多個條件來使用呢?今天就為大家嘮一下excel if函數多個條件的使用方法!那麼excel if函數的多個條件實現到底怎麼用?我們首先要明白,滿足多個條件也可以分兩種情況:1)需要多個條件同時滿足;2)或者一個、幾個或多個條件。我們以下圖的數據來舉例說明。