这个 正在工作......我把处理代码移到了finally块,现在每次都失败了。
我有一个测试电子表格,有4条记录,长6列。这是我用来引入它的代码。这是IIS 5(我的电脑)和IIS 6(网络服务器)上的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;
答案 0 :(得分:5)
我不确定这是不是你的问题,但很可能是。您没有正确清理excel对象。它们是非托管代码,清理起来可能很棘手。最后应该看起来像这样:并且评论已经注意到使用asp.net的excel并不是一个好主意。此清理代码来自winform app:
GC.Collect();
GC.WaitForPendingFinalizers();
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(range);
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(sheet);
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(book);
WB.Close(false, Type.Missing, Type.Missing);
Excel.Quit();
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(Excel);
修改强>
另一种方法是使用ado.net打开工作簿。
DataTable dt = new DataTable();
string connectionString;
System.Data.OleDb.OleDbConnection excelConnection;
System.Data.OleDb.OleDbDataAdapter da;
DataTable dbSchema;
string firstSheetName;
string strSQL;
connectionString = @"provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + filename + @";Extended Properties=""Excel 12.0;HDR=YES;IMEX=1""";
excelConnection = new System.Data.OleDb.OleDbConnection(connectionString);
excelConnection.Open();
dbSchema = excelConnection.GetOleDbSchemaTable(System.Data.OleDb.OleDbSchemaGuid.Tables, null);
firstSheetName = dbSchema.Rows[0]["TABLE_NAME"].ToString();
strSQL = "SELECT * FROM [" + firstSheetName + "]";
da = new OleDbDataAdapter(strSQL, excelConnection);
da.Fill(dt);
da.Dispose();
excelConnection.Close();
excelConnection.Dispose();
答案 1 :(得分:1)
在每个请求上创建/销毁excel将会对你的工作产生绝对可怕的性能。一般来说,使用自动化运行任何Office应用程序都是一项令人讨厌的业务,原因很多(参见here)。我让它工作的唯一方法是有一个应用程序的单个实例(在我的例子中是Word),它被初始化一次,然后请求排队到这个实例进行处理
如果您可以远离应用程序并自行解析文件(使用MS库,仅使用XML)
答案 2 :(得分:1)
使用ASP.NET中的interop会遇到很多麻烦。除非这是针对一些微小的内部应用,否则建议不要继续使用它。
Office Interop不是传统意义上的编程API - 它是Office宏系统的最大化,具有处理进程间的能力 - 例如Excel宏可以与Outlook交互。使用互操作的一些后果是:
所有这些都使得互操作能够避免常规桌面应用程序,并且应该只用作服务器应用程序的最后手段,因为需要操作或脚本泄漏进程的GUI弹出窗口是服务器环境中的谋杀。 / p>
一些替代方案包括:
答案 3 :(得分:0)
错误可能正是它所说的,你得到的内存不足错误。尝试将values数组的加载拆分为几个较小的块,而不是一次获取整个Range。我在C#中尝试了你的代码并且没有任何问题,但我加载的电子表格大多是空的。
我注意到Range虽然是整个电子表格(从A2到IV65536或其他东西)。我不确定是否有意。
您可以尝试使用的一件事是sheet.UsedRange,它将减少您正在加载的单元格数量。
我学到的另外一些你可能会觉得有用的小东西: