阿里開源的這個庫,讓 Excel 導出不再複雜(簡簡單單的寫)

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你好,我是看山。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"導出是中後臺常見的功能,Excel文件是常見的導出格式。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在Java棧中,常用的是","attrs":{}},{"type":"link","attrs":{"href":"https://sourceforge.net/projects/jexcelapi/","title":"","type":null},"content":[{"type":"text","text":"JXL(目前改名爲JExcel)","attrs":{}}]},{"type":"text","text":"和","attrs":{}},{"type":"link","attrs":{"href":"http://poi.apache.org/","title":"","type":null},"content":[{"type":"text","text":"Apache POI","attrs":{}}]},{"type":"text","text":"。其中jxl最後的更新時間是2012,除了老系統中能看到影子,幾乎見不到蹤跡了。目前基本上是POI一統天下。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"今天要說的EasyExcel阿里巴巴開源的Excel導出類庫,是對POI的封裝,實現了很多高級功能,並且留出擴展口,支持擴展定製化功能。打個比喻,POI相當於樂高積木,一個個的小積木可以自由組裝,只能動手能力強,就可以隨心所欲的組裝。EasyExcel更像是把這些小積木提前組裝好,想要搭建房子,就直接找組裝好的屋頂、圍牆就行。如果僅僅如此,那EasyExcel僅僅就是簡單的工具包,其更加吸引人的地方是對於內存的控制,它通過壓縮文件、分批讀取、拋棄不重要數據、文件緩存等多種方式,降低內存消耗。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"內容比較多,文內只會列出關鍵代碼,想要完整源碼,可以關注公號「看山的小屋」回覆“easyexcel”獲取。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"最簡單的寫表格","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"開始之前,先定義一下基礎類,這個類將貫穿全文,所有的功能都是在這個類的簡單變形。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"@Data\npublic class Item {\n @ExcelProperty(\"字符串標題\")\n private String string;\n @ExcelProperty(\"日期標題\")\n private Date date;\n @ExcelProperty(\"數字標題\")\n private Double doubleData;\n @ExcelIgnore\n private String ignore;\n}\n","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"根據頭對象和列表向一個工作表中寫一個表格","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這是最簡單的一種實現,只需要定義一個對象類,然後讀取數據列表即可。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"/**\n * 藉助{@link com.alibaba.excel.write.builder.ExcelWriterSheetBuilder}自動創建{@link com.alibaba.excel.ExcelWriter}寫入數據。\n *

\n * 提供列表和函數作爲數據源\n */\npublic static void writeAutoWriter() {\n final String fileName = defaultFileName(\"writeAutoWriter\");\n EasyExcelFactory.write(fileName)\n .head(Item.class)\n .sheet(\"模板\")\n .doWrite(WriteSample::sampleItems);\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"EasyExcel提供了","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"EasyExcelFactory","attrs":{}}],"attrs":{}},{"type":"text","text":"類,API方法也是fluent方式,可以如絲般順滑的實現生成Excel文件。如果感覺","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"EasyExcelFactory","attrs":{}}],"attrs":{}},{"type":"text","text":"太長,還可以直接寫作","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"EasyExcel","attrs":{}}],"attrs":{}},{"type":"text","text":",這是","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"EasyExcelFactory","attrs":{}}],"attrs":{}},{"type":"text","text":"的子類,類似於別名。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"不過,這種別名定義方式,在有些規範中屬於","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"smell code","attrs":{}}],"attrs":{}},{"type":"text","text":",所以,根據自己或者公司規範選擇吧。","attrs":{}}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"com.alibaba.excel.EasyExcelFactory#write(java.lang.String)","attrs":{}}],"attrs":{}},{"type":"text","text":"方法的參數傳的是導出文件的文件名,如果並不需要生成文件,只需要創建文件流,也可以傳入一個輸出流","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"OutputStream","attrs":{}}],"attrs":{}},{"type":"text","text":",這樣就可以更加靈活的實現生成邏輯了。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"com.alibaba.excel.metadata.AbstractParameterBuilder#head()","attrs":{}}],"attrs":{}},{"type":"text","text":"方法是定義表頭,只要傳入一個類,就會讀取這個類的所有字段作爲表頭。如果字段上","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"com.alibaba.excel.annotation.ExcelProperty","attrs":{}}],"attrs":{}},{"type":"text","text":"註解,定義了","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"value","attrs":{}}],"attrs":{}},{"type":"text","text":",就會取","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"value","attrs":{}}],"attrs":{}},{"type":"text","text":"的值作爲表頭。此處還有很多操作,比如,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"value","attrs":{}}],"attrs":{}},{"type":"text","text":"是數組,可以定義多個,如果是相鄰字段定義了相同的表頭,會合並單元格,表體內容會選擇第一個單元格的內容。這個註解還可以定義","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"index","attrs":{}}],"attrs":{}},{"type":"text","text":"、","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"order","attrs":{}}],"attrs":{}},{"type":"text","text":"、","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"converter","attrs":{}}],"attrs":{}},{"type":"text","text":"等,後面會一一給出例子。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"com.alibaba.excel.write.builder.ExcelWriterBuilder#sheet()","attrs":{}}],"attrs":{}},{"type":"text","text":"方法定義工作表,有多個重載方法,可以定義","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"sheetNo","attrs":{}}],"attrs":{}},{"type":"text","text":"指明是第幾個工作表,可以傳入","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"sheetName","attrs":{}}],"attrs":{}},{"type":"text","text":"指明工作表名稱。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"com.alibaba.excel.write.builder.ExcelWriterSheetBuilder#doWrite()","attrs":{}}],"attrs":{}},{"type":"text","text":"方法就是寫Excel文件了,傳入全部的列表數據,或者使用Java8+的","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Supplier","attrs":{}}],"attrs":{}},{"type":"text","text":"函數。還可以實現分頁寫入,後面會給出例子。這個方法會自動關閉文件流,真是很貼心。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"結果爲:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/a0/a0de5cb490bf6616084bed5a19ec208c.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"根據頭對象和列表向多個工作表中寫數據","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"上面是向一個工作表寫數據,接下來我們向多個工作表寫數據。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這個例子會涉及更多的內部對象,比如:ExcelWriter、WriteSheet。","attrs":{}}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"/**\n * 手動創建{@link com.alibaba.excel.ExcelWriter},指定sheet寫入數據。\n *

\n * 提供列表和函數作爲數據源\n */\npublic static void writeManualWither() {\n String fileName = defaultFileName(\"writeManualWriter\");\n ExcelWriter excelWriter = null;\n try {\n excelWriter = EasyExcelFactory.write(fileName)\n .head(Item.class)\n .build();\n final WriteSheet writeSheet1 = EasyExcelFactory.writerSheet(\"模板1\").build();\n excelWriter.write(WriteSample::sampleItems, writeSheet1);\n\n final WriteSheet writeSheet2 = EasyExcelFactory.writerSheet(\"模板2\").build();\n excelWriter.write(sampleItems(), writeSheet2);\n } finally {\n // 千萬別忘記finish 會幫忙關閉流\n if (excelWriter != null) {\n excelWriter.finish();\n }\n }\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"因爲是想多個工作表中寫數據,我們就不能直接使用","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"doWrite","attrs":{}}],"attrs":{}},{"type":"text","text":"方法了。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"com.alibaba.excel.ExcelWriter","attrs":{}}],"attrs":{}},{"type":"text","text":"類是Excel寫對象,用來創建Excel工作簿的。","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"com.alibaba.excel.write.metadata.WriteSheet","attrs":{}}],"attrs":{}},{"type":"text","text":"類是Sheet寫對象,用來創建Sheet工作表的。通過","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"com.alibaba.excel.ExcelWriter#write()","attrs":{}}],"attrs":{}},{"type":"text","text":"方法,指定寫入數據和寫入的目標工作表,就可以實現向多個工作表中寫數據的功能。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"此處需要注意,我們在創建","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ExcelWriter","attrs":{}}],"attrs":{}},{"type":"text","text":"對象時,調用了","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"head()","attrs":{}}],"attrs":{}},{"type":"text","text":"方法定義了表頭,這是整個Excel的定義,sheet會繼承這個定義。這樣,整個Excel文件中的所有工作表,表頭都是相同的。不要停,後面會給出不同工作表定義不同表頭的示例。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"結果爲:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/8f/8f2c86fea7f678a4456af7727f7feeb6.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"按照定義指定導出列","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在後臺系統中,會有行列權限的控制。行權限,通過數據行實現,只導出有權限的行數據即可。列權限,可以通過只導出有權限的列,排除沒有權限的列(通常是分等級的敏感數據)。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"有時候需要定製化導出,導出所有列表格比較大,用戶根據需要指定需要導出的列。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"排除指定列","attrs":{}}]},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"private static void writeExcludeColumn() {\n String fileName = defaultFileName(\"writeExcludeColumn\");\n Set excludeColumnFiledNames = new HashSet<>();\n excludeColumnFiledNames.add(\"date\");\n\n EasyExcelFactory.write(fileName)\n .head(Item.class)\n .excludeColumnFiledNames(excludeColumnFiledNames)\n .sheet(\"模板\")\n .doWrite(WriteSample::sampleItems);\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這個需求,需要藉助","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"com.alibaba.excel.write.builder.AbstractExcelWriterParameterBuilder#excludeColumnFiledNames","attrs":{}}],"attrs":{}},{"type":"text","text":"方法。這個方法是在","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ExcelWriterBuilder","attrs":{}}],"attrs":{}},{"type":"text","text":"、","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ExcelWriterSheetBuilder","attrs":{}}],"attrs":{}},{"type":"text","text":"、","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ExcelWriterTableBuilder","attrs":{}}],"attrs":{}},{"type":"text","text":"的父類中定義,也就是說,可以是整個Excel工作簿都排除指定字段,也可以是某個sheet工作表排除指定字段,還可以是table表格排除指定字段。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"除了","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"excludeColumnFiledNames","attrs":{}}],"attrs":{}},{"type":"text","text":"通過字段名排除字段,還可以使用","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"excludeColumnIndexes","attrs":{}}],"attrs":{}},{"type":"text","text":"指定字段下標排除列,如果需要控制下標,需要在字段上定義","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ExcelProperty","attrs":{}}],"attrs":{}},{"type":"text","text":"指明index屬性,這樣也能夠更好的固定字段下標。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"結果爲:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/4e/4e0cc378e198949d197769add6820e99.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"只導出指定列","attrs":{}}]},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"private static void writeIncludeColumn() {\n String fileName = defaultFileName(\"writeIncludeColumn\");\n Set includeColumnFiledNames = new HashSet<>();\n includeColumnFiledNames.add(\"date\");\n EasyExcelFactory.write(fileName)\n .head(Item.class)\n .includeColumnFiledNames(includeColumnFiledNames)\n .sheet(\"模板\")\n .doWrite(WriteSample::sampleItems);\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這個需求,需要藉助","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"com.alibaba.excel.write.builder.AbstractExcelWriterParameterBuilder#includeColumnFiledNames","attrs":{}}],"attrs":{}},{"type":"text","text":"方法。與","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"excludeColumnFiledNames","attrs":{}}],"attrs":{}},{"type":"text","text":"是相似,都是可以分級定義,用起來也是一樣的,只不過功能相反而已。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"同樣的,也可以使用","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"includeColumnIndexes","attrs":{}}],"attrs":{}},{"type":"text","text":"方法,通過指定字段下標指定列。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"結果爲:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/4f/4f66653e0bea78329f4d5993b5d1c232.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"表頭","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"表頭的定義是比較關鍵的,會直接影響Excel文件的質量。所以,EasyExcel提供了比較豐富的表頭定義方法。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"原始表頭","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這裏定義了一個新的基礎類:","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"EmptyItem","attrs":{}}],"attrs":{}},{"type":"text","text":",與","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Item","attrs":{}}],"attrs":{}},{"type":"text","text":"的區別是移除了","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ExcelProperty","attrs":{}}],"attrs":{}},{"type":"text","text":"的定義。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"@Data\npublic class EmptyItem {\n private String string;\n private Date date;\n private Double doubleData;\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在這種情況下,會直接使用","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"EmptyItem","attrs":{}}],"attrs":{}},{"type":"text","text":"對象的字段作爲表頭名稱。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"private static void writeNoAnnotation() {\n final String fileName = defaultFileName(\"writeNoAnnotation\");\n EasyExcelFactory.write(fileName)\n .head(EmptyItem.class)\n .sheet(\"模板\")\n .doWrite(WriteSample::sampleItems);\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這裏可以看到,EasyExcel對於表頭對象、表體列表對象,沒有強制要求必須是相同的對象,只要字段一致,就能夠正常組裝數據。","attrs":{}}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"結果爲:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/fd/fd3de63f420592b02060c43a3911911f.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"自定義表頭","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"使用字段作爲表頭顯然不是我們想要的,EasyExcel提供了","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ExcelProperty","attrs":{}}],"attrs":{}},{"type":"text","text":"註解,可以定義表頭的名稱。這個註解還提供了","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"index","attrs":{}}],"attrs":{}},{"type":"text","text":"、","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"order","attrs":{}}],"attrs":{}},{"type":"text","text":"兩個屬性,可以定義列的位置和順序。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"@Data\npublic class IndexItem {\n @ExcelProperty(value = \"字符串標題\", index = 1)\n private String string;\n @ExcelProperty(value = \"日期標題\", index = 3)\n private Date date;\n @ExcelProperty(value = \"數字標題\", index = 5)\n private Double doubleData;\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"使用起來也很簡單:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"private static void writeWithIndex() {\n final String fileName = defaultFileName(\"writeWithIndex\");\n EasyExcelFactory.write(fileName)\n .head(IndexItem.class)\n .sheet(\"模板\")\n .doWrite(WriteSample::sampleItems);\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"結果爲:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/d9/d9ebdc43639974914ff18dadef3f2a18.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這裏需要注意一下,在使用","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ExcelProperty","attrs":{}}],"attrs":{}},{"type":"text","text":"註解時,index表示字段放置第幾列,order表示順序。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"根據index和order的不同語義,對兩者的控制不同。如果index相同,直接會拋出異常,因爲程序無法判斷這個列放那個字段。如果index值中間有空的數字,就會出現空列。如果order和index同時使用,index優先佔據位置,order做排序。index=-1的話,使用java默認排序,order值越小,列越靠前。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"ExcelProperty","attrs":{}}],"attrs":{}},{"type":"text","text":"的value屬性是字符串數組,相當於一個字段可以定義多個頭,這樣就可以實現多級表頭。同時,如果位置相鄰的列定義列明相同,還會合並列。比如:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"@Data\npublic class ComplexHeadItem {\n @ExcelProperty({\"大標題\", \"字符串標題\"})\n private String string;\n @ExcelProperty(\"日期標題\")\n private Date date;\n @ExcelProperty({\"大標題\", \"數字標題0\"})\n private Double doubleData;\n @ExcelProperty({\"數字標題\"})\n private Double doubleData1;\n @ExcelProperty({\"數字標題\"})\n private Double doubleData2 = 0.0;\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"結果爲:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/5b/5b170b11eaa3f8d7ce8771c35752545c.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"動態表頭、表體","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"前面的例子中,表頭定義都是傳入一個對象,通過解析對象的屬性字段,抽取表頭定義。有的時候,我們沒有辦法提前定義表頭對象,或者說,表頭是根據條件、權限等因素動態變化的,這個時候,就可以使用EasyExcel提供的動態表頭功能了。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"/**\n * 動態表頭,傳入的是{@code List>}格式數據。\n *

\n * 可以實現多層表頭。\n */\nprivate static void writeDynamicHead() {\n String fileName = defaultFileName(\"writeDynamicHead\");\n EasyExcelFactory.write(fileName)\n .head(dynamicHead())\n .sheet()\n .doWrite(sampleItems());\n}\n\nprivate static List> dynamicHead() {\n List> heads = new ArrayList<>();\n final List head0 = new ArrayList<>(Arrays.asList(\"頭0\", \"字符串標題【動態】\"));\n heads.add(head0);\n final List head1 = new ArrayList<>(Arrays.asList(\"頭0\", \"日期標題【動態】\"));\n heads.add(head1);\n final List head2 = new ArrayList<>(Collections.singletonList(\"數字標題【動態】\"));\n heads.add(head2);\n return heads;\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"使用","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"com.alibaba.excel.metadata.AbstractParameterBuilder#head(java.util.List>)","attrs":{}}],"attrs":{}},{"type":"text","text":"方法,傳入","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"List>","attrs":{}}],"attrs":{}},{"type":"text","text":"類型的數據即可。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"結果爲:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/5e/5ed1e13df09a2fc9feac3f6ec17c0197.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當然,這樣做還不是徹底的動態。我們可以使用","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"com.alibaba.excel.write.builder.ExcelWriterSheetBuilder#doWrite(java.util.Collection>)","attrs":{}}],"attrs":{}},{"type":"text","text":"實現動態表體。代碼如下:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"private static void writeDynamicData() {\n String fileName = defaultFileName(\"writeDynamicData\");\n EasyExcelFactory.write(fileName)\n .head(dynamicHead())\n .sheet()\n .doWrite(dynamicData());\n}\n\nprivate static List> dynamicData() {\n List> list = new ArrayList<>();\n for (int i = 0; i < 10; i++) {\n List data = new ArrayList<>();\n data.add(\"字符串\" + i);\n data.add(new Date());\n data.add((i + 1) * 0.1);\n list.add(data);\n }\n return list;\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"結果爲:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/6f/6f8b454a5977797c53aada91290b1fc7.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"表頭國際化","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"互聯網無國界,很多時候,我們需要實現國際化。這個時候,我們可以使用動態表頭功能,傳入不同的表頭定義,生成不同的Excel文件。有時候,我們還需要提前定義表體的格式,使用動態表體可以實現。有沒有更加簡單方法呢?必須有。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"先定義格式化表頭對象:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"@Data\npublic class FormatContentItem {\n @ExcelProperty(value = \"字符串標題\", converter = TitleFormatConverter.class)\n private String string;\n @DateTimeFormat(\"yyyy年MM月dd日HH時mm分ss秒\")\n @ExcelProperty(value = \"日期標題\")\n private Date date;\n @NumberFormat(\"0.000%\")\n @ExcelProperty(\"數字標題\")\n private Double doubleData;\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"再實現國際化:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"/**\n * 可以同時設置head參數:\n * {@link AbstractParameterBuilder#head(java.util.List)}\n * {@link AbstractParameterBuilder#head(java.lang.Class)}\n *

\n * 對於表頭設置,最終起作用的是{@link AbstractParameterBuilder#head(java.util.List)},這樣的話,我們可以實現國際化的配置。\n */\nprivate static void writeDynamicMultiHead() {\n String fileName = defaultFileName(\"writeDynamicMultiHead\");\n EasyExcelFactory.write(fileName)\n .head(dynamicHead())\n .head(FormatContentItem.class)\n .sheet()\n .doWrite(sampleItems());\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"結果爲:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/ee/ee0b14846feb6d78eddb7c7720dee848.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"多次寫入","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"一般來說,中後臺的數據量都不小,有時候需要一次導出幾十萬行數據,甚至更多,而這種操作並不是常態,如果內存配置比較大,那大多數時間內存都是閒置狀態。此時,就可以藉助EasyExcel的文件緩存能力,分批寫入數據。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"向同一個excel同一個sheet中多次寫入","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"首先是比較常見的場景,向一個sheet工作表中分批寫入數據。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"private static void writeOneSheet() {\n String fileName = defaultFileName(\"writeOneSheet\");\n ExcelWriter excelWriter = null;\n try {\n excelWriter = EasyExcelFactory.write(fileName)\n .head(Item.class)\n .build();\n final WriteSheet writeSheet = EasyExcelFactory.writerSheet(\"模板\").build();\n for (int i = 0; i < 5; i++) {\n excelWriter.write(sampleItems(), writeSheet);\n }\n } finally {\n // 千萬別忘記finish 會幫忙關閉流\n if (excelWriter != null) {\n excelWriter.finish();\n }\n }\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"首先定義","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ExcelWriter","attrs":{}}],"attrs":{}},{"type":"text","text":"可以操作整個Excel工作簿,然後定義","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ExcelWriter","attrs":{}}],"attrs":{}},{"type":"text","text":"sheet工作表,接下來就是循環調用","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"com.alibaba.excel.ExcelWriter.write(java.util.Collection>, com.alibaba.excel.write.metadata.WriteSheet)","attrs":{}}],"attrs":{}},{"type":"text","text":"方法,將數據寫入到指定的sheet工作表中。這裏需要注意的是,最後一定要調用","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"com.alibaba.excel.ExcelWriter.finish","attrs":{}}],"attrs":{}},{"type":"text","text":"方法,表示停止寫入並關閉流。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"結果爲:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/75/759cb99bac7dc8d7ed1b997bd5976210.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"向同一個excel不同sheet中多次寫入(表頭相同)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"還有一種場景是按月導出全年的訂單數據,每個月一個sheet工作表,這種導出的方式,表頭都是相同的。根據上面的經驗,我們需要定義多個","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"WriteSheet","attrs":{}}],"attrs":{}},{"type":"text","text":"工作表對象,然後向該對象中寫數據。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這裏還可能有一種情況,就是我們需要在多個","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"WriteSheet","attrs":{}}],"attrs":{}},{"type":"text","text":"工作表對象之間切換寫入,爲了不會找錯對象,可以指定","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"sheetNo","attrs":{}}],"attrs":{}},{"type":"text","text":"。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"代碼如下:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"private static void writeDiffSheetWithSameHead() {\n String fileName = defaultFileName(\"writeDiffSheetWithSameHead\");\n ExcelWriter excelWriter = null;\n try {\n excelWriter = EasyExcelFactory.write(fileName)\n .head(Item.class)\n .build();\n for (int i = 0; i < 5; i++) {\n final WriteSheet writeSheet = EasyExcelFactory.writerSheet(i, \"模板\" + i)\n .build();\n excelWriter.write(sampleItems(), writeSheet);\n }\n } finally {\n // 千萬別忘記finish 會幫忙關閉流\n if (excelWriter != null) {\n excelWriter.finish();\n }\n }\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"結果爲:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/30/307c827618e07979b7eac7eddbeae0ca.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/3c/3cef53ea7774e84f5893b19a1ad8ab81.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"向同一個excel不同sheet中多次寫入(表頭不同)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"還有一種場景,導出指定時間範圍的訂單信息,一個sheet工作表放具體的商品信息,另一個sheet工作表放訂單收貨地址信息。這種場景就需要不同的表頭,根據前面的講解,我們知道,只需要在定義","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"WriteSheet","attrs":{}}],"attrs":{}},{"type":"text","text":"對象時指定不同的表頭對象即可。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"代碼如下:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"private static void writeDiffSheetWithDiffHead() {\n String fileName = defaultFileName(\"writeDiffSheetWithDiffHead\");\n ExcelWriter excelWriter = null;\n try {\n excelWriter = EasyExcelFactory.write(fileName)\n .build();\n\n final WriteSheet writeSheet0 = EasyExcelFactory.writerSheet(0, \"模板1\")\n .head(Item.class)\n .build();\n excelWriter.write(sampleItems(), writeSheet0);\n\n final WriteSheet writeSheet1 = EasyExcelFactory.writerSheet(1, \"模板2\")\n .head(ComplexHeadItem.class)\n .build();\n excelWriter.write(sampleItems(), writeSheet1);\n } finally {\n // 千萬別忘記finish 會幫忙關閉流\n if (excelWriter != null) {\n excelWriter.finish();\n }\n }\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"結果爲:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/91/917d64063f22ed597a5ba00202900754.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/89/897147abe41bb42e6ee33accb1347f2d.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"實現多表","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"EasyExcel對於Excel文件定義分成了三層,","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"工作簿,也就是Excel文件","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"工作表,對應是Excel文件中的Sheet","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"表格,對應是Sheet中的有表頭、表體的組合","attrs":{}}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這裏所說的功能就是在一個Sheet中創建多個表格。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"同一表單中創建表格","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這個是開胃菜,演示一下怎麼單獨指定表格。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"private static void writeTable() {\n String fileName = defaultFileName(\"writeTable\");\n final ExcelWriter excelWriter = EasyExcelFactory.write(fileName)\n .head(Item.class)\n .build();\n try {\n // 把sheet設置爲不需要頭 不然會輸出sheet的頭 這樣看起來第一個table 就有2個頭了\n WriteSheet writeSheet = EasyExcelFactory.writerSheet()\n .needHead(Boolean.FALSE)\n .build();\n\n // 這裏必須指定需要頭,table 會繼承sheet的配置,sheet配置了不需要,table 默認也是不需要\n WriteTable writeTable0 = EasyExcelFactory.writerTable(0)\n .needHead(Boolean.TRUE)\n .build();\n\n excelWriter.write(sampleItems(), writeSheet, writeTable0);\n } finally {\n if (excelWriter != null) {\n excelWriter.finish();\n }\n }\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可以看到,除了前面提過的","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ExcelWriter","attrs":{}}],"attrs":{}},{"type":"text","text":"和","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"WriteSheet","attrs":{}}],"attrs":{}},{"type":"text","text":",這裏還用到了","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"WriteTable","attrs":{}}],"attrs":{}},{"type":"text","text":",這個就是表格的寫對象。有了這個對象,我們只要多創建幾個,就能夠實現在一個Sheet工作表中,創建多個表格的功能。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"結果爲:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/c0/c0865cc830c9043af1976e6011a939f5.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"與前面的例子完全沒有差別,條條大路通羅馬。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"同一表單中創建不同表格(相同表頭)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"有了上面的鋪墊,我們直接上代碼:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"private static void writeTables() {\n String fileName = defaultFileName(\"writeTables\");\n final ExcelWriter excelWriter = EasyExcelFactory.write(fileName)\n .build();\n try {\n // 把sheet設置爲不需要頭 不然會輸出sheet的頭 這樣看起來第一個table 就有2個頭了\n WriteSheet writeSheet = EasyExcelFactory.writerSheet()\n .head(Item.class)\n .needHead(Boolean.FALSE)\n .build();\n\n // 這裏必須指定需要頭,table 會繼承sheet的配置,sheet配置了不需要,table 默認也是不需要\n WriteTable writeTable0 = EasyExcelFactory.writerTable(0)\n .needHead(Boolean.TRUE)\n .build();\n\n WriteTable writeTable1 = EasyExcelFactory.writerTable(1)\n .needHead(Boolean.TRUE)\n .build();\n // 第一次寫入會創建頭\n excelWriter.write(sampleItems(), writeSheet, writeTable0);\n // 第二次寫如也會創建頭,然後在第一次的後面寫入數據\n excelWriter.write(sampleItems(), writeSheet, writeTable1);\n } finally {\n if (excelWriter != null) {\n excelWriter.finish();\n }\n }\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"因爲使用的是相同的表頭,我們可以直接在","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"WriteSheet","attrs":{}}],"attrs":{}},{"type":"text","text":"中定義表頭對象,通過繼承的方式,實現兩個表格的表頭是相同的。這裏需要注意一下,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"WriteSheet","attrs":{}}],"attrs":{}},{"type":"text","text":"構建時,設置","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"needHead(Boolean.FALSE)","attrs":{}}],"attrs":{}},{"type":"text","text":",如果不設置或者設置爲true,那第一個表格就會有兩個表頭。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"結果爲:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/fb/fb0ec6caa90c9b0575658fb6eb51f0b8.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"同一表單中創建不同表格(不同表頭)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"舉一反三,對於不同表頭,我們只需要爲","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"WriteTable","attrs":{}}],"attrs":{}},{"type":"text","text":"對象設置不同表頭即可:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"private static void writeTablesWithDiffHead() {\n String fileName = defaultFileName(\"writeTablesWithDiffHead\");\n final ExcelWriter excelWriter = EasyExcelFactory.write(fileName)\n .build();\n try {\n WriteSheet writeSheet = EasyExcelFactory.writerSheet()\n .build();\n\n WriteTable writeTable0 = EasyExcelFactory.writerTable(0)\n .head(Item.class)\n .build();\n excelWriter.write(sampleItems(), writeSheet, writeTable0);\n\n WriteTable writeTable1 = EasyExcelFactory.writerTable(1)\n .head(ComplexHeadItem.class)\n .build();\n excelWriter.write(sampleItems(), writeSheet, writeTable1);\n } finally {\n if (excelWriter != null) {\n excelWriter.finish();\n }\n }\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"結果爲:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/cf/cf9de2bb33118cb352f1112dc4f3849b.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"寫入模板文件(非填充)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"有時候,我們需要按照某種模板導出數據,這類模板文件屬於固定樣式,沒有動態數據。比如前面幾行是標題、權限聲明、責任聲明之類的,緊跟着就是列表數據。如果全靠手工拼寫數據比較繁瑣,EasyExcel提供了寫入模板文件的方式。先看代碼:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"private static void writeByTemplate() {\n String fileName = defaultFileName(\"writeByTemplate\");\n String templateFile = getPath() + File.separator + \"template_write_after_fill.xlsx\";\n EasyExcelFactory.write(fileName)\n .withTemplate(templateFile)\n .head(Item.class)\n .sheet()\n .doWrite(sampleItems());\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"需要使用","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"com.alibaba.excel.write.builder.ExcelWriterBuilder#withTemplate(java.lang.String)","attrs":{}}],"attrs":{}},{"type":"text","text":"指定模板文件路徑。withTemplate方法有幾個重載實現:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"指定模板文件路徑","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ExcelWriterBuilder#withTemplate(java.lang.String)","attrs":{}}],"attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"指定模板文件對象","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ExcelWriterBuilder#withTemplate(java.io.File)","attrs":{}}],"attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"指定模板文件輸入流","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ExcelWriterBuilder#withTemplate(java.io.InputStream)","attrs":{}}],"attrs":{}}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"指定模板文件和模板文件對象都是操作文件的,需要有文件信息。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"指定模板文件輸入流是隻要文件流,這個可操作性空間就比較大了。比如,模板文件是可變的,我們可以基於一個帶變量的模板文件,使用填充寫入的方式初始化模板文件,然後再用模板寫入的方式,寫入列表。(這個會在技巧篇中詳細說明)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"代碼中的模板文件內容:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/bd/bd2c93b8e3fc7db35f6a9a719a3602e4.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"導出文件的內容:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/35/352a9db70240bc5d321c0430986e6292.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可以看出,這種方式寫入的列表是以追加的方式寫入,原有的模板內容不會修改,會從第一行空白行開始寫列表信息。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"文末總結","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"本文從實戰角度說了一下 EasyExcel 如果實現寫表格,接下來會講解一下如何更好看的寫。","attrs":{}}]},{"type":"horizontalrule","attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你好,我是看山。遊於碼界,戲享人生。如果文章對您有幫助,請點贊、收藏、關注。我還整理了一些精品學習資料,關注公衆號「看山的小屋」,回覆“資料”即可獲得。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/9e/9e305acd1cca75053c144cb28adc6061.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章