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

如果我有Worksheet的引用,并closures它的父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 

这是我尝试访问工作表时遇到的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不提供一个(这真的很烦人)。

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

如果其他解决scheme失败,另一种处理此问题的方法是在打开工作簿后存储工作簿的名称,然后在引用Workbooks表之前检查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; } 

我用这个方法:

  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; } 

我没有试过这个,但是你可以检查Application.Workbooks集合中sheet.Parent存在Workbook sheet.Parent