The explanation you are giving in your question is not accurate enough. You must distinguish two cases:
Case 1: You have more than one Excel process each with one workbook. That means that e.g. all your excel workbooks each run in an own hosting excel window. You achieve this when e.g right-clicking on the excel icon, getting an empty excel workbook and loading the workbook you want into that process. In this case your approach works, as every excel process has its own title naming the workbook file name. The requested process is killed when iterating through the excel processes.
Case 2, which is the more "normal" case when working with excel, and to which you probably refer to: You have one excel process hosting more than one workbook, each possibly with several worksheets. In that case Excel acts as you describe and changes its window title (Multiple document interface).
In case 2, when there is only one single excel process present, you can close the workbook in the following way, using COM Interop:
private void button1_Click(object sender, EventArgs e)
{
CloseExcelWorkbook("TestReport.xlsx");
}
//put the following abbreviation to the "using" block: using Excel = Microsoft.Office.Interop.Excel;
internal void CloseExcelWorkbook(string workbookName)
{
try
{
Process[] plist = Process.GetProcessesByName("Excel", ".");
if (plist.Length > 1)
throw new Exception("More than one Excel process running.");
else if (plist.Length == 0)
throw new Exception("No Excel process running.");
Object obj = Marshal.GetActiveObject("Excel.Application");
Excel.Application excelAppl = (Excel.Application)obj;
Excel.Workbooks workbooks = excelAppl.Workbooks;
foreach (Excel.Workbook wkbk in workbooks )
{
if (wkbk.Name == workbookName)
wkbk.Close();
}
//dispose
//workbooks.Close(); //this would close all workbooks
GC.Collect();
GC.WaitForPendingFinalizers();
if (workbooks != null)
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(workbooks);
//excelAppl.Quit(); //would close the excel application
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(excelAppl);
GC.Collect();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
This approach works in case you have only ONE Excel process running. When there are more than one present, the situation is more complicated as you must get access to all Excel processes. For a discussion for that case, see here.
Another point to observe is to release excel objects properly to avoid stale excel objects. See there.
If you omit the "dispose" activities, it may happen that on closing Excel and continuing to run your app the Excel process runs silently on, as an inspection in Task Manager shows.