c# - 如何处理来自嵌入式 Excel.OleObjects 或 Excel.Shapes 的事件

标签 c# vb.net excel vba vsto

我正在处理旧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/

相关文章:

c# - "x.OnSpeak += (s, e)"是什么意思?

vb.net - 将整数拆分为数组VB

vb.net - 从谷歌获取IP

vb.net - Directory.GetFiles 返回整个路径,我只想要文件名?

excel - python XlsxWriter : set font does not affect the appearance of cells in output excel file

c# - 找出 C# 枚举器

C# 窗体 : move text from one textbox to another

c# - 如何使用 TcpClient 类在 WCF 中获取超时异常

excel - 在 Excel 2007 中删除特定字符串之后的所有内容

python - 根据单元格值定位行