<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          EasyExcel太方便易用了,強烈推薦!

          共 5777字,需瀏覽 12分鐘

           ·

          2022-05-15 19:02

          背景

          系統(tǒng)中經(jīng)常要導(dǎo)出大量的數(shù)據(jù),格式基本上都是Excel,然而每次導(dǎo)表都是對系統(tǒng)內(nèi)存的一次挑戰(zhàn)。

          在Java領(lǐng)域,生成或解析Excel的框架比較有名的當(dāng)屬Apache的poi和jxl了。但使用它們,會面臨著嚴(yán)重的內(nèi)存損耗問題。如果系統(tǒng)的并發(fā)量還不行,一旦導(dǎo)出大量數(shù)據(jù),便會出現(xiàn)JVM頻繁full gc,甚至導(dǎo)致OOM。

          EasyExcel是阿里巴巴開源的一個Excel處理框架,使用簡單、節(jié)省內(nèi)存。節(jié)省內(nèi)存的原理也很簡單,在解析Excel時沒有將文件數(shù)據(jù)全部加載到內(nèi)存當(dāng)中,而是從磁盤文件中一行行讀取。

          今天這篇文章就帶大家來了解一下EasyExcel的使用,個人使用后的感慨是:太簡單易用了。

          項目構(gòu)建及依賴

          首先創(chuàng)建一個Maven項目,在pom文件中添加如下依賴:


          ?????com.alibaba
          ?????easyexcel
          ?????2.2.8

          當(dāng)引入該依賴之后,會發(fā)現(xiàn)在項目的依賴文件中同時多出了poi的類庫。也就是說,EasyExcel是基于poi來進行實現(xiàn)的,間接地引入了如下依賴:


          ?????org.apache.poi
          ?????poi
          ?????3.17


          ?????org.apache.poi
          ?????poi-ooxml
          ?????3.17

          所以,當(dāng)你的項目中已經(jīng)引入了poi的依賴,要考慮一下版本的兼容問題。

          創(chuàng)建實體類

          EasyExcel易用性的體現(xiàn)之一就是可以通過在實體類中使用注解的形式,來與Excel中的表頭進行綁定。

          現(xiàn)在直接上實體類:

          @Data
          public?class?UserData?{

          ?@ExcelProperty(index?=?0,?value?=?"姓名")
          ?private?String?username;

          ?@ExcelProperty(index?=?1,?value?=?"年齡")
          ?private?int?age;

          ?@DateTimeFormat("yyyy-MM-dd")
          ?@ExcelProperty(index?=?2,?value?=?"生日")
          ?private?Date?birthday;
          }

          在上面的實體類中@Data為Lombok的注解,當(dāng)然你可以自行生成getter/setter方法,其他的注解均為EasyExcel提供的:

          • @ExcelProperty:用于設(shè)置Excel表頭,其中index用戶表頭的編號,從0開始;value為表頭對應(yīng)的內(nèi)容。
          • @DateTimeFormat:用于日期的格式化。

          完成上述功能準(zhǔn)備工作之后,我們先來生成一個Excel。

          生成Excel

          下面直接展示生成Excel的示例代碼:

          public?class?EasyExcelDemo?{

          ?public?static?void?main(String[]?args)?{
          ??//?實現(xiàn)excel寫操作
          ??//1.設(shè)置寫入文件夾地址和excel文件名稱
          ??String?fileName?=?"/Users/zzs/temp/excel/write.xlsx";
          ??//調(diào)用easyExcel里面的方法實現(xiàn)寫操作
          ??//2個參數(shù),第一個參數(shù)是文件名稱,第二個參數(shù)是實體類
          ??EasyExcel.write(fileName,?UserData.class).sheet("學(xué)生信息表").doWrite(getData());
          ?}

          ?//創(chuàng)建方法返回list集合
          ?public?static?List?getData()?{
          ??List?list?=?new?ArrayList<>();

          ??UserData?userData1?=?new?UserData();
          ??userData1.setUsername("張三");
          ??userData1.setAge(22);
          ??userData1.setBirthday(formatDate("2000-10-11"));
          ??list.add(userData1);

          ??UserData?userData2?=?new?UserData();
          ??userData2.setUsername("李四");
          ??userData2.setAge(23);
          ??userData2.setBirthday(formatDate("1999-5-3"));
          ??list.add(userData2);

          ??return?list;
          ?}

          ?public?static?Date?formatDate(String?birthday)?{
          ??SimpleDateFormat?sdf?=?new?SimpleDateFormat("yyy-MM-dd");
          ??try?{
          ???return?sdf.parse(birthday);
          ??}?catch?(ParseException?e)?{
          ???e.printStackTrace();
          ??}
          ??return?null;
          ?}
          }

          除了準(zhǔn)備數(shù)據(jù)的代碼,核心代碼只有main方法中調(diào)用的EasyExcel.write方法,就是如此的簡單。EasyExcel的write方法會根據(jù)傳入的數(shù)據(jù)和實體類UserData進行綁定,生成Excel文件。

          我們來看一下Excel的效果:

          write-excel

          生成效果還不錯,而且使用起來是不是非常簡單?

          解析Excel

          再來看看解析Excel的操作,直接用上面生成的Excel文件。

          首先創(chuàng)建一個監(jiān)聽器ExcelListener,集成EasyExcel提供AnalysisEventListener類:

          public?class?ExcelListener?extends?AnalysisEventListener?{

          ?/**
          ??*?一行一行的讀取excel內(nèi)容
          ??*/
          ?@Override
          ?public?void?invoke(UserData?data,?AnalysisContext?analysisContext)?{
          ??System.out.println("****"?+?data);
          ?}

          ?/**
          ??*?讀取表頭內(nèi)容
          ??*/
          ?@Override
          ?public?void?invokeHeadMap(Map?headMap,?AnalysisContext?context)?{
          ??System.out.println("表頭"?+?headMap);
          ?}

          ?/**
          ??*?讀取完成操作
          ??*/
          ?@Override
          ?public?void?doAfterAllAnalysed(AnalysisContext?analysisContext)?{
          ??System.out.println("讀取Excel完畢");
          ?}
          }

          在該監(jiān)聽器中,通過重寫AnalysisEventListener的方法來獲得解析的數(shù)據(jù)、表頭信息,以及解析完畢之后執(zhí)行的操作信息。

          同樣寫Excel一樣,通過EasyExcel類的靜態(tài)方法來執(zhí)行讀操作:

          public?class?EasyExcelReadDemo?{

          ?public?static?void?main(String[]?args)?{
          ??//?實現(xiàn)excel寫操作
          ??//1.設(shè)置寫入文件夾地址和excel文件名稱
          ??String?fileName?=?"/Users/zzs/temp/excel/write.xlsx";
          ??//調(diào)用easyExcel里面的方法實現(xiàn)寫操作
          ??//2個參數(shù),第一個參數(shù)是文件名稱,第二個參數(shù)是實體類
          ??EasyExcel.read(fileName,?UserData.class,?new?ExcelListener()).sheet().doRead();
          ?}
          }

          執(zhí)行上述方法,打印信息如下:

          表頭{0=姓名,?1=年齡,?2=生日}
          ****UserData(username=張三,?age=22,?birthday=Wed?Oct?11?00:00:00?CST?2000)
          ****UserData(username=李四,?age=23,?birthday=Mon?May?03?00:00:00?CST?1999)
          讀取Excel完畢

          最先是打印了表頭信息,這里也可以看到表頭的排序是從0開始的。然后,讀取并打印了對應(yīng)的Excel內(nèi)容,兩條數(shù)據(jù);最后,執(zhí)行讀取完的方法中的日志打印。

          看完了上面的整個操作,解析Excel是不是變得非常簡單了?再也不為解析Excel犯愁了。

          其他相關(guān)特殊用法

          上面提到的@DateTimeFormat注解可轉(zhuǎn)換日期格式,還有其他類似功能的注解和自定義轉(zhuǎn)換器。

          自定義轉(zhuǎn)換器

          通過自定義轉(zhuǎn)換器,比如將1、0轉(zhuǎn)換成男、女的實例:

          import?com.alibaba.excel.converters.Converter;
          import?com.alibaba.excel.enums.CellDataTypeEnum;
          import?com.alibaba.excel.metadata.CellData;
          import?com.alibaba.excel.metadata.GlobalConfiguration;
          import?com.alibaba.excel.metadata.property.ExcelContentProperty;

          public?class?SexConverter?implements?Converter?{

          ????@Override
          ????public?Class?supportJavaTypeKey()?{
          ????????return?Integer.class;
          ????}

          ????@Override
          ????public?CellDataTypeEnum?supportExcelTypeKey()?{
          ????????return?CellDataTypeEnum.STRING;
          ????}

          ????@Override
          ????public?Integer?convertToJavaData(CellData?cellData,?ExcelContentProperty?excelContentProperty,?GlobalConfiguration?globalConfiguration)?throws?Exception?{
          ????????return?"男".equals(cellData.getStringValue())???1?:?0;
          ????}

          ????@Override
          ????public?CellData?convertToExcelData(Integer?integer,?ExcelContentProperty?excelContentProperty,?GlobalConfiguration?globalConfiguration)?throws?Exception?{
          ????????return?new?CellData<>(integer.equals(1)???"男"?:?"女");
          ????}
          }

          性別屬性注入SexConverter轉(zhuǎn)換器:

          @ExcelProperty(value?=?"性別",?converter?=?SexConverter.class)
          private?Integer?sex;

          再次生成Excel,性別字段內(nèi)容便顯示為:男、女字樣。

          保留兩位小數(shù)

          比如體重需要保留兩位小數(shù),可通過@NumberFormat 注解實現(xiàn):

          @ExcelProperty(value?=?"體重KG")
          @NumberFormat("0.##")?//?會以字符串形式生成單元格,要計算的列不推薦
          private?BigDecimal?weight;

          另外一種方法是使用@ContentStyle注解:

          @ContentStyle(dataFormat?=?2)
          private?BigDecimal?weight2;

          這樣也能達到保留兩位小數(shù)的效果。

          當(dāng)然,也可以使用實現(xiàn)Converter接口的方式實現(xiàn)(同性別實現(xiàn))。

          排除指定Excel列

          在很多場景下,Excel的列與實體類可能并不完全一致,這時就需要排除一些實體類的字段。

          方式一:類上加注解 @ExcelIgnoreUnannotated,過濾屬性沒有@ExcelProperty注解的字段

          @Data
          @ToString
          @AllArgsConstructor
          @NoArgsConstructor??//?一定要有無參構(gòu)造方法
          @ExcelIgnoreUnannotated
          public?class?UserData?{
          ????.....
          }

          方式二:指定字段加@ExcelIgnore注解

          @ExcelIgnore?//?該字段不生成excel
          private?String?remark;

          方式三:代碼指定過濾字段,通過excludeColumnFiledNames方法:

          ??EasyExcel.write(fileName,?UserData.class).sheet("學(xué)生信息表").excludeColumnFiledNames(Arrays.asList("remark")).doWrite(getData());

          這種方法的好處是:同一Excel可以在調(diào)用方法時排除不同的數(shù)據(jù)列。

          小結(jié)

          本文介紹了EasyExcel的使用,整體而言操作簡單、使用方便,提供了不少注解,方便與實體對象之間的關(guān)系綁定。而且官網(wǎng)也提供了相關(guān)的性能數(shù)據(jù),更多的API使用大家還可以繼續(xù)探索。

          無論從性能或易用性上來說,都值得你嘗試。特別是臨時寫一個Excel的解析或生成的工具,再也不用惆悵一行行的解析了,趕緊收藏用起來吧。

          往期推薦

          漫畫 | 為什么程序員干兩年后就要跑路?

          2萬字詳解,吃透 ES

          全網(wǎng)顯示 IP 歸屬地,是怎么實現(xiàn)的?

          10年了,軟件架構(gòu)是如何一步步演進的?

          面試官:淘寶七天自動確認(rèn)收貨,可以怎么實現(xiàn)?

          終于搞明白Tomcat的構(gòu)成組件,以及是如何運作的了!



          如果你覺得這篇文章不錯,那么,下篇通常會更好。備注“公眾號”添加微信好友(微信號:zhuan2quan)。

          ▲?按關(guān)注”程序新視界“,洞察技術(shù)內(nèi)幕
          瀏覽 77
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  午夜成人app | 久久久久性色Av免费毛片特级 | 午夜福利美女视频 | 久久大香蕉精 | 国内精品久久久 |