Reputation: 115
I'm reading some data from a sheet of an excel file using interop library. I get the data just fine by using Microsoft.Office.Interop.Excel
and then reading all data in the sheet.
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();
But after my application terminates, I tried to edit my excel file and had some problems while opening. Apparently the excel process keeps on running in the background even though I called ExcelApp.Quit()
. Is there a way to properly close the excel file that the application uses? I'm new to c# so i'm probably missing something here.
Edit: Solved! Apparently there's a rule for com objects that discourages using 2 dots.
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();
Upvotes: 10
Views: 16805
Reputation: 1
var Process = Process.GetProcessesByName("excel").Select(x => x.Id.ToString());
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
foreach (Process pros in Process.GetProcessesByName("excel"))
{
if (!array1.Contains(pros.Id.ToString()))
{
Console.WriteLine(pros.Id.ToString());
pros.Kill();
}
}
Upvotes: -1
Reputation: 103
This code worked on me.
Excel.Application excelApp = null;
Excel.Workbooks excelWorkbooks = null;
Excel.Workbook excelWorkbook = null;
Excel._Worksheet xlWorkSheet = null;
Excel.Range range = null;
excelApp = new Excel.Application();
excelWorkbooks = excelApp.Workbooks;
excelWorkbook = excelWorkbooks.Open(excelName);
xlWorkSheet = (Excel.Worksheet)excelWorkbook.ActiveSheet;
range = xlWorkSheet.Range["C3"] ;
range.Value = "Update Data";
Marshal.ReleaseComObject(range);
xlWorkSheet.SaveAs(path);
Marshal.ReleaseComObject(xlWorkSheet);
excelWorkbook.Close();
Marshal.ReleaseComObject(excelWorkbook);
excelWorkbooks.Close();
Marshal.ReleaseComObject(excelWorkbooks);
excelApp.Quit();
Marshal.ReleaseComObject(excelApp);
Upvotes: 0
Reputation: 1
For me this worked : //opening
var excelFile = new Application();
Workbook workBook1 = excelFile.Workbooks.Open(goldenCopy_path);
Workbook workBook2 = excelFile.Workbooks.Open(new_path);
Worksheet goldWorkSheet, newWorkSheet;
goldWorkSheet = workBook1.Worksheets[1];
newWorkSheet = workBook2.Worksheets[1];
//closing //it will release the workbook from visual studio
goldWorkSheet = null;
newWorkSheet = null;
workBook1.Close();
workBook2.Close();
workBook1 = null;
workBook2 = null;
excelFile.Quit();
excelFile = null;
Upvotes: 0
Reputation: 369
For me this worked!
//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;
Upvotes: 1
Reputation: 464
Long time no answer but what worked for me was to call the GC.Collect(); from the caller,
i.e. instead of
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();
}
Using above Excel does not die
but a very small change, to where the GC is called from
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
}
My guess is the garbage collector needs to also quietly clean up internally created temp values (including refs/pointers) from the heap - some of which I guess in this case are pointing to COM objects.
(Just takes a smidgen of understanding of how machines work underneath the source code.)
Upvotes: 5
Reputation: 15695
There was another similar question - and answer (https://stackoverflow.com/a/17367570/3063884), in which the solution was to avoid using double-dot notation. Instead, define variables for each object used along the way, and individually use Marshal.ReleaseComObject
on each one.
Copying straight from the linked solution:
var workbook = excel.Workbooks.Open(/*params*/)
---> instead use -->
var workbooks = excel.Workbooks;
var workbook = workbooks.Open(/*params*/)
Then, when done, release each COM object:
Marshal.ReleaseComObject(workbook);
Marshal.ReleaseComObject(workbooks);
Marshal.ReleaseComObject(excel);
Upvotes: 15
Reputation: 186
Interop is notoriously buggy... I use the following method after saving my workbook, and no longer have issues with Excel remaining open when I exit my applications:
while (Marshal.ReleaseComObject(wb) > 0);
while (Marshal.ReleaseComObject(xl) > 0);
wb = null;
xl = null;
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
wb is my workbook object, and xl is my Excel.Application object.
Upvotes: 0
Reputation: 466
You are not closing your workbook. Close it and then release it before quitting the Excel application:
excelWorkbook.close();
Marshal.ReleaseComObject(excelWorkbook);
ExcelApp.Quit();
Upvotes: 1