使用開源計算引擎提升Excel格式文件處理效率

對Excel進行解析\生成\查詢\計算等處理是Java下較常見的任務,但Excel的文件格式很復雜,自行編碼讀寫太困難,有了POI\EasyExcel\JExcel等類庫就方便多了 , 其中POI最為出色 。
POI具有全面而細致的xls讀寫能力POI可讀寫多種Excel文件格式 , 既支持古老的二進制格式(xls) , 也支持現代的OOXML格式(xlsx),既支持全內存一次性讀寫 , 也支持小內存流式讀寫 。POI為大量Excel元素設計了相應的JAVA類,包括workbook、printer、sheet、row、cell , 其中,與cell相關的類包括單元格樣式、字體、顏色、日期、對齊、邊框等 。僅單元格樣式類,方法就超過了四十個,可進行最全面最細致的讀寫操作 。
POI的讀寫功能很底層POI的讀寫功能全面而細致,但細致也意味著過于底層,開發者必須從頭寫起,自己處理每一處細節,即使簡單的操作也要編寫大量代碼 。比如,讀入首行為列名的行式xls:
FileInputStream fileInputStream = new FileInputStream("d:\\Orders.xls");// get the excel bookWorkbook workbook = new HSSFWorkbook(fileInputStream);if (workbook != null) {// get the first sheetSheet sheet = workbook.getSheetAt(0);if (sheet != null) {//get the col name/first lineRow rowTitle = sheet.getRow(0); // first lineif (rowTitle != null) {int cellTitles = rowTitle.getPhysicalNumberOfCells(); // get column numberfor (int i = 0; i < cellTitles; i++) {Cell cell = rowTitle.getCell(i); //the cell!if (cell != null) {System.out.print(cell.getStringCellValue() + " | ");}}}//get the value/other linesint rows = sheet.getPhysicalNumberOfRows(); // get line numberfor (int i = 1; i < rows; i++) {Row row = sheet.getRow(i); // get row iif (row != null) {int cells = row.getPhysicalNumberOfCells(); // get column numberfor (int j = 0; j < cells; j++) {// line number and row numberSystem.out.print("[" + i + "-" + j + "]");Cell cell = row.getCell(j); // the cell!if (cell != null) {int cellType = cell.getCellType();Object valuehttps://www.huyubaike.com/biancheng/= "";switch (cellType) {case HSSFCell.CELL_TYPE_STRING: // stringvalue = https://www.huyubaike.com/biancheng/cell.getStringCellValue();break;case HSSFCell.CELL_TYPE_BLANK: // 空break;case HSSFCell.CELL_TYPE_BOOLEAN: // booleanvalue = cell.getBooleanCellValue();break;case HSSFCell.CELL_TYPE_NUMERIC: // numberif (HSSFDateUtil.isCellDateFormatted(cell)) { // date numberDate date = cell.getDateCellValue();value = new DateTime(date).toString("yyyy-MM-dd HH:mm:ss");}else { // normal number// change to string to avoid being too longcell.setCellType(HSSFCell.CELL_TYPE_STRING);value = https://www.huyubaike.com/biancheng/cell;}break;case HSSFCell.CELL_TYPE_ERROR:throw new RuntimeException("data type mistaken");}System.out.println(value);}}}System.out.println("end of the "+i+" line");}System.out.println("end of the value lines=======================================");}}行式xls是最常見的格式,但POI并沒有為此提供方便的處理方法,只能按照workbook->sheet->line->cell的順序進行循環解析,造成了如此繁瑣的代碼 。
這還只是將數據簡單讀出來 , 如果下一步想再處理數據,還要事先轉為結構化數據對象,比如ArrayList<實體類>或HashMap,代碼就更繁瑣了 。
POI查詢計算困難解析Excel并不是目標,我們通常還要對這些文件進查詢計算 , 但POI作為Excel的解析類,沒有也不合適再提供相關的方法,只能用JAVA手工硬寫 。比如基礎的分組匯總運算,JAVA代碼大概這樣:
【使用開源計算引擎提升Excel格式文件處理效率】Comparator<salesRecord> comparator = new Comparator<salesRecord>() { public int compare(salesRecord s1, salesRecord s2) {if (!s1.salesman.equals(s2.salesman)) {return s1.salesman.compareTo(s2.salesman);} else {return s1.ID.compareTo(s2.ID);} }};Collections.sort(sales, comparator);ArrayList<resultRecord> result=new ArrayList<resultRecord>();salesRecord standard=sales.get(0);float sumValue=https://www.huyubaike.com/biancheng/standard.value;for(int i = 1;i < sales.size(); i ++){ salesRecord rd=sales.get(i); if(rd.salesman.equals(standard.salesman)){sumValue=sumValue+rd.value; }else{result.add(new resultRecord(standard.salesman,sumValue));standard=rd;sumValue=standard.value; }}result.add(new resultRecord(standard.salesman,sumValue));Java編碼實現計算不僅繁瑣,而且存在架構性缺陷 。代碼很難復用,數據結構和計算代碼通常會耦合在一起 , 如果數據結構發生變化,代碼就要重寫 。查詢計算的要求靈活多變,而Java作為編譯型語言,每次修改代碼都要重啟應用,維護工作量大,系統穩定性差 。
POI成熟穩定,但讀寫能力過于底層,且未提供查詢計算能力,直接基于POI完成Excel文件的處理(特別是查詢計算)的開發效率很低 。如果針對POI進行封裝,形成簡單易用的高級讀寫函數,并額外提供查詢計算能力,就能大幅度提高開發效率了 。

推薦閱讀