2011-06-07 49 views
3

我在ASP.NET應用程序中使用NPOI 1.2.3.0將相當大的SQL查詢的結果導出到Excel 2003 XLS文件。生成大型Excel電子表格時出現OutOfMemoryException

總之,查詢結果被填充到一個ADO.NET DataTable中。然後我有一個例程循環遍歷DataTable中的行,併爲每行添加一行到NPOI電子表格。足夠智能的是,對於單張紙來說,一旦超過65,000行,就會創建一張新的紙張,並且行在那裏繼續,從新紙張的第一行開始。

這種方法適用於我的一些小型數據庫查詢,其中包括例如30,000行和50列,但我有這樣一個查詢返回125,000行以北,大約有50列,其中許多列有很好的文本交易。

我可以毫無問題地構建電子表格,但是當我嘗試將生成的電子表格下載到瀏覽器時,我在調用HSSFWorkbook類的Write方法時得到OutOfMemoryException。 (在內部,當Write方法調用類的GetBytes方法時,錯誤發生。)

如果在調用Write方法之前運行調試器並停止,則會看到工作簿的Size屬性返回值(大致) 6500萬。

在CodePlex的NPOI項目中注意到這個錯誤 - 請參閱標題爲Out of Memory Problems的討論 - 但不幸的是沒有找到解決方案。

爲了完整,以下是引發異常的代碼(具體而言,它是在workbook.Write行中引發的)。

Using exportData As New MemoryStream() 
    workbook.Write(exportData) 

    Response.ContentType = "application/vnd.ms-excel" 
    Response.AddHeader("Content-Disposition", "Attachment;Filename=" & saveAsName) 
    Response.Clear() 
    Response.BinaryWrite(exportData.GetBuffer()) 
    Response.End() 
End Using 

謝謝!

+1

嗨斯科特 - 我記得在容量方面讀了關於內存流對象的限制,我認爲在32位環境下這是512MB。您是否嘗試將Excel文檔寫入不同類型的流? – 2011-06-07 20:05:32

+0

如果這確實是內存流本身的一個限制,你可以使用Win32 api的包裝來避免Disk IO,如果你需要:例如:https://github.com/tomasr/filemap – 2011-06-07 20:33:25

+0

@Dave,使用FileStream將其寫入磁盤不會導致任何錯誤併成功生成電子表格。聽起來像MemoryStream可能是罪魁禍首。生產環境是64位的,所以我不知道FileMap類是否可行。 – 2011-06-07 21:48:08

回答

1

在這種情況下我會做什麼,記住FileStream對象不會導致錯誤,並且錯誤是由32位和64位的2GB限制中的512MB容量限制引起的,請嘗試並將該文件寫入memoryStream,如果遇到錯誤,則捕獲錯誤並恢復爲FileStream以查找較大的文件。

有一個明顯的性能權衡這裏,但如果你的用戶正在下載> 2GB的文件,所以它們可能希望這是慢一點:-)

很想知道這對你的作品。

感謝, 戴夫

+0

讓我困惑的一件事是生成的Excel文件大小約爲85 MB。我不清楚這個大小的Excel文檔如何超過512MB的限制。 – 2011-06-09 16:22:15

+0

嗨斯科特 - 這是一個困難的,說實話,我也不知道。如果我不得不猜測,我認爲它與HSSPWorkbook將數據緩衝到內存流中的方式有​​關,那麼可能會出現某種填充,但不知道實現的具體細節還不清楚。這也可能與COMInterop有關,但我只是在這裏猜測......當我得到一些時間並且一定會讓你知道什麼時候,我會更詳細地研究一下它。我發現。 – 2011-06-10 05:56:32

0

NPOI不僅使用的MemoryStream也是字節數組。主要的根本原因是字節數組。但是到目前爲止,NPOI必須使用字節數組。目前還沒有計劃改變這一點。給您造成的任何不便,請原諒。