我正在为一款旧的VBA程序制作C#和VB.NET版本,它有很多像CommandButton或图像这样的MSForms/OleObjects嵌入其中。
一开始我的想法是将所有按钮声明为Microsoft.Vbe.Interop.Forms.CommandButton,但这导致了一个COM异常,即System._COM类型无法转换为...Forms.CommandButton。如果我尝试更通用版本的此解决方案,我找不到任何项,而如果我尝试遍历所有VBComponent,我会发现它们都是workbook中的sheets,但没有控件:
foreach (VBComponent xxx in Globals.ThisWorkbook.VBProject.VBComponents) {
Interaction.MsgBox(xxx.Name);
Interaction.MsgBox(xxx.ToString);
}
因此,所有这些控件都不在.VBComponents
中,但我可以在thisworkbook.worksheets(n).OLEobjects
中找到它们作为OLE对象(这对我来说很反直觉,但我可能从一开始就不理解这个系统)。
如何处理这种对象的单击操作?
我假设我需要使用Excel.OLEObjectEvents_Event
接口,但我似乎无法弄清楚如何使用。如果我尝试使用delegate
创建自定义事件,我似乎无法将它们分配给OleObjects
。如果我使用ActionClickEventHandler.CreateDelegate
,我会遇到各种错误,使我认为这是一个死路。来自微软的官方文档似乎并没有太大帮助,尽管它让我了解了
Verb
的概念,我正在研究这一点。到目前为止,这只产生了类似于“应用程序启动失败”的COM错误。甚至只是尝试使用两个标准事件之一,
.GotFocus
,我总是会遇到0x80040200错误。Excel.OLEObject ButtonCatcher = Globals.ThisWorkbook.Worksheets(1).OLEObjects("CommandButton1");
ButtonCatcher.GotFocus += CommandButton1_Click;
第二行抛出了COMException异常 Exception from HRESULT: 0x80040200
。在查看了Office开发网站上的代码编号后,我检查了按钮是否启用。
尝试在包含控件的工作表中的代码中采用更加通用的方法:
object CommandButtonStart = this.GetType().InvokeMember("CommandButton1", System.Reflection.BindingFlags.GetProperty, null, this, null);
抛出一个“缺少方法”错误。
非常感谢任何帮助,这似乎应该很明显,但我却没想到。编辑:我还发现我可以将这些控件转换为
Excel.Shape
,但这并不能让我更接近从VSTO运行函数或子程序。 我正在尝试使用Excel.Shape.OnAction
,但这需要调用一个VBA子程序。 假设VSTO是可见的,则可以调用从VSTO调用子程序的VBA子程序。 这似乎非常绕,只有在最后没有办法时才想这样做。