[英]Excel doesn't close despite objects being released
So, I have a class that I wrote to handle opening excel files, however excel doesn't close even though I call the close function. This worked before I started using multiple workbooks so I presume that its something to do with that but I have no idea how to fix this.所以,我写了一个 class 来处理打开 excel 文件,但是即使我调用关闭 function,excel 也没有关闭。这在我开始使用多个工作簿之前就起作用了,所以我认为它与此有关,但我有不知道如何解决这个问题。 Any help appreciated!任何帮助表示赞赏!
This is the code:这是代码:
public class ExcelReaderClass
{
public Excel.Application? excelApp = null; // create a null excell object that will later be used to store the reference to the open excel app
public Excel.Workbooks? excelBooks = null; // create a null object collection that will contain all workbooks
public Excel.Workbook? excelBook = null; // create a null object that will contain a workbook (excel file)
public Excel.Worksheet? curWorksheet = null; // create a null worksheet object that will contain the reference to the current worksheet that is open
public Excel.Range? curWorksheetRange = null; // create a range object that will contain the data from the currently open worksheet
// function that opens excel file and opens excel if it isnt already open
public void openExcelFile(string filePath) // filePath = filepath for the worksheet that is to be opened
{
if(excelApp == null) // if excel isnt open
{
excelApp = new Excel.Application(); // create a new instance of excel
excelApp.DisplayAlerts = false; // prevents "do you want to save" popups, which we want because we are only looking at files not changing them
excelBooks = excelApp.Workbooks; // create a new instance of workbook object collection
}
excelBook = excelBooks.Add(filePath); // add the workbook to the collection
}
// function that closes all instances of excel opened by this program
public void closeExcelFile(bool save, bool closeAll) // bool that controls whether only the worksheet is closed or the whole instance of excel
{
//excelBook.Save(); // save function not needed in this instance but might be useful later
GC.Collect();
GC.WaitForPendingFinalizers();
foreach (Excel.Workbook workbook in excelBooks)
{
workbook.Close(save, System.Reflection.Missing.Value, System.Reflection.Missing.Value); // close the workbook
NAR(workbook);
}
NAR(excelBooks); ; // release the workbook collection from Com
NAR(excelBook);
NAR(curWorksheet);
NAR(curWorksheetRange);
if (closeAll) // if close all is true, we want to close the excel instance too
{
excelApp.Quit(); // quit out of excel
NAR(excelApp); // release excel from Com
}
}
public List<object[,]> readExcelFile(string[] filePaths) //
{
List<object[,]> rangeList = new List<object[,]>(); // list of objects that will contain the data from the excel sheets
foreach (var filePath in filePaths) // for each file
{
openExcelFile(filePath); // open the file in excel
}
foreach (var workbook in excelBooks) // iterate through workbooks
{
var book = workbook as Excel.Workbook; // set book as a reference to the workbook
curWorksheet = book.Worksheets[1]; // set this variable to the first sheet in the workbook
curWorksheetRange = curWorksheet.UsedRange; // set this variable to the workbook range
object[,]? range = (object[,])curWorksheetRange.Value2;
rangeList.Add(range);
}
closeExcelFile(false,true);
return (rangeList);
}
//function to kill object and release it from COM
private void NAR(object o)
{
try
{
Marshal.FinalReleaseComObject(o);
}
catch { }
finally
{
o = null;
}
}
}
I've tried using GC.Collect()
and GC.WaitForPendingFinalizers()
but that doesn't seem to work either.我试过使用GC.Collect()
和GC.WaitForPendingFinalizers()
但这似乎也不起作用。
Update, this is what I did to fix the code.更新,这就是我修复代码所做的。 Feel free to use it.随意使用它。 (Doesn't work in Debug mode though) (虽然在调试模式下不起作用)
public class ExcelReaderClass
{
public Excel.Application? excelApp = null; // create a null excell object that will later be used to store the reference to the open excel app
public Excel.Workbooks? excelBooks = null; // create a null object collection that will contain all workbooks
public Excel.Workbook? excelBook = null; // create a null object that will contain a workbook (excel file)
public Excel.Worksheet? curWorksheet = null; // create a null worksheet object that will contain the reference to the current worksheet that is open
public Excel.Range? curWorksheetRange = null; // create a range object that will contain the data from the currently open worksheet
// function that opens excel file and opens excel if it isnt already open
public void openExcelFile(string filePath) // filePath = filepath for the worksheet that is to be opened
{
if(excelApp == null) // if excel isnt open
{
excelApp = new Excel.Application(); // create a new instance of excel
excelApp.DisplayAlerts = false; // prevents "do you want to save" popups, which we want because we are only looking at files not changing them
excelBooks = excelApp.Workbooks; // create a new instance of workbook object collection
}
excelBook = excelBooks.Add(filePath); // add the workbook to the collection
}
// function that closes all instances of excel opened by this program
public void closeExcelFile(bool save, bool closeAll) // bool that controls whether only the worksheet is closed or the whole instance of excel
{
foreach (Excel.Workbook workbook in excelBooks)
{
workbook.Close(save, System.Reflection.Missing.Value, System.Reflection.Missing.Value); // close the workbook
}
excelBooks = null; // clear the reference to the workbook collection
excelBook = null; // clear the reference to the active workbook
curWorksheet = null; // clear the reference to the current worksheet
curWorksheetRange = null; // clear the reference to the range of the current worksheet
if (closeAll) // if close all is true, we want to close the excel instance too
{
excelApp.Quit(); // quit out of excel
excelApp = null;
}
}
public List<object[,]> readExcelFile(string[] filePaths)
{
List<object[,]> rangeList = new List<object[,]>();
foreach (var filePath in filePaths)
{
openExcelFile(filePath);
}
Console.WriteLine();
foreach (var workbook in excelBooks) // done to select the first workbook because other methods have failed but this works
{
var book = workbook as Excel.Workbook; // set book as a reference to the workbook
curWorksheet = book.Worksheets[1]; // set this variable to the first sheet in the workbook
curWorksheetRange = curWorksheet.UsedRange; // set this variable to the workbook range
object[,]? range = (object[,])curWorksheetRange.Value2;
rangeList.Add(range);
}
closeExcelFile(false,true);
GC.Collect();
GC.WaitForPendingFinalizers();
return (rangeList);
}
}
Quick Rundown: I deleted the NAR function and any places it was called, added GC.Collect()
and GC.WaitForPendingFinalisers
after all my excel code is executed, and made sure all variables are set to null before GC.* functions are called.简要说明:我删除了 NAR function 和它被调用的任何地方,在我的所有 excel 代码执行后添加了GC.Collect()
和GC.WaitForPendingFinalisers
,并确保在调用 GC.* 函数之前将所有变量设置为 null。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.