[英]Excel doesn't close despite objects being released
所以,我写了一个 class 来处理打开 excel 文件,但是即使我调用关闭 function,excel 也没有关闭。这在我开始使用多个工作簿之前就起作用了,所以我认为它与此有关,但我有不知道如何解决这个问题。 任何帮助表示赞赏!
这是代码:
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;
}
}
}
我试过使用GC.Collect()
和GC.WaitForPendingFinalizers()
但这似乎也不起作用。
更新,这就是我修复代码所做的。 随意使用它。 (虽然在调试模式下不起作用)
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);
}
}
简要说明:我删除了 NAR function 和它被调用的任何地方,在我的所有 excel 代码执行后添加了GC.Collect()
和GC.WaitForPendingFinalisers
,并确保在调用 GC.* 函数之前将所有变量设置为 null。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.