在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
。