1. 程式人生 > >Java POI大資料量的Excel匯入匯出

Java POI大資料量的Excel匯入匯出

  1. 大資料量的匯入

當Excel中的資料量超過10萬行時,在用POI讀取檔案流時很容易引起失敗,需要引入xlsx-streamer來進行資源的開啟,剩下的處理同POI處理上百行資料量類似:filePath=>FileInputStream=>Workbook=>Sheet=>Row=>Cell=>Java反射獲取值。

 <dependency>        <groupId>com.monitorjbl</groupId>        <artifactId>xlsx-streamer</artifactId>        <version>1.2.1</version> </dependency>  

  /**      * 主要針對超過10萬行要解析的Excel的Workbook獲取;      *       * 快取到記憶體中的行數,預設是10行;      *       * 讀取資源時快取到記憶體的位元組大小,預設是1024;      *       * 資源必須開啟,InputStream或者File都可以,但是隻能開啟XLSX格式的檔案      *       * @param filePath      * @return      * @throws Exception      */     public static Workbook obtainWorkbookByStreamm(String filePath) throws Exception {         // StreamingReader用於讀取Excel的內容,不能寫入,不能隨機讀取Excel的內容         FileInputStream in = new FileInputStream(filePath);         Workbook workbook = StreamingReader.builder().rowCacheSize(100).bufferSize(4096).open(in);         return workbook;     }

2. 大資料量的匯出

分而治之的思想,將大資料量分批次的匯出到多個Excel檔案或者單個Excel檔案的多個sheet,也可匯出到多個Excel檔案後合併從單獨的檔案。

/**  * 可選擇是分批次Excel匯出和多Sheet匯出;  *   * @author LEric  */ public abstract class HugeDataExcelExportUtil {

    public void handleMulti(HugeDataExcelOutputDomain domain) throws IOException {         int totalRowNums = domain.getTotalRowNums();         int filterRowNums = domain.getFilterRowNums();         String fileName = new String(domain.getFileName().getBytes("ISO-8859-1"), Charset.defaultCharset());         String filePath = domain.getFilePath();

        File file = new File(filePath);         if (!file.exists()) {             file.mkdirs();         }         if (filterRowNums >= totalRowNums) {             filterRowNums = totalRowNums;         }         int tempsize = (totalRowNums % filterRowNums) == 0 ? totalRowNums / filterRowNums                 : totalRowNums / filterRowNums + 1;

        String tempExcelFile = filePath + fileName + ".xlsx";         FileOutputStream fos = new FileOutputStream(tempExcelFile);         // 在記憶體當中保持 100 行 , 超過的資料放到硬碟中         SXSSFWorkbook workbook = new SXSSFWorkbook(100);

        for (int i = 0; i < tempsize; i++) {             Map<String, Object> params = new HashMap<>();             params.put("limit", i * filterRowNums);             if (i == (totalRowNums / filterRowNums)) {                 params.put("offset", totalRowNums);             } else {                 params.put("offset", (i + 1) * filterRowNums);             }             List<Map<String, Object>> dataList = getData(params);             workbook = exportDataToExcel(workbook, dataList, i);         }

        try {             workbook.write(fos);             fos.flush();         } catch (Exception e) {             throw new ExcelHandleException(e);         } finally {             if (Objects.nonNull(fos)) {                 fos.close();             }             if (Objects.nonNull(workbook)) {                 workbook.dispose();             }         }     }

    @SuppressWarnings("resource")     public void handle(HugeDataExcelOutputDomain domain) throws IOException {         int totalRowNums = domain.getTotalRowNums();         int filterRowNums = domain.getFilterRowNums();         String fileName = new String(domain.getFileName().getBytes("ISO-8859-1"), Charset.defaultCharset());         String filePath = domain.getFilePath();

        File file = new File(filePath);         if (!file.exists()) {             file.mkdirs();         }         if (filterRowNums >= totalRowNums) {             filterRowNums = totalRowNums;         }         int tempsize = (totalRowNums % filterRowNums) == 0 ? totalRowNums / filterRowNums                 : totalRowNums / filterRowNums + 1;

        for (int i = 0; i < tempsize; i++) {             Map<String, Object> params = new HashMap<>();             params.put("limit", i * filterRowNums);             if (i == (totalRowNums / filterRowNums)) {                 params.put("offset", totalRowNums);             } else {                 params.put("offset", (i + 1) * filterRowNums);             }             List<Map<String, Object>> dataList = getData(params);             String tempExcelFile = filePath + fileName + "[" + (i + 1) + "].xlsx";             FileOutputStream fos = new FileOutputStream(tempExcelFile);

            // 在記憶體當中保持 100 行 , 超過的資料放到硬碟中             SXSSFWorkbook workbook = new SXSSFWorkbook(100);             try {                 workbook = exportDataToExcel(workbook, dataList, i);                 workbook.write(fos);                 fos.flush();             } catch (Exception e) {                 throw new ExcelHandleException(e);             } finally {                 if (Objects.nonNull(fos)) {                     fos.close();                 }                 if (Objects.nonNull(workbook)) {                     workbook.dispose();                 }             }         }     }

    public abstract List<Map<String, Object>> getData(Map<String, Object> params);

    public abstract Map<String, Object> getHeaderMetadata();

    /**      * 可利用反射動態匹配對映實現      *       * @param workbook      * @param dataList      * @param size      * @return      */     public SXSSFWorkbook exportDataToExcel(SXSSFWorkbook workbook, List<Map<String, Object>> dataList, int size) {         Map<String, Object> objects = getHeaderMetadata();         String[] headNames = (String[]) objects.get("headNames");         String[] headEngNames = (String[]) objects.get("headEngNames");         String sheetName = (String) objects.get("sheetName");

        Cell cell = null;         Sheet sheet = workbook.createSheet(sheetName);         Row row = sheet.createRow(0);         for (int i = 0; i < headNames.length; i++) {             cell = row.createCell(i);             cell.setCellValue(headNames[i]);         }

        if (Objects.nonNull(dataList) && dataList.size() > 0 && !dataList.isEmpty()) {             int rowIndex = 1;             for (Map<String, Object> map : dataList) {                 row = sheet.createRow(rowIndex++);                 int index = 0;                 for (int i = 0; i < headEngNames.length; i++) {                     cell = row.createCell(index++);                     cell.setCellType(CellType.STRING);                     cell.setCellValue(("" + map.get(headEngNames[i])).replace("null", ""));                 }             }         }         return workbook;     } }