这工作......我把处理代码移到了finally块,现在每次都失败了 .
我有一个测试电子表格,有4条记录,长6列 . 这是我用来引入它的代码 . 这是IIS 5(我的电脑)和IIS 6(Web服务器)上的ASP .Net 3.5 .
它在捕获之前的线上爆炸:“values =(object [,])range.Value2;”出现以下错误:
11/2/2009 8:47:43 AM :: Not enough storage is available to complete this operation. (Exception from HRESULT: 0x8007000E (E_OUTOFMEMORY))
有任何想法吗?建议?我从codeproject中获取了大部分代码,所以我不知道这是否是使用Excel的正确方法 . 感谢您的任何帮助,您可以提供 .
这是我的代码:
Excel.ApplicationClass app = null;
Excel.Workbook book = null;
Excel.Worksheet sheet = null;
Excel.Range range = null;
object[,] values = null;
try
{
// Configure Excel
app = new Excel.ApplicationClass();
app.Visible = false;
app.ScreenUpdating = false;
app.DisplayAlerts = false;
// Open a new instance of excel with the uploaded file
book = app.Workbooks.Open(path);
// Get first worksheet in book
sheet = (Excel.Worksheet)book.Worksheets[1];
// Start with first cell on second row
range = sheet.get_Range("A2", Missing.Value);
// Get all cells to the right
range = range.get_End(Excel.XlDirection.xlToRight);
// Get all cells downwards
range = range.get_End(Excel.XlDirection.xlDown);
// Get address of bottom rightmost cell
string downAddress = range.get_Address(false, false, Excel.XlReferenceStyle.xlA1, Type.Missing, Type.Missing);
// Get complete range of data
range = sheet.get_Range("A2", downAddress);
// get 2d array of all data
values = (object[,])range.Value2;
}
catch (Exception e)
{
LoggingService.log(e.Message);
}
finally
{
// Clean up
range = null;
sheet = null;
if (book != null)
book.Close(false, Missing.Value, Missing.Value);
book = null;
if (app != null)
app.Quit();
app = null;
}
return values;
4 回答
我不确定这是不是你的问题,但很可能是 . 您没有正确清理excel对象 . 它们是非托管代码,清理起来可能很棘手 . 最后应该看起来像这样:并且评论已经注意到使用asp.net的excel并不是一个好主意 . 此清理代码来自winform应用程序:
EDIT
另一种方法是使用ado.net打开工作簿 .
在每个请求上创建/销毁excel对于你所做的事情都将具有绝对可怕的性能 . 通常,使用自动化运行任何Office应用程序都是一项令人讨厌的业务,原因很多(参见here) . 我让它工作的唯一方法是有一个应用程序的单个实例(在我的情况下是Word)初始化一次,然后请求排队到这个实例进行处理
如果你可以远离应用程序并自己解析文件(使用MS库,只需XML)
使用ASP.NET中的interop会遇到很多麻烦 . 除非这是针对一些微小的内部应用,否则建议不要继续使用它 .
Office Interop不是传统意义上的编程API - 它是Office宏系统的最大化,具有处理进程间的能力 - 例如Excel宏可以与Outlook交互 .
使用互操作的一些后果是:
您实际上是在打开办公室应用程序的完整副本 .
应用程序正在执行您的操作,就像用户启动它们一样 - 这意味着代替在代码中返回的错误消息,它们将显示在GUI中 .
只有在您明确命令时才会关闭应用程序的副本 - 即使这样,错误也可能阻止实际发生(如果您没有可编程地告诉Excel不需要保存更改,则应用程序可能会显示"do you want to save"对话框) . 这通常会导致许多隐藏的Excel副本在系统上运行 - 打开任务管理器并查看正在运行的excel.exe进程数 .
所有这些都使得互操作可以避免常规桌面应用程序,并且应该仅用作服务器应用程序的最后手段,因为需要操作或脚本泄漏进程的GUI弹出窗口是服务器环境中的谋杀 .
一些替代品包括:
使用基于Microsoft Office 2007 XML的格式,以便您可以自己编写XML文件 .
使用SpreadsheetGear.Net,这是一个.NET二进制Excel文件读取器/写入器(您不需要安装Excel,因为它完全独立) . 在Intertop接口之后,SpreadsheetGear会自行建模,以便更容易地转换旧代码 .
错误可能正是它所说的,你得到的内存不足错误 . 尝试将values数组的加载拆分为几个较小的块,而不是一次获取整个Range . 我在C#中尝试了你的代码并且没有任何问题,但我加载的电子表格大多是空的 .
我注意到Range虽然是整个电子表格(从A2到IV65536或其他东西) . 我不确定这是不是故意的 .
您可以尝试使用的一件事是sheet.UsedRange,它将减少您正在加载的单元格数量 .
我学到的其他一些小东西你可能会觉得有用:
使用Application而不是ApplicationClass
使用Marshal.FinalReleaseComObject(范围)(以及工作表,书籍,应用程序),否则您将有EXCEL.EXE过程 .