2012-03-06 51 views
5

如果我參考了Worksheet,並關閉它的父項Workbook,則參考文獻不會消失。但我無法弄清楚我應該如何檢查以確保這些表格不存在。檢查null不起作用。在Excel VSTO中,如何檢查工作表是否屬於已關閉的工作簿?

例子:

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不提供一個(這真的是惱人)。

有沒有一些方便的方法來確保我不使用這些工作表?

回答

3

如果其他解決方案失敗,另一種方式來處理這個問題是存儲在工作簿的名稱打開之後,然後在引用表單之前檢查該名稱是否存在於Workbooks集合中。從名稱you can only have uniquely named workbooks in each instance of 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; 
} 
+0

這有效,但只有當我碰巧有'Workbook'的時候。我的示例代碼很簡單,但實際上,我有幾個只使用'Worksheet'對象的方法。不過,我會接受你的回答,因爲我最終做了類似的事情。即,我檢查了'Application.Workbooks.Count> 0'。由於我沒有打開任何工作簿時只遇到了這個問題,所以此檢查就足以滿足我的需求。感謝您的輸入。 – 2012-03-08 20:46:16

0

我還沒有試過這個,但是你可以檢查Application.Workbooks集合中是否存在工作簿sheet.Parent

+0

將無法​​工作。調用'sheet.Parent'會導致與調用'sheet.Name'相同的異常。雖然好想。 – 2012-03-06 20:43:01

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

我怎麼知道什麼時候該調用?我有一些潛在開放或潛在關閉的工作表。如果它是開放的,我想用它做點什麼。如果它關閉,我不會。問題是我無法知道它是打開還是關閉。這種方法似乎只有當我知道它關閉時纔會有幫助。 – 2012-03-06 20:47:23

+0

我添加了額外的代碼。 – Andrew 2012-03-06 20:55:31

+0

我可以做到這一點,但我寧願只用它作爲最後的手段。我一般認爲[異常不應該用於流量控制。](http://stackoverflow.com/questions/729379/why-not-use-exceptions-as-regular-flow-of-control ) – 2012-03-06 21:06:50

相關問題