2016-07-24 27 views
-2

我剛剛嘗試使用XSSF XLSX2CSV樣本,使用SAX事件API將使用OpenCV的630k行5列電子表格導出爲CSV。 完成操作需要至少70秒(儘管我最初在分析Web服務器時看到20分鐘),而Excel在不到10秒的時間內完成操作。問題的將XLSX導出爲CSV的最快方式

部分原因是org.apache.poi.xssf.eventusermodel.XSSFSheetXMLHandler.SheetContentsHandler界面看起來是這樣的:

/** 
    * You need to implement this to handle the results 
    * of the sheet parsing. 
    */ 
public interface SheetContentsHandler { 
    /** A row with the (zero based) row number has started */ 
    public void startRow(int rowNum); 
    /** A row with the (zero based) row number has ended */ 
    public void endRow(int rowNum); 
    /** 
    * A cell, with the given formatted value (may be null), 
    * and possibly a comment (may be null), was encountered */ 
    public void cell(String cellReference, String formattedValue, XSSFComment comment); 
    /** A header or footer has been encountered */ 
    public void headerFooter(String text, boolean isHeader, String tagName); 
} 

注意你怎麼只有一次一個細胞,而不是一個整體行。 我對此的解決方案是將單元格放入映射中,使用列標題作爲使用endRow寫入行的鍵。

@Override 
public void endRow(int rowNum) { 
    if(currentRow == HEADER_ROW) { 
     processRow(currentRow, columnHeaders); 
    } else { 
     processRow(currentRow, currentRowMap); 
    } 
} 

private void processRow(int currentRow, LinkedHashMap<String, String> map) { 
    String[] nextLine = map.values().toArray(new String[map.size()]); 
    csvWriter.writeNext(nextLine); 
} 

/** 
* POI will not invoke this method if the cell is blank or if it detects there's no more data in the row. 
* Therefore, this is not necessarily invoked the same number of times each row. 
* The startRow method has initialised the currentRowMap to work around this. 
*/ 
@Override 
public void cell(String cellReference, String formattedValue, XSSFComment comment) { 
    if(currentRow == HEADER_ROW) { 
     columnHeaders.put(getColumnReference(cellReference), formattedValue); 
    } else { 
     String columnHeader = columnHeaders.get(getColumnReference(cellReference)); 
     currentRowMap.put(columnHeader, formattedValue); 
    } 
} 

/** 
* Returns the alphabetic column reference from this cell reference. Example: Given 'A12' returns 
* 'A' or given 'BA205' returns 'BA' 
*/ 
private static String getColumnReference(String cellReference) { 

    if (StringUtils.isBlank(cellReference)) { 
     return ""; 
    } 

    return cellReference.split("[0-9]*$")[0]; 
} 

添加並讀取到此映射並獲取每個單元格的列引用稱爲3M時間,效率非常低。

將XLSX導出到CSV有哪些更快的選項?

+4

顯然你做錯了什麼,但沒有看到任何代碼,我們不可能幫助你。此外,由於您的問題現在有了措辭(_「將XLS和XLSX導出爲CSV有哪些更快的選項」),因爲它要求提供外部資源建議,所以它是無關緊要的。 –

+0

該接口需要一個單元格,因爲文件格式一次存儲一個單元格!至於性能,它應該只需要幾秒鐘就可以完成。你在用什麼堆大小? – Gagravarr

+0

我剛剛運行了一個微型基準測試,大約需要2秒才能調用3M次getColumnReference,所以我沒有看到整個文件導出如何在幾秒鐘內完成。 – opticyclic

回答

-2

Perl(Spreadsheet :: ParseExcel)不需要那麼長時間。