Get Hashcode for Excel Workbook in VSTO to enable buttons based on state

I ended up solving this by simply casting the IntPtr to an long, and then the disposal of the IntPtr doesn't affect me. I don't need to preserve the IntPtr because all I really need is something unique about the workbook.

The following code allows me to store Workbook-specific state information, so I can update the visual state of the buttons in my ribbon based on a custom object workbook state. You can store any information you'd like in your custom WorkbookState class, but typically it would be session-specific information you don't want to persist in the spreadsheet itself.

Separate Workbook extensions:

public static class WorkbookExtensions
{
    public static long GetHashery(this msExcel.Workbook workbook)
    {
        if (workbook == null)
        {
            throw new ArgumentNullException("workbook");
        }

        IntPtr pUnknown = IntPtr.Zero;
        try
        {
            pUnknown = Marshal.GetIUnknownForObject(workbook);
            return pUnknown.ToInt64();
        }
        finally
        {
            // GetIUnknownForObject causes AddRef.
            if (pUnknown != IntPtr.Zero)
            {
                Marshal.Release(pUnknown);
            }
        }
    }
}

Then in my VSTO/ExcelDna ThisAddIn class I store a map of all workbook states with the above method to find a unique workbook hash key:

private Dictionary<long, WorkbookState> _workbookStates = new Dictionary<long, WorkbookState>();
public WorkbookState WorkbookState
{
    get
    {
        long hash = Application.ActiveWorkbook.GetHashery();
        WorkbookState state;
        if (!_workbookStates.TryGetValue(hash, out state))
        {
            state = _workbookStates[hash] = new WorkbookState();
        }
        return state;
    }
}

And of course now I can access my WorkbookState from anywhere in my ribbon application by simply calling ThisAddIn.WorkbookState

Tags:

C#

.Net

Excel

Com

Vsto