目錄

  • 簡介
  • 匯出excel常用的幾種方法
    • POI
    • CSV
    • jxl
    • jxls
    • easyexcel
  • 快速入門
    • 程式碼解讀
    • 總結
  • 常用API
    • 單元格樣式
    • 合併單元格
    • 資料樣式
    • 多sheet設定
    • 單元格新增超連結
      • 依賴
      • 使用版本
      • 中流砥柱
  • notes
    • 系統時間
    • 讀寫資料格式內建轉換器
    • ModelBuildEventListener
    • write
  • 讀寫流程分析
    • read
    • write
  • # 加入戰隊
    • 微信公眾號

此文章以獨家授權一下公眾號 :
【新華前後端開發】
【指令碼之家】

快速、簡單避免OOM的java處理Excel工具】 github上關於專案的介紹

簡介

poi使用userModel模式,這個模式的特點就是上手很容易。程式碼寫起來很複雜。而且公用的地方很少。導致每次讀寫excel都需要重新編寫。
EasyExcel使用SAX模式使得easyexcel可以節省記憶體。而且easyexcel解決了記憶體洩漏問題。如果想了解SAX模式開發那成本需要3~5天學習。

匯出excel常用的幾種方法

通過Java讀寫excel大概有以下幾種:
poi、csv、jxl、jxls 、easyPoi 、easyExcel
根據效能他們的排序:
jxl 、 easyexcel 、 csv 、  poi 、  easypoi 、  jxls

POI

  • POI是apache的一個開源專案。他是基於微軟提供對Java程式的一個API。通過它我們能控制excel的單元格的內容及樣式的讀取寫入。
  • 但是正是因為他的細節之處導致我們開發起來程式碼很多。而且無法抽離。

CSV

  • csv實際上就是一個文字,只不過通過office能夠開啟的一中文字。真正的excel物件如果通過普通的文字工具開啟你會發現實際是一個二進位制檔案。因為csv是一個文字,所以在讀寫他的時候實際就是文字的讀取。沒有POI的workbook、sheet、row 、cell 之說。所以讀寫的效率還是很快的。
  • 但是因為是文字所以我們無法控制單元格的樣式。比如樣式、加下拉框、合併單元格之類的。

jxl

  • jxl實際和POI差不多。兩者的理念一樣,都是通過表格物件--》單元頁--》行--》列--》單元格的邏輯去操作讀寫的。基本上常用的功能都是提供方法的。不同的是方法的傳參順序的不同。兩者在效能上的比較jxl效能更佳。
  • 因為POI的風靡。jxl並不是很熟知。筆者也是整理的時候發現jxl。暫時不知道jxl的缺點。非要指出缺點那麼就是他和poi的邏輯不一樣。編寫起來有點彆扭。

jxls

  • 這裡需要值得注意的是jxls和jxl一點關係都沒有。兩者的使用方法的邏輯也是天差萬別的。jxls更佳側重的是excel本身的模板的編寫。jxls是通過模板在注入資料進行渲染的一個框架。他的最大的有點就是程式碼量很少。基本上我們只需要準備好資料就可以進行匯出了。
  • 因為是基於模板的。所以jxls實現匯出的很簡單。但是實現讀取資料這裡就很不好辦了。這裡筆者暫時不知道如何實現。 這個問題就留給聰明的讀者吧!!!

    easypoi

  • easypoi和easyexcel很相似。兩者都是通過註解的方式實現excel表頭與實體物件的一種對映。一個@Excel 另一個是@ExcelProperty . 相對easyexcel,easypoi功能就相對單一點。
  • 兩者都可以在自身的功能不足的情況下,通過POI的功能實現自定義功能

easyexcel

  • easyexcel是重點物件。他基於註解的方式將以前POI的複雜的程式碼進模組抽離。我們基本上的需求只需要在excelproperty註解中就可以解決。
    - easyexcel最大的特點就是解決了記憶體洩漏的問題。以上幾種poi在匯出excel的時候都受到了資料的影響.而且效能上還不是很好。easyexcel是POI系列產品的最佳之選

快速入門

easyexcel名字非常的符合他的個性。他是真的很easy.下面我們來實現一個匯出學生資訊的程式碼


String fileName = EasyExcelTools.class.getResource("/").getPath() + "student" + System.currentTimeMillis() + ".xlsx";
ExcelWriterBuilder excelWriterBuilder = EasyExcel.write(fileName, Student.class);
//excelWriterBuilder.registerConverter(new SexConverter()).registerWriteHandler(new AgeRowHandler()).registerWriteHandler(new SexCellWriteHandler());
ExcelWriter excelWriter = excelWriterBuilder.build();
WriteSheet writeSheet = EasyExcel.writerSheet("中化安元").build();
try {
    excelWriter.write(ts, writeSheet);
} catch (Exception e) {
    e.printStackTrace();
}finally {
    excelWriter.finish();
}

程式碼解讀

  • Student是匯出需要的實體。裡面配置了表格的一些基本資訊
  • ts 是Student資料的一個集合
  • fileName 是匯出的檔案地址

    student


