gpt4 book ai didi

c# - 在 VSTO 中获取 Excel 工作簿的哈希码以启用基于状态的按钮

转载 作者:太空狗 更新时间:2023-10-29 21:34:34 25 4
gpt4 key购买 nike

我正在为 excel 创建一个 VSTO Ribbon AddIn,我正在我的应用程序中存储一些工作簿状态信息,我用它来更新启用的可视按钮。考虑到可以有多个工作簿,我将这个状态对象存储在 ThisAddIn 类的字典中。我的问题是我不知道如何为工作簿获取唯一的 Hash/Key/Guid,因为我得到的只是一个不断更改哈希的 COM 包装器。很公平,我完全理解这一点。

我使用了很长时间的一个解决方案是创建一个 guid 并将其存储在工作簿的 CustomDocumentProperties 中,并根据它作为键来映射状态。这至少有效,但如果我创建工作簿的副本并在同一个应用程序实例中打开它并且现在有多个具有相同 guid 的工作簿,它就会失败。

我现在有一个想法,我想我可以在 Workbook_Open 事件上刷​​新这个 Guid。但这仍然是一个不可靠的解决方案。

我在这里找到的第二个解决方案: http://social.msdn.microsoft.com/Forums/en-US/vsto/thread/04efa74d-83bd-434d-ab07-36742fd8410e/

所以我使用了那些人的代码并创建了这个:

public static class WorkbookExtensions
{
public static IntPtr GetHashery(this msExcel.Workbook workbook)
{
IntPtr punk = IntPtr.Zero;
try
{
punk = Marshal.GetIUnknownForObject(workbook);
return punk;
}
finally
{
//Release to decrease ref count
Marshal.Release(punk);
}
}
}

它在几分钟内运行良好,直到在访问 Application.ActiveWorkbook 时开始出现臭名昭著的错误“无法使用与其底层 RCW 分离的 COM 对象”。

这是引用 Workbook COM 对象的安全方法吗?如果我有两个功能区应用程序都使用此方法来获取单个工作簿 GUID 怎么办?如果其中一个应用程序在我的状态对象上运行垃圾收集器,它会调用终结器来调用 Marshal.FinalReleaseComObject(workbook) 怎么办?有什么方法可以获得工作簿的引用计数,这样我就不会在其他功能区应用程序完成它们之前调用 FinalRelease 吗?清理 VSTO 中的 Workbook COM 对象以保持与这些其他应用公平竞争的一些最佳做法是什么?

当然,我不是第一个想要根据工作簿状态启用按钮的人,其他人是怎么做到的?我在此处查看了 Stack Overflow 上的其他几篇文章,但没有一篇对我使用 Workbook Guid 解决方案有很大帮助。

我正在使用 Ribbon Designer,并连接到 Workbook Load 和 Deactivate 事件。

提前致谢,希望我已经提供了所有详细信息。

最佳答案

我最终通过简单地将 IntPtr 转换为 long 来解决这个问题,然后 IntPtr 的处置不会影响我。我不需要保留 IntPtr,因为我真正需要的只是工作簿的一些独特之处。

以下代码允许我存储特定于工作簿的状态信息,因此我可以根据自定义对象工作簿状态更新功能区中按钮的视觉状态。您可以在自定义 WorkbookState 类中存储您想要的任何信息,但通常是您不想保留在电子表格本身中的特定于 session 的信息。

单独的工作簿扩展:

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

然后在我的 VSTO/ExcelDna ThisAddIn 类中,我使用上述方法存储所有工作簿状态的映射以查找唯一的工作簿哈希键:

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

当然,现在我可以通过简单地调用 ThisAddIn.WorkbookState

从功能区应用程序的任何位置访问我的 WorkbookState

关于c# - 在 VSTO 中获取 Excel 工作簿的哈希码以启用基于状态的按钮,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15940358/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com