我正在使用互操作库从一张excel文件中读取一些数据。我通过使用Microsoft.Office.Interop.Excel
然后读取表格中的所有数据来获得数据。
Application ExcelApp = new Excel.Application();
Workbook excelWorkbook = ExcelApp2.Workbooks.Open(excelFileNamePath);
_Worksheet excelWorksheet = excelWorkbook.Sheets[excelSheetName];
Range excelRange = excelWorksheet.UsedRange;
//...for loops for reading data
ExcelApp.Quit();
但是在我的应用程序终止后,我尝试编辑我的excel文件并在打开时遇到一些问题。显然,即使我调用ExcelApp.Quit()
,excel进程仍在后台运行。有没有办法正确关闭应用程序使用的excel文件?我是c#的新手,所以我可能在这里遗漏了一些东西。
编辑:解决了!显然有一个rule的com对象不鼓励使用2个点。
Excel.Application ExcelApp2 = new Excel.Application();
Excel.Workbooks excelWorkbooks = ExcelApp2.Workbooks;
Excel.Workbook excelWorkbook = excelWorkbooks.Open(excelFileName);
Excel._Worksheet excelWorksheet = excelWorkbook.Sheets[excelSheetName];
//...
excelWorkbook.Close();
Marshal.ReleaseComObject(excelWorkbook);
Marshal.ReleaseComObject(excelWorksheet);
Marshal.ReleaseComObject(excelRange);
ExcelApp2.Quit();
答案 0 :(得分:9)
还有另一个类似的问题 - 并回答(https://stackoverflow.com/a/17367570/3063884),其中解决方案是避免使用双点表示法。相反,为沿途使用的每个对象定义变量,并在每个对象上单独使用Marshal.ReleaseComObject
。
直接从链接的解决方案中复制:
var workbook = excel.Workbooks.Open(/*params*/)
--->而是使用 - >
var workbooks = excel.Workbooks;
var workbook = workbooks.Open(/*params*/)
然后,完成后,释放每个COM对象:
Marshal.ReleaseComObject(workbook);
Marshal.ReleaseComObject(workbooks);
Marshal.ReleaseComObject(excel);
答案 1 :(得分:1)
您没有关闭工作簿。关闭它,然后在退出Excel应用程序之前将其释放:
excelWorkbook.close();
Marshal.ReleaseComObject(excelWorkbook);
ExcelApp.Quit();
答案 2 :(得分:1)
很久没有回答,但对我有用的是调用GC.Collect();来自来电者,
即。而不是
main()
{
...
doexcelstuff();
...
}
void doexcelstuff()
{
Excel.Application ExApp2 = new Excel.Application();
Excel.Workbook excelWb = ExApp2 .Workbooks.Open(excelFName);
Excel._Worksheet excelWorksheet = excelWb.Sheets[excelSName];
//...
excelWb.Close();
ExApp2.Quit();
Marshal.ReleaseComObject(excelWb);
Marshal.ReleaseComObject(excelWorksheet);
Marshal.ReleaseComObject(ExApp2);
excelWb = null;
excelWorksheet= null;
ExApp2= null;
GC.Collect();
}
使用上面的Excel不会死亡
但是从
调用GC的位置变化非常小main()
{
...
doexcelstuff();
GC.Collect(); // <<-- moved the GC to here (the caller)
...
}
void doexcelstuff()
{
Excel.Application ExApp2 = new Excel.Application();
Excel.Workbook excelWb = ExApp2 .Workbooks.Open(excelFName);
Excel._Worksheet excelWorksheet = excelWb.Sheets[excelSName];
//...
excelWb.Close();
ExApp2.Quit();
Marshal.ReleaseComObject(excelWb);
Marshal.ReleaseComObject(excelWorksheet);
Marshal.ReleaseComObject(ExApp2);
excelWb = null;
excelWorksheet= null;
ExApp2= null;
// removed the GC from here
}
我的猜测是垃圾收集器还需要从堆中安静地清理内部创建的临时值(包括引用/指针) - 其中一些我想在这种情况下指向COM对象。
(只需了解机器如何在源代码下工作。)
答案 3 :(得分:1)
这对我来说很有效!
//Initializing
Application excelApp = new Application();
Workbook excelWorkbook = excelApp.Workbooks.Open(pathExcelFile, 0, true, 5, "", "",
true, XlPlatform.xlWindows, "\t", false, false, 0,
true, 1, 0);
Worksheet excelWorksheet = (Worksheet)excelWorkbook.Sheets[1];
//closing
excelWorksheet = null;
excelWorkbook.Close();
excelWorkbook = null;
excelApp.Quit();
excelApp = null;
答案 4 :(得分:0)
Interop是出了名的错误...我保存工作簿后使用以下方法,退出应用程序时Excel不再存在问题:
while (Marshal.ReleaseComObject(wb) > 0);
while (Marshal.ReleaseComObject(xl) > 0);
wb = null;
xl = null;
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
wb是我的工作簿对象,xl是我的Excel.Application对象。