public class Student {

/**
  * 學生索引id
  */
@ExcelProperty(value = {HeadConstant.FIRSTNAME,HeadConstant.SECONDNAME,"學號"})
private String id;
/**
  * 姓名
  */
@ExcelProperty(value = {HeadConstant.FIRSTNAME,HeadConstant.SECONDNAME,"姓名"})
private String userName;

/**
  * 使用者暱稱
  */
@ExcelProperty(value = {HeadConstant.FIRSTNAME,HeadConstant.SECONDNAME,"暱稱"})
@ExcelIgnore
private String userNick;

/**
  * 年齡
  */
@ExcelProperty(value = {HeadConstant.FIRSTNAME,HeadConstant.SECONDNAME,"年齡"})
private Integer age;
/**
  * 性別 true : 男  ; false : 女
  */
@ExcelProperty(value = {HeadConstant.FIRSTNAME,HeadConstant.SECONDNAME,"性別"})
private boolean sex;
/**
  * 生日
  */
@ExcelProperty(value = {HeadConstant.FIRSTNAME,HeadConstant.SECONDNAME,"生日"})
private Date birth;
/**
  * 身高
  */
@ExcelProperty(value = {HeadConstant.FIRSTNAME,HeadConstant.SECONDNAME,"身高"})
private Double height;

}

總結

  • 通過easyexcel匯出我們只需要準備好資料,然後兩行程式碼匯出。

常用API

  • EasyExcel 入口類,用於構建開始各種操作
  • ExcelReaderBuilder ExcelWriterBuilder 構建出一個 ReadWorkbook WriteWorkbook,可以理解成一個excel物件,一個excel只要構建一個
  • ExcelReaderSheetBuilder ExcelWriterSheetBuilder 構建出一個 ReadSheet WriteSheet物件,可以理解成excel裡面的一頁,每一頁都要構建一個
  • ReadListener 在每一行讀取完畢後都會呼叫ReadListener來處理資料
  • WriteHandler 在每一個操作包括建立單元格、建立表格等都會呼叫WriteHandler來處理資料
  • 所有配置都是繼承的,Workbook的配置會被Sheet繼承,所以在用EasyExcel設定引數的時候,在EasyExcel...sheet()方法之前作用域是整個sheet,之後針對單個sheet

單元格樣式

  • 因為被封裝了一層。如果easyexcel滿足不了我們的話,我們可以通過workbook去具體操作單元格內容和樣式。這種方法是萬不得已在使用。就比如我們想改變單元格樣式。easyexcel提供了開發介面CellWriteHandler。我們只需要實現這個介面並重寫他的beforeCellCreateafterCellCreateafterCellDispose.其中afterCellDispose方法是在單元格建立後銷燬前的一個時機。這時候我們可以改變單元格內容。easyExcel提供了四種時間捕捉介面
    CellWriteHandler
    WorkbookWriteHandler
    SheetWriteHandler
    RowWriteHandler

合併單元格

  • 在POI中我們實現合併單元格我們需要指定合併的範圍。但是在easyexcel中我們只需要在ExcelProperty註解中加入表頭的時候在對應位置加入相同的內容就會自動的合併單元格。


資料樣式

  • 資料樣式使我們Java開發中經常遇到的。比如說學生資訊中的性別我們粗在資料庫中大部分情況都是通過0、1來控制的。但是我們匯出的時候肯定是不能直接展示01的。這個時候我們就需要資料樣式了。說的在明白點就是資料格式轉換。在easyexcel中提供了Converter介面。
    convertToJavaData : excel資料轉換成Java物件
    convertToExcelData: Java物件轉換成excel資料

多sheet設定

  • 多sheet頁實際上就是建立多個sheet。每個sheet有不同的編號。剩下的操作都是一樣的。

單元格新增超連結

  • 通過CellWriteHandler實現在afterCellDispose方法中實現
CreationHelper createHelper = writeSheetHolder.getSheet().getWorkbook().getCreationHelper();
Hyperlink hyperlink = createHelper.createHyperlink(HyperlinkType.URL);
hyperlink.setAddress("https://gitee.com/zxhTom");
cell.setHyperlink(hyperlink);

依賴


<dependency>
   <groupId>net.sourceforge.javacsv</groupId>
   <artifactId>javacsv</artifactId>
   <version>2.0</version>
</dependency>

使用版本


<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>2.1.0-beta4</version>
</dependency>

中流砥柱

  • ExcelProperty: 實體屬性配置註解
  • BaseRowModel : 編寫實體繼承的實體類
  • WriteHandler : 用來控制單元格輸出,包括樣式和資料格式設定
  • ExcelWriter : 用於匯出excel

notes

系統時間

1900 windowing 1900年日期系統
1904 windowing 1904年日期系統
Excel for windows 使用1900
Excel2008 for mac 和之前版本 1904
excel 2016 for mac ; excel for mac 2011 1900

讀寫資料格式內建轉換器

  • BigDecimalBooleanConverter()
  • BigDecimalNumberConverter();
  • BigDecimalStringConverter();
  • BooleanBooleanConverter();
  • BooleanNumberConverter();
  • BooleanStringConverter();
  • ByteBooleanConverter();
  • ByteNumberConverter();
  • ByteStringConverter();
  • DateNumberConverter();
  • DateStringConverter();
  • DoubleBooleanConverter();
  • DoubleNumberConverter();
  • DoubleStringConverter();
  • FloatBooleanConverter();
  • FloatNumberConverter();
  • FloatStringConverter();
  • IntegerBooleanConverter();
  • IntegerNumberConverter();
  • IntegerStringConverter();
  • LongBooleanConverter();
  • LongNumberConverter();
  • LongStringConverter();
  • ShortBooleanConverter();
  • ShortNumberConverter(Converter 資料轉換介面);
  • ShortStringConverter();
  • StringBooleanConverter();
  • StringNumberConverter();
  • StringStringConverter();
  • StringErrorConverter();

ModelBuildEventListener

  • ModelBuildEventListener 預設的也是第一個資料監聽器,主要功能就是將讀取到的當前行資料轉換成實體或者map

write

  • FileUtils.createPoiFilesDirectory();
    在初始化時建立臨時快取目錄以避免POI併發寫入錯誤

讀寫流程分析

read

write

加入戰隊

# 加入戰隊

微信公眾號

相關文章