5

如果我有一个引用Worksheet并且我关闭它的 parent 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

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

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: 

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

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

4

3 回答 3

3

我使用这种方法:

        private void releaseObject(object obj)
    {
        try
        {
            System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
            obj = null;
        }
        catch (Exception ex)
        {
            obj = null;
            MessageBox.Show("Exception Occured while releasing object " + ex.ToString());
        }
        finally
        {
            GC.Collect();
        }
    }

或者你可以尝试这样的事情:

    static bool IsOpened(string wbook) 
{ 
    bool isOpened = true; 
    Excel.Application exApp; 
    exApp = (Excel.Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application"); 
    try 
    { 
        exApp.Workbooks.get_Item(wbook); 
    } 
    catch (Exception) 
    { 
        isOpened = false; 
    } 
    return isOpened; 
} 
于 2012-03-06T20:41:30.533 回答
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;
}

编辑:为了完整起见,辅助扩展方法:

public static bool SheetExists(this Excel.Workbook wbk, string sheetName)
{
    for (int i = 1; i <= wbk.Worksheets.Count; i++)
    {
        if (((Excel.Worksheet)wbk.Worksheets[i]).Name == sheetName)
        {
            return true;
        }
    }

    return false;
}
于 2012-03-08T20:25:20.910 回答
0

我没有尝试过,但您可以检查工作簿是否sheet.Parent存在于 Application.Workbooks 集合中。

于 2012-03-06T20:32:58.133 回答