【发布时间】:2019-11-15 14:12:29
【问题描述】:
我正在尝试将 DataTable 导出到 Microsoft Excel 2016,并且我的代码“成功”运行了一次。当它运行时,我试图打开 Excel 文件,它告诉我文件格式无效(试图导出到XLSX)。这完全是另一个问题,但我将其包括在内以防万一它有任何帮助。
以下每次尝试导出时,代码都会抛出 COMException 并显示以下消息:
无法访问“System.IO.MemoryStream”。
堆栈跟踪显示:
在 Microsoft.Office.Interop.Excel._Workbook.SaveAs(对象文件名、对象文件格式、对象密码、对象 WriteResPassword、对象 ReadOnlyRecommended、对象 CreateBackup、XlSaveAsAccessMode 访问模式、对象 ConflictResolution、对象 AddToMru、对象 TextCodepage、对象 TextVisualLayout、对象本地)
在 C:\...\PageName.aspx.cs:line 279 中的 MyNamespace.btnExportToExcel_Click(Object sender, EventArgs e)
这两者都对调试进程没有帮助。我遇到过 Stream 对象在尝试重新打开之前没有关闭的异常情况,这很容易解决,这里有很多关于此的问题。
我在using 语句中创建流,即使发生异常,它也应该自动关闭并处理Stream。尽管如此,我还尝试手动将Close 和Dispose 添加到我的代码的finally 块中,但仍然抛出异常。
using (MemoryStream fs = new MemoryStream()) {
try {
Excel.Application xlApp = new Excel.Application();
Excel.Workbook xlWorkBook = xlApp.Workbooks.Add(Missing.Value);
var xlSheets = xlWorkBook.Sheets as Excel.Sheets;
var xlNewSheet = (Excel.Worksheet)xlSheets.Add(xlSheets[1], Type.Missing, Type.Missing, Type.Missing);
xlNewSheet.Name = "newsheet";
System.Data.DataTable dt = (System.Data.DataTable)excelGrid.DataSource;
for (int x = 0; x < dt.Rows.Count; x++)
for (int y = 0; y < dt.Columns.Count; y++)
xlNewSheet.Cells[x + 1, y + 1] = dt.Rows[x][y];
xlWorkBook.SaveAs((Stream)fs); // Exception is thrown here.
fs.Position = 0;
string myName = Server.UrlEncode(SearchTitle + ".xlsx");
Response.Clear();
Response.Buffer = true;
Response.AddHeader("content-disposition", "attachment; filename=" + myName);
Response.ContentType = "application/vnd.ms-excel";
Response.BinaryWrite(fs.ToArray());
Response.End();
xlWorkBook.Close(true, Missing.Value, Missing.Value);
xlApp.Quit();
} catch (ThreadAbortException) {
// This exception is throw from Response.End by design. Gracefully ignore it.
} catch (Exception ex) {
// Log exception.
throw ex;
} finally {
fs.Close();
fs.Dispose();
}
}
我认为也许重新启动我的调试会话会起作用,但这也没有解决问题。
是什么导致COMException 与消息Cannot access 'System.IO.MemoryStream' 被抛出?
【问题讨论】:
-
听起来你忘了处理不止一件 Disposeable 的东西。
-
正如您从异常中看到的,在您的情况下,SaveAs 方法应该将文件路径字符串作为其唯一参数。查找和使用正确的文件类型(第二个参数)通常更安全。然后将保存的文件写入您的响应。然后处理您创建的临时文件。
标签: c# excel exception comexception