Excel automation: Close event missing

前端 未结 4 918
南方客
南方客 2021-01-19 00:56

Another hi all,

I am doing Excel automation via Interop in C#, and I want to be informed when a workbook is closed. However, there is no Close event on the workbook

4条回答
  •  清歌不尽
    2021-01-19 01:32

    I've created a hack using a polling-like approach, and it works:

    Given the workbook to observe, I create a thread which periodically tries to find that workbook in the workbooks collection.

    (The DisposableCom class is my current solution to properly cleanup COM objects.)

    Excel.Application app = wbWorkbook.Application;
    string sWorkbookName = wbWorkbook.Name;
    
    Thread overseeWorkbooksThread = new Thread(new ThreadStart(
        delegate()
        {
            bool bOpened = false;
    
            Excel.Workbooks wbsWorkbooks = app.Workbooks;
            using (new DisposableCom(wbsWorkbooks))
            {
                while (true)
                {
                    Thread.Sleep(1000);
    
                    if (wbsWorkbooks.ContainsWorkbookProperly(sWorkbookName))
                        bOpened = true;
                    else
                        if (bOpened)
                            // Workbook was open, so it has been closed.
                            break;
                        else
                        {
                            // Workbook simply not finished opening, do nothing
                        }
                }
    
                // Workbook closed
                RunTheCodeToBeRunAfterWorkbookIsClosed();
            }
        }));
    
    overseeWorkbooksThread.Start();
    

    The "ContainsWorkbookProperly" extension methods looks like this:

    public static bool ContainsWorkbookProperly(this Excel.Workbooks excelWbs,
        string sWorkbookName)
    {
        Excel.Workbook wbTemp = null;
        try
            wbTemp = excelWbs.Item(sWorkbookName);
        catch (Exception)
        {
            // ignore
        }
    
        if (wbTemp != null)
        {
            new DisposableCom(wbTemp).Dispose();
            return true;
        }
    
        return false;
    }
    

    Still I would be interested if there is a simpler or better solution.

提交回复
热议问题