5

への参照がWorksheetあり、その親を閉じると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

これは、シートにアクセスしようとしたときに発生する例外です。

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 ではイベントが提供されません (これは非常に面倒です)。

これらのワークシートを使用しないようにする便利な方法はありますか?

4

3 に答える 3

3

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;
}
于 2012-03-08T20:25:20.910 に答える
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; 
} 
于 2012-03-06T20:41:30.533 に答える
0

私はこれを試していませんが、ワークブックsheet.ParentがApplication.Workbooksコレクションに存在するかどうかを確認できます。

于 2012-03-06T20:32:58.133 に答える