Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Excel VSTO, how can I check if a worksheet belongs to a closed workbook?

If I have a reference to Worksheet and I close it's parent Workbook, the reference doesn't go away. But I can't figure out how I should check to make sure these sheets don't exist. Checking for null doesn't work.

Example:

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

This is the exception I get when I try to access the sheet:

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: 

This wouldn't even be an issue if I could check for a workbook delete event, but Excel doesn't provide one (which is really annoying).

Is there some convenient way to make sure I don't use these worksheets?

like image 318
Kris Harper Avatar asked Mar 06 '12 20:03

Kris Harper


People also ask

Which collection do you check to determine if a specific worksheet exists or not?

What is this? With this code we can use =WorksheetExists(B3) to test any text string to see if it exists as a sheet name in the current workbook.

How can I tell if an Excel file is saved?

You can determine if changes have been made to a workbook by checking the Saved property of the workbook. The Saved property returns a True or False value depending on whether changes have been made to the workbook. It is possible to set the Saved property to True or False.

Is worksheet A collection of workbook?

Excel lets you create spreadsheets with multiple pages of data, each of which can conveniently exchange information with other pages. Each page is called a worksheet, and a collection of one or more worksheets is called a workbook (which is also sometimes called a spreadsheet file).


2 Answers

If the other solutions fail, another way to handle this is to store the name of the workbook after it opens, then check to see if that name exists in the Workbooks collection before referencing the sheet. Referencing the workbooks by name will work since 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: for completeness, a helper extension method:

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;
}
like image 159
Peter Majeed Avatar answered Sep 20 '22 15:09

Peter Majeed


I use this method :

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

or you can try something like this:

    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; 
} 
like image 20
Andrew Avatar answered Sep 17 '22 15:09

Andrew