打开多个Excel文件时关闭特定的Excel文件

时间:2015-07-18 16:10:58

标签: c# .net

我正在尝试使用以下代码关闭名为TestReport.xlsx的excel文件。当只有一个excel进程正在运行但是当我打开多个excel窗口时,它正在工作,MainWindowTitle发生了变化,代码没有杀死所需的excel进程。

Process[] plist = Process.GetProcessesByName("Excel",".");
foreach(Process p in plist)
{         

    if (p.MainWindowTitle.Contains("TestReport.xlsx") && p.ProcessName == "EXCEL")
    {
        p.Kill();
    }
}

1 个答案:

答案 0 :(得分:0)

您在问题中提供的解释不够准确。你必须区分两种情况:

案例1:您有多个Excel流程,每个流程都有一个工作簿。这意味着,例如所有excel工作簿都在自己的托管excel窗口中运行。例如,右键单击excel图标,获取一个空的excel工作簿并将所需的工作簿加载到该过程中即可实现此目的。在这种情况下,您的方法可行,因为每个excel进程都有自己的标题命名工作簿文件名。迭代excel进程时,请求的进程被终止。

案例2,这是更多"正常"使用excel时可能会引用的情况:您有一个托管多个工作簿的excel进程,每个工作簿可能包含多个工作表。在这种情况下,Excel会按照您的描述进行操作并更改其窗口标题(多文档界面)。

在案例2中,当只有一个excel进程存在时,您可以使用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);
    }
}

如果您只运行一个Excel进程,则此方法有效。当存在多个存在时,情况会更复杂,因为您必须访问所有Excel进程。有关该案例的讨论,请参阅here

要注意的另一点是正确释放excel对象以避免陈旧的excel对象。请参阅there

如果省略" dispose"活动,可能会发生这种情况,在关闭Excel并继续运行您的应用程序时,Excel进程将静默运行,如任务管理器中的检查所示。