我正在处理旧VBA
程序的C#
和现在的VB.NET
端口。它有很多 MSForms/OleObjects
嵌入其中,例如 CommandButton
甚至图像。
我的第一个想法是将所有按钮声明为 Microsoft.Vbe.Interop.Forms.CommandButton
,但这会导致 COM
异常,System. _COM 类型
无法转换为 ...Forms.CommandButton
。如果我尝试更通用的版本 this solution ,我没有找到任何项目,如果我尝试遍历所有 VBComponet
,我注意到它们都是 workbook
中的所有工作表,但没有一个控件:
foreach (VBComponent xxx in Globals.ThisWorkbook.VBProject.VBComponents) {
Interaction.MsgBox(xxx.Name);
Interaction.MsgBox(xxx.ToString);
}
因此所有这些控件都不在 .VBComponets
中,但我可以在 thisworkbook.worksheets(n).OLEobjects
中找到它们作为 OLEobjects>(这对我来说是违反直觉的,但我可能一开始就不理解这个系统)。
如何处理此类对象的点击操作?
我假设我需要使用 Excel.OLEObjectEvents_Event
接口(interface),但我似乎不知道如何使用。如果我尝试使用 delegates
创建自定义事件,我似乎无法将它们分配给 OleObjects
。如果我使用 ActionClickEventHandler.CreateDelegate
,我会收到各种各样的错误,这让我觉得这是死胡同。
official documentation来自 MS 的帮助似乎不大,尽管它确实向我介绍了 idea Verb
,我正在研究。到目前为止,这只产生了类似于“应用程序无法启动”的 COM 错误。
即使只是尝试使用两个标准事件之一,.GotFocus
,我也总是会出现 0x80040200 错误。
示例:
Excel.OLEObject ButtonCatcher = Globals.ThisWorkbook.Worksheets(1).OLEObjects("CommandButton1");
ButtonCatcher.GotFocus += CommandButton1_Click;
在第二行抛出 COMException Exception from HRESULT: 0x80040200
。该按钮已启用,这是我在查找 code number from the office dev site. 后检查的
尝试更多 generic approach在包含控件的工作表的代码中:
object CommandButtonStart = this.GetType().InvokeMember("CommandButton1", System.Reflection.BindingFlags.GetProperty, null, this, null);
Throws a Missing Method error.
非常感谢任何帮助,这似乎应该是显而易见的,我错过了。
**编辑:我还发现我可以将这些控件转换为 Excel.Shape
,但这实际上并没有让我更接近从 VSTO 运行函数或子程序。我正在玩 Excel.Shape.OnAction
但这需要调用 VBA sub。据推测,只要 VSTO 是 COM 可见的,我就可以调用一个从 VSTO 调用一个子程序的 VBA 子程序。这似乎真的很迂回,我只想作为最后的手段。
最佳答案
解决方案类型: VSTO Document-Level
场景:
1.) 在运行时创建的 Excel.Worksheet。 (不是 Worksheet Host Item )
2.) 在运行时在工作表上添加一个按钮,单击时触发 C# 代码。
程序集引用:
Microsoft.Vbe.Interop (Microsoft.Vbe.Interop.dll)
Microsoft.Vbe.Interop.Forms (Microsoft.Vbe.Interop.Forms.dll)
Microsoft.VisualBasic (Microsoft.VisualBasic.dll)
测试/工作代码:
using MSForms = Microsoft.Vbe.Interop.Forms;
using System.Windows.Forms;
...
Microsoft.Vbe.Interop.Forms.CommandButton CmdBtn;
private void CreateOLEButton()
{
Excel.Worksheet ws = Globals.ThisWorkbook.Application.Sheets["MyWorksheet"];
// insert button shape
Excel.Shape cmdButton = ws.Shapes.AddOLEObject("Forms.CommandButton.1", Type.Missing, false, false, Type.Missing, Type.Missing, Type.Missing, 500, 5, 100, 60);
cmdButton.Name = "btnButton";
// bind it and wire it up
CmdBtn = (Microsoft.Vbe.Interop.Forms.CommandButton)Microsoft.VisualBasic.CompilerServices.NewLateBinding.LateGet(ws, null, "btnButton", new object[0], null, null, null);
CmdBtn.Caption = "Click me!";
CmdBtn.Click += new MSForms.CommandButtonEvents_ClickEventHandler(ExecuteCmd_Click);
}
private void ExecuteCmd_Click()
{
MessageBox.Show("Click");
}
关于c# - 如何处理来自嵌入式 Excel.OleObjects 或 Excel.Shapes 的事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22368680/