c# vb.net excel vba vsto

c# - Cómo manejar eventos desde Excel.OleObjects incrustado o Excel.Shapes



vb.net vba (4)

¿Has intentado usar NewLateBinding.LateGet?

using MSForms = Microsoft.Vbe.Interop.Forms; using Microsoft.VisualBasic.CompilerServices; ... MSForms.CommandButton CommandButton1 = (MSForms.CommandButton)NewLateBinding.LateGet(Globals.ThisWorkbook.Worksheets(1), null, "CommandButton1", new object[0], null, null, null); CommandButton1.Click += new Microsoft.Vbe.Interop.Forms.CommandButtonEvents_ClickEventHandler(CommandButton1_Click);

Se hace referencia en MSDN en los foros de VSTO y en una publicación de blog anterior .

Estoy trabajando en C# y ahora en los puertos VB.NET de un antiguo programa VBA . Tiene muchos MSForms/OleObjects incrustados en ella como CommandButton o incluso imágenes.

Mi primer pensamiento fue declarar todos los botones como Microsoft.Vbe.Interop.Forms.CommandButton pero eso lleva a una excepción COM que el System._COM type no se puede convertir en ...Forms.CommandButton . Si intento una versión más genérica de esta solución , no encuentro ningún elemento, y si trato de revisar todos los VBComponet , tengo en cuenta que son todas las hojas del workbook , pero ninguno de los controles:

foreach (VBComponent xxx in Globals.ThisWorkbook.VBProject.VBComponents) { Interaction.MsgBox(xxx.Name); Interaction.MsgBox(xxx.ToString); }

Por lo tanto, todos estos controles no están en .VBComponets , pero puedo encontrarlos como OLEobjects en thisworkbook.worksheets(n).OLEobjects (esto es contraintutivo para mí, pero probablemente no entiendo el sistema para empezar).

¿Cómo manejo la acción Click de un objeto de este tipo?

Supongo que necesito usar la interfaz Excel.OLEObjectEvents_Event , pero parece que no Excel.OLEObjectEvents_Event entender cómo. Si intento crear eventos personalizados con delegates , parece que no puedo asignarlos a OleObjects . Si uso ActionClickEventHandler.CreateDelegate , puedo obtener una gran variedad de errores que me hacen pensar que es un callejón sin salida.

La documentación oficial de MS no parece ser tan útil, aunque me introdujo en la idea de Verb , que estoy estudiando. Hasta el momento, eso solo ha producido errores COM a lo largo de las líneas de "Error al iniciar la aplicación".

Incluso tratando de usar uno de los dos eventos estándar, .GotFocus , siempre .GotFocus un error 0x80040200. Ejemplo:

Excel.OLEObject ButtonCatcher = Globals.ThisWorkbook.Worksheets(1).OLEObjects("CommandButton1"); ButtonCatcher.GotFocus += CommandButton1_Click;

Lanza una Exception from HRESULT: 0x80040200 COMException Exception from HRESULT: 0x80040200 en la segunda línea. El botón está habilitado, que se comprueba después de buscar el número de código en el sitio de desarrollo de oficina.

Intentando un enfoque más genérico dentro del código para una hoja que contiene controles:

object CommandButtonStart = this.GetType().InvokeMember("CommandButton1", System.Reflection.BindingFlags.GetProperty, null, this, null);

Lanza un error del método que falta.

Cualquier ayuda es muy apreciada, esto parece que esto debería ser obvio y me estoy perdiendo.

** Editar: También descubrí que puedo convertir estos controles en Excel.Shape pero eso no me acerca mucho más a la ejecución de una función o sub de VSTO. Estoy jugando con Excel.Shape.OnAction pero esto requiere que se llame a un sub VBA. Supongo que podría llamar a un sub VBA que llama a un sub desde el VSTO siempre que el VSTO sea COM visible. Esto parece realmente redondo y solo me gustaría hacerlo como último recurso.


¿Puede agregar código a un módulo de código en el libro de trabajo de manera programática, como esto ?

Private Sub CommonButton_Click(ByVal buttonName As String) MsgBox "You clicked button [" & buttonName & "]" End Sub Private Sub CreateEventHandler(ByVal buttonName As String) Dim VBComp As VBIDE.VBComponent Dim CodeMod As VBIDE.CodeModule Dim codeText As String Dim LineNum As Long Set VBComp = ThisWorkbook.VBProject.VBComponents(Me.CodeName) Set CodeMod = VBComp.CodeModule LineNum = CodeMod.CountOfLines + 1 codeText = codeText & "Private Sub " & buttonName & "_Click()" & vbCrLf codeText = codeText & " Dim buttonName As String" & vbCrLf codeText = codeText & " buttonName = """ & buttonName & "" & vbCrLf codeText = codeText & " CommonButton_Click buttonName" & vbCrLf codeText = codeText & "End Sub" CodeMod.InsertLines LineNum, codeText End Sub


Utilice el kit de herramientas de formularios de interoperabilidad. Es gratis desde Microsoft. Proporciona envoltorios com y clase de mensajería de eventos que comunica los datos del evento hacia y desde .NET a VBA. Lo he usado para controlar los eventos de control de VBA en .NET y los eventos de .NET a VBA. Usted usaría la interoperabilidad

http://www.codeproject.com/Articles/15690/VB-C-Interop-Form-Toolkit .

Desde el kit de herramientas de ducoumentación:

Interop UserControls proporciona un conjunto básico de eventos intrínsecos (Click, GotFocus, Validate, etc.) en Visual Basic 6.0. Puede definir sus propios eventos personalizados en Visual Studio .NET y aumentarlos utilizando RaiseEvent. Para manejar los eventos en Visual Basic 6.0, debe agregar una referencia de proyecto y agregar una declaración de variable WithEvents en su código, y luego manejar los eventos usando la variable WithEvents en lugar del propio control.

Cómo manejar los eventos personalizados de Interop UserControl

1. En Visual Basic 6.0, en el menú Proyecto, haga clic en Referencias. Tenga en cuenta que ya hay una referencia a ControlNameCtl, donde ControlName es el nombre de su Interop UserControl.

2. En la lista Referencias disponibles, localice una referencia para ControlName y verifíquela, y luego haga clic en Aceptar.

3. En el Editor de código, agregue una declaración para una variable WithEvents:

Dim WithEvents ControlNameEvents As ControlLibrary.ControlName

En el controlador de eventos Form_Load, agregue el siguiente código para inicializar la variable WithEvents:

Private Sub Form_Load() Set ControlNameEvents = Me.ControlNameOnVB6Form End Sub

Agregue código para manejar su evento personalizado en el controlador de eventos de la variable WithEvents:

Private Sub ControlNameEvents_MyCustomEvent() MsgBox("My custom event fired") End Sub


Tipo de solución: nivel de documento VSTO

Guión:
1.) Excel.Worksheet creado en tiempo de ejecución. (no es un elemento de host de hoja de trabajo )
2.) Agregue un botón en la hoja de trabajo en tiempo de ejecución que active el código C # cuando se haga clic.

Referencias de la asamblea:
Microsoft.Vbe.Interop (Microsoft.Vbe.Interop.dll)
Microsoft.Vbe.Interop.Forms (Microsoft.Vbe.Interop.Forms.dll)
Microsoft.VisualBasic (Microsoft.VisualBasic.dll)

Código probado / de trabajo:

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