在Excel VSTO中,如何检查工作表是否属于已关闭的工作簿?

Kri*_*per 5 c# com excel vsto comexception

如果我有一个引用Worksheet并且我关闭它的父级Workbook,则引用不会消失.但我无法弄清楚我应该如何检查以确保这些表不存在.检查null不起作用.

例:

Workbook book = Globals.ThisAddIn.Application.ActiveWorkbook;
Worksheet sheet = (Worksheet)book.Worksheets[1]; // Get first worksheet
book.Close(); // Close the workbook
bool isNull = sheet == null; // false, worksheet is not null
string name = sheet.Name; // throws a COM Exception
Run Code Online (Sandbox Code Playgroud)

这是我尝试访问工作表时遇到的异常:

System.Runtime.InteropServices.COMException was caught
  HResult=-2147221080
  Message=Exception from HRESULT: 0x800401A8
  Source=MyProject
  ErrorCode=-2147221080
  StackTrace:
       at Microsoft.Office.Interop.Excel._Worksheet.get_Name()
       at MyCode.test_Click(Object sender, RibbonControlEventArgs e) in c:\MyCode.cs:line 413
  InnerException: 
Run Code Online (Sandbox Code Playgroud)

如果我可以检查工作簿删除事件,这甚至不是问题,但Excel不提供一个(这真的很烦人).

有没有一些方便的方法来确保我不使用这些工作表?

Pet*_*eed 3

Workbooks如果其他解决方案失败,处理此问题的另一种方法是在工作簿打开后存储工作簿的名称,然后在引用工作表之前检查集合中是否存在该名称。按名称引用工作簿是可行的,因为在每个 Excel 实例中只能有唯一命名的工作簿

public void Test()
{
    Workbook book = Globals.ThisAddIn.Application.ActiveWorkbook;
    string wbkName = book.Name; //get and store the workbook name somewhere
    Worksheet sheet = (Worksheet)book.Worksheets[1]; // Get first worksheet
    book.Close(); // Close the workbook
    bool isNull = sheet == null; // false, worksheet is not null
    string name;

    if (WorkbookExists(wbkName))
    {
        name = sheet.Name; // will NOT throw a COM Exception
    }
}

private bool WorkbookExists(string name)
{
    foreach (Microsoft.Office.Interop.Excel.Workbook wbk in Globals.ThisAddIn.Application.Workbooks)
    {
        if (wbk.Name == name)
        {
            return true;
        }
    }

    return false;
}
Run Code Online (Sandbox Code Playgroud)

编辑:为了完整性,一个辅助扩展方法:

public void Test()
{
    Workbook book = Globals.ThisAddIn.Application.ActiveWorkbook;
    string wbkName = book.Name; //get and store the workbook name somewhere
    Worksheet sheet = (Worksheet)book.Worksheets[1]; // Get first worksheet
    book.Close(); // Close the workbook
    bool isNull = sheet == null; // false, worksheet is not null
    string name;

    if (WorkbookExists(wbkName))
    {
        name = sheet.Name; // will NOT throw a COM Exception
    }
}

private bool WorkbookExists(string name)
{
    foreach (Microsoft.Office.Interop.Excel.Workbook wbk in Globals.ThisAddIn.Application.Workbooks)
    {
        if (wbk.Name == name)
        {
            return true;
        }
    }

    return false;
}
Run Code Online (Sandbox Code Playgroud)