比 poi匯入匯出更好用的 EasyExcel使用小結

2023-03-10 06:08:05

轉載請註明出處:

  官方檔案: https://easyexcel.opensource.alibaba.com/docs/current/quickstart/read

1.簡潔

  Java解析、生成Excel比較有名的框架有Apache poi、jxl。但他們都存在一個嚴重的問題就是非常的耗記憶體,poi有一套SAX模式的API可以一定程度的解決一些記憶體溢位的問題,但POI還是有一些缺陷,比如07版Excel解壓縮以及解壓後儲存都是在記憶體中完成的,記憶體消耗依然很大。 easyexcel重寫了poi對07版Excel的解析,一個3M的excel用POI sax解析依然需要100M左右記憶體,改用easyexcel可以降低到幾M,並且再大的excel也不會出現記憶體溢位;03版依賴POI的sax模式,在上層做了模型轉換的封裝,讓使用者更加簡單方便

  優點:節省記憶體消耗,可大量減少網路開銷

2.使用方法

2.1.引入依賴

<dependency>
     <groupId>com.alibaba</groupId>
     <artifactId>easyexcel</artifactId>
     <version>3.1.0</version>
</dependency>

2.2 匯入

  匯入對應的表格欄位解析實體類:

public class ConfigImportExcelRow implements Serializable {

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

    /**
     * 暱稱
     */
    @ExcelProperty(value = "暱稱", index = 1)
    private String nickName;

    @ExcelProperty(value = "年齡", index = 2)
    private Integer age;

}

  介面範例

@PostMapping("/import")
    public JSONResult import(@RequestParam(name = "file") MultipartFile file, HttpServletResponse response) {
    
    List<ConfigImportExcelRow> userRowList = null;
        try {
            userRowList = EasyExcel.read(file.getInputStream()).headRowNumber(2)
                    .head(ConfigImportExcelRow.class).sheet().doReadSync();
        } catch (Exception e) {
            LOGGER.error("匯入設定異常", e);
        }
        
        return  "匯入結果";
    }

  head()指定Excel行對應的POJO

  sheet() 讀取第一個sheet

  doReadSync() ; 同步讀取會自動finish

  headRowNumber 從頭的第幾行開始讀取:可以設定1,因為頭就是一行。如果多行頭,可以設定其他值。不傳入也可以沒有指定頭,也就是預設1行

 

  當有多個 sheet的時候,可以將 read 改為 readSheet 方法:

  官方範例:

2.3 匯出

  同樣對匯出的實體欄位新增 @ExcelProperty 註解

public class ConfigExportExcelRow implements Serializable {

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

    /**
     * 暱稱
     */
    @ExcelProperty(value = "暱稱", index = 1)
    private String nickName;

    @ExcelProperty(value = "年齡", index = 2)
    private Integer age;

}

  呼叫範例

@GetMapping("/export")
    @ApiOperation(value = "匯出明細")
    public JSONResult importUser(HttpServletResponse response) {
        
        return JSONResult.okResult();
    }
    
    public void exportWorkerPlan(Long cycleId, HttpServletResponse response) {

        try {
            List<ConfigExportExcelRow> excelRowList = new ArrayList<>();
            ConfigExportExcelRow result1 = new ConfigExportExcelRow();
            result1.setUserName("張三");
            result1.setNickName("張三");
            result1.setAge(22);
            excelRowList.add(result1);
            AssessPersonConfigImportResult result2 = new AssessPersonConfigImportResult();
            result2.setUserName("李四");
            result2.setNickName("李四");
            result2.setAge("33");
            excelRowList.add(result2);

            String fileFix = DateUtils.formatDate(System.currentTimeMillis(), DateFormatEnum.YYYYMMDDHHMMSSS);
            String fileName = "匯出結果_" + fileFix;
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            // 這裡URLEncoder.encode可以防止中文亂碼 當然和easyexcel沒有關係
            fileName = URLEncoder.encode(fileName, "UTF-8").replace("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");

            // 內容樣式策略
            WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
            // 垂直居中,水平居中
            contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
            contentWriteCellStyle.setBorderLeft(BorderStyle.THIN);
            contentWriteCellStyle.setBorderTop(BorderStyle.THIN);
            contentWriteCellStyle.setBorderRight(BorderStyle.THIN);
            contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);
            // 字型策略
            WriteFont contentWriteFont = new WriteFont();
            // 字型大小
            contentWriteFont.setFontHeightInPoints((short) 10);
            contentWriteCellStyle.setWriteFont(contentWriteFont);

            //設定輸出流和模板資訊
            File excelTemplate = ResourceUtils.getFile(EXCEL_TEMPLATE_PATH);
            ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream())
                    .registerWriteHandler(new HorizontalCellStyleStrategy(null, contentWriteCellStyle))
                    .excelType(ExcelTypeEnum.XLSX)
                    .withTemplate(excelTemplate).build();
            WriteSheet writeSheet = EasyExcel.writerSheet().build();
            //開啟自動換行,自動換行表示每次寫入一條list資料是都會重新生成一行空行,此選項預設是關閉的,需要提前設定為true
            FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
            excelWriter.fill(excelRowList, fillConfig, writeSheet);
            excelWriter.finish();
        } catch (Exception e) {
            LOGGER.error("匯出Excel失敗, errorMessage={}", e.getMessage(), e);
            throw new BusinessException(ActionStatus.PARAMAS_ERROR.inValue(), "人員設定匯出Excel失敗!");
        }
    }