我用EasyExcel優化了公司的導出(附踩坑記錄)
背景介紹
最近要改一個導出的功能,在原有的基礎上,在導出一份明細數據,要求導出內容加在原有 excel 的第二個 sheet 上。考慮到數據量還比較大,乾脆引入阿里的 EasyExcel 來做。
下面我先上最終程式碼,再來說說我遇到的坑有哪些
程式碼實戰
public String doHandle() {
try(ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
com.alibaba.excel.ExcelWriter excelWriter = EasyExcel.write(outputStream).build()) {
List<SaleTransferSummaryRateExportVo> exportVos = queryAction.querySummaryExport();
List<SaleTransferClassRateExportVo> exportRateVos = queryAction.queryClassRate();
WriteSheet writeSheet = EasyExcel.writerSheet(0, "統計").head(SaleTransferSummaryRateExportVo.class).build();
excelWriter.write(exportVos, writeSheet);
WriteSheet rateWriteSheet = EasyExcel.writerSheet(1, "明細").head(SaleTransferClassRateExportVo.class).build();
excelWriter.write(exportRateVos, rateWriteSheet);
excelWriter.close();
// 數據落地到OSS
String resultPath = ossClient.uploadFile(outputStream.toByteArray(), ContentMediaEnum.XLSX.getName(), FileExtEnum.XLSX.getName());
return resultPath;
} catch (Exception e) {
return "";
}
}
我們項目是將文件傳到 oss,然後去 oss 進行下載。也可以直接寫入到文件或 response
public void doHandle() {
File file=new File("");
try(
com.alibaba.excel.ExcelWriter excelWriter = EasyExcel.write(file).build()) {
List<SaleTransferSummaryRateExportVo> exportVos = queryAction.querySummaryExport();
List<SaleTransferClassRateExportVo> exportRateVos = queryAction.queryClassRate();
WriteSheet writeSheet = EasyExcel.writerSheet(0, "統計").head(SaleTransferSummaryRateExportVo.class).build();
excelWriter.write(exportVos, writeSheet);
WriteSheet rateWriteSheet = EasyExcel.writerSheet(1, "明細").head(SaleTransferClassRateExportVo.class).build();
excelWriter.write(exportRateVos, rateWriteSheet);
} catch (Exception e) {
log.error("導出異常",e);
}
}
只需要修改 write 的參數即可。
主要的程式碼就完成了,那麼數據的屬性和 excel 列名稱怎麼對應上的呢?
在數據的實體類上加上@ExcelProperty 註解就行了。它就能自動創建列頭,並將數據對應寫入。
- @ColumnWidth 列寬度
- @ExcelIgnore 代表不用導出的屬性
- DateTimeFormat 日期格式化
public class SaleTransferSummaryRateExportVo {
@ExcelProperty("老師昵稱")
@ColumnWidth(10)
private String teacherName;
@ExcelProperty("大區")
private String regionName;
@ExcelProperty("小組")
private String groupName;
@ExcelProperty("創建時間")
@DateTimeFormat("yyyy-MM-dd")
private Date createTime;
}
寫完之後覺得表格有點丑,於是又調了下樣式。也是幾個註解搞定
@HeadStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 44)
@HeadFontStyle(fontHeightInPoints = 10)
@ContentFontStyle(fontHeightInPoints = 10)
public class SaleTransferSummaryRateExportVo {
@ExcelProperty("老師昵稱")
private String teacherName;
@ExcelProperty("大區")
private String regionName;
@ExcelProperty("小組")
private String groupName;
@ExcelProperty("創建時間")
@DateTimeFormat("yyyy-MM-dd")
private Date createTime;
}
fillForegroundColor 的值就代表顏色,具體什麼值代表什麼顏色,可以參考 IndexedColors 枚舉類。
就這樣就完成了。導出效果圖如下:
遇到的坑
- 版本問題
我最開始用的版本是這樣的,因為項目里之前就引入了 poi
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.1.2</version>
</dependency>
版本不對的時候寫入直接報錯。
異常資訊如下:
Exception in thread "main" com.alibaba.excel.exception.ExcelGenerateException: java.lang.NoSuchMethodError: org.apache.poi.ss.usermodel.Cell.setCellValue(Ljava/time/LocalDateTime;)V
at com.alibaba.excel.write.ExcelBuilderImpl.addContent(ExcelBuilderImpl.java:65)
at com.alibaba.excel.ExcelWriter.write(ExcelWriter.java:70)
at com.alibaba.excel.ExcelWriter.write(ExcelWriter.java:47)
at cn.jojo.sales.app.task.ExportSalesTransferSummaryTask.main(ExportSalesTransferSummaryTask.java:90)
Caused by: java.lang.NoSuchMethodError: org.apache.poi.ss.usermodel.Cell.setCellValue(Ljava/time/LocalDateTime;)V
at com.alibaba.excel.write.executor.AbstractExcelWriteExecutor.converterAndSet(AbstractExcelWriteExecutor.java:95)
at com.alibaba.excel.write.executor.ExcelWriteAddExecutor.addJavaObjectToExcel(ExcelWriteAddExecutor.java:174)
at com.alibaba.excel.write.executor.ExcelWriteAddExecutor.addOneRowOfDataToExcel(ExcelWriteAddExecutor.java:82)
at com.alibaba.excel.write.executor.ExcelWriteAddExecutor.add(ExcelWriteAddExecutor.java:58)
at com.alibaba.excel.write.ExcelBuilderImpl.addContent(ExcelBuilderImpl.java:59)
... 3 more
- excelWriter 要關閉
excelWriter.close();
我之前因為 excelWriter 的定義是是寫在 try 里的,所以沒有 close,但是我的用法又是將 excelWriter 寫入到位元組流,然後位元組流傳到 oss,而且這個步驟也是在 try 裡面。就導致了我一直寫入不成功,後來才發現,浪費了一點時間。