2012-03-06 25 views
5

Nếu tôi có một tham chiếu đến Worksheet và tôi đóng nó là phụ huynh Workbook, tham chiếu sẽ không biến mất. Nhưng tôi không thể tìm ra cách tôi nên kiểm tra để chắc chắn rằng những tờ này không tồn tại. Kiểm tra null không hoạt động.Trong Excel VSTO, làm cách nào tôi có thể kiểm tra xem một trang tính thuộc về một bảng tính đã đóng?

Ví dụ:

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 

Đây là ngoại lệ tôi nhận được khi tôi cố gắng truy cập vào tờ:

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: 

này sẽ thậm chí không phải là một vấn đề nếu tôi có thể kiểm tra một workbook xóa sự kiện, nhưng Excel không cung cấp một (mà là thực sự gây phiền nhiễu).

Có cách nào thuận tiện để đảm bảo tôi không sử dụng các trang tính này không?

Trả lời

3

Nếu các giải pháp khác thất bại, một cách khác để xử lý này là để lưu trữ tên của bảng tính sau khi nó mở ra, sau đó kiểm tra xem tên đó có tồn tại trong bộ sưu tập Workbooks trước khi tham khảo trang tính hay không. Tham chiếu các sổ làm việc theo tên sẽ hoạt động từ 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; 
} 

Edit: cho đầy đủ, một phương pháp mở rộng helper:

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

Điều này có tác dụng, nhưng chỉ khi nào tôi có 'Sổ làm việc' vào lúc đó. Mã ví dụ của tôi rất đơn giản, nhưng trong thực tế, tôi có một số phương thức chỉ lấy một đối tượng 'Worksheet'. Tuy nhiên, tôi sẽ chấp nhận câu trả lời của bạn kể từ khi tôi đã làm một cái gì đó tương tự. Cụ thể, tôi đã kiểm tra 'Application.Workbooks.Count> 0'. Vì tôi chỉ gặp vấn đề này khi không có sổ làm việc nào được mở, kiểm tra này đủ cho nhu cầu của tôi. Cảm ơn cho đầu vào của bạn mặc dù. –

0

Tôi chưa thử điều này, nhưng bạn có thể kiểm tra xem Workbook sheet.Parent có tồn tại trong bộ sưu tập Application.Workbooks hay không.

+0

sẽ không hoạt động. Gọi 'sheet.Parent' gây ra cùng một ngoại lệ khi gọi' sheet.Name'. Mặc dù vậy, suy nghĩ tốt. –

3

tôi sử dụng phương pháp này:

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

hoặc bạn có thể thử một cái gì đó như thế này:

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

Làm cách nào để biết khi nào nên gọi điều này? Tôi có một số bảng tính có khả năng mở hoặc có khả năng đóng. Nếu nó mở, tôi muốn làm gì đó với nó. Nếu nó đóng cửa thì không. Vấn đề là tôi không có cách nào để biết nó mở hay đóng. Phương pháp này có vẻ như nó sẽ giúp chỉ khi tôi biết nó đóng cửa. –

+0

Tôi đã thêm mã bổ sung. – Andrew

+0

Tôi có thể làm điều này, nhưng tôi chỉ muốn sử dụng nó như một phương sách cuối cùng. Tôi thường có ý kiến ​​rằng [ngoại lệ không nên được sử dụng để kiểm soát luồng.] (Http://stackoverflow.com/questions/729379/why-not-use-exceptions-as-regular-flow-of-control) –