Saltar al contenido

¿Cómo llamar a métodos .NET desde Excel VBA?

Por fin luego de mucho trabajar pudimos dar con el arreglo de este dilema que muchos de nuestros usuarios de nuestro sitio web presentan. Si tienes algún detalle que compartir no dudes en dejar tu conocimiento.

Solución:

Aquí hay una respuesta canónica sobre los 3 métodos principales para llamar a .Net desde Excel (o VBA).

Las tres formas funcionan en .Net 4.0.

1. XLL

El Add-In Express de terceros ofrece funcionalidad XLL, sin embargo, es gratuito y fácil de usar Excel-DNA el autor esta aqui https://stackoverflow.com/users/44264

Aquí hay un extracto de la página de Excel-DNA: https://excel-dna.net/

Introducción

Excel-DNA es un proyecto independiente para integrar .NET en Excel. Con Excel-DNA puede crear complementos nativos (.xll) para Excel usando C #, Visual Basic.NET o F #, proporcionando funciones definidas por el usuario (UDF) de alto rendimiento, interfaces de cinta personalizadas y más. Todo el complemento se puede empaquetar en un solo archivo .xll que no requiere instalación ni registro.

Empezando

Si está utilizando una versión de Visual Studio que admita NuGet Package Manager (incluido Visual Studio 2012 Express para Windows Desktop), la forma más sencilla de crear un complemento de Excel-DNA es:

Cree un nuevo proyecto de biblioteca de clases en Visual Basic, C # o F #. Utilice el cuadro de diálogo Administrar paquetes NuGet o la Consola del administrador de paquetes para instalar el paquete Excel-DNA:

PM> Install-Package Excel-DNA

Agregue su código (C #, Visual Basic.NET o F #):

using ExcelDna.Integration;
public static class MyFunctions

    [ExcelFunction(Description = "My first .NET function")]
    public static string SayHello(string name)
    
        return "Hello " + name;
    

Compile, cargue y use su función en Excel:

=SayHello("World!")

2. Complementos de automatización

Este artículo de Eric Carter muestra cómo hacerlo, al artículo le faltan montones de imágenes, así que estoy copiando / pegando el artículo completo y he recreado las imágenes para preservarlas.

REF: https://blogs.msdn.microsoft.com/eric_carter/2004/12/01/writing-user-defined-functions-for-excel-in-net/

Excel permite la creación de funciones definidas por el usuario que se pueden utilizar en fórmulas de Excel. Un desarrollador debe crear un tipo especial de DLL llamado XLL. Excel también le permite escribir funciones personalizadas en VBA que se pueden usar en fórmulas de Excel. Desafortunadamente, Excel no admite ni recomienda escribir un XLL que utilice código administrado. Si está dispuesto a correr el riesgo de que su XLL no se ejecute en las versiones actuales o futuras de Excel, existen soluciones disponibles que permiten este escenario: busque en la web “XLL administrado”.

Afortunadamente, existe una manera más fácil de crear una función definida por el usuario que no requiere que cree una dll XLL. Excel XP, Excel 2003 y Excel 2007 admiten algo llamado Complemento de automatización. Se puede crear un complemento de automatización de manera bastante simple en C # o VB.NET. Les voy a mostrar un ejemplo en C #.

Primero, inicie Visual Studio y cree un nuevo proyecto de biblioteca de clases C # llamado AutomationAddin para este ejemplo.

Luego, en su archivo Class1.cs, ingrese el código que se muestra a continuación. Reemplace el GUID con su propio GUID que cree utilizando Generar GUID en el menú Herramientas de Visual Studio.

using System;
using System.Runtime.InteropServices;
using Microsoft.Win32;

namespace AutomationAddin


  // Replace the Guid below with your own guid that
  // you generate using Create GUID from the Tools menu
  [Guid("A33BF1F2-483F-48F9-8A2D-4DA68C53C13B")] 
  [ClassInterface(ClassInterfaceType.AutoDual)]
  [ComVisible(true)]
  public class MyFunctions
  
    public MyFunctions()
    

    

    public double MultiplyNTimes(double number1, double number2, double timesToMultiply)
    
      double result = number1;
      for (double i = 0; i < timesToMultiply; i++)
      
        result = result * number2;
      
      return result;
    

    [ComRegisterFunctionAttribute]
    public static void RegisterFunction(Type type)
    
      Registry.ClassesRoot.CreateSubKey(GetSubKeyName(type, "Programmable"));
      RegistryKey key = Registry.ClassesRoot.OpenSubKey(GetSubKeyName(type, "InprocServer32"), true);
      key.SetValue("", System.Environment.SystemDirectory + @"mscoree.dll",RegistryValueKind.String);
    

    [ComUnregisterFunctionAttribute]
    public static void UnregisterFunction(Type type)
    
      Registry.ClassesRoot.DeleteSubKey(GetSubKeyName(type, "Programmable"), false);
    

    private static string GetSubKeyName(Type type, string subKeyName)
    
      System.Text.StringBuilder s = new System.Text.StringBuilder();
      s.Append(@"CLSID");
      s.Append(type.GUID.ToString().ToUpper());
      s.Append(@"");
      s.Append(subKeyName);
      return s.ToString();
      
  

Con este código escrito, muestre las propiedades del proyecto haciendo doble clic en el nodo de propiedades debajo del proyecto en el Explorador de soluciones. Haga clic en la pestaña Generar y marque la casilla de verificación que dice "Registrarse para interoperabilidad COM". En este punto, tiene un paso adicional si está ejecutando Windows Vista o superior. Visual Studio debe ejecutarse con privilegios de administrador para registrarse en la interoperabilidad COM. Guarde su proyecto y salga de Visual Studio. Luego busque Visual Studio en el menú Inicio y haga clic derecho sobre él y elija "Ejecutar como administrador". Vuelva a abrir su proyecto en Visual Studio. Luego, elija "Crear" para crear el complemento.

ingrese la descripción de la imagen aquí

Ahora inicie Excel y acceda al cuadro de diálogo Servidores de automatización siguiendo estos pasos:

  1.  Launch Excel and click the Microsoft Office button in the top left corner of the window. 
    
  2.  Choose Excel Options.
    
  3.  Click the Add-Ins tab in the Excel Options dialog. 
    
  4.  Choose Excel Add-Ins from the combo box labeled Manage.  Then click the Go button.
    
  5.  Click the Automation button in the Add-Ins dialog.
    

Puede encontrar la clase que creó buscando AutomationAddin.MyFunctions en la lista de complementos de Automatización:

ingrese la descripción de la imagen aquí

Ahora, intentemos usar la función MultiplyNTimes dentro de Excel. Primero cree una hoja de cálculo simple que tenga un número, un segundo número para multiplicar el primero y un tercer número para cuántas veces desea multiplicar el primer número por el segundo número. Aquí se muestra un ejemplo de hoja de cálculo:

ingrese la descripción de la imagen aquí

Haga clic en una celda vacía en el libro de trabajo debajo de los números y luego haga clic en el botón Insertar función en la barra de fórmulas. Desde el cuadro de diálogo de fórmulas disponibles, despliegue el cuadro desplegable "O seleccione una categoría" y elija "AutomationAddin.MyFunctions".

ingrese la descripción de la imagen aquí

Luego haga clic en la función MultiplyNTimes como se muestra aquí:

ingrese la descripción de la imagen aquí

Cuando presiona el botón Aceptar, Excel muestra un cuadro de diálogo para ayudarlo a obtener argumentos de función de la hoja de cálculo, como se muestra aquí:

ingrese la descripción de la imagen aquí

Finalmente, haga clic en Aceptar y vea su hoja de cálculo final como se muestra aquí con su fórmula personalizada en la celda C3.

ingrese la descripción de la imagen aquí


3. Llamar a .Net desde Excel VBA

REF: Llamar a un método de biblioteca .net desde vba

Usando el código del proyecto Automation.AddIn podemos llamar fácilmente a la función MultiplyNTimes desde Excel VBA.

Primero agregue una referencia a la DLL de Excel, para hacer esto necesitará estar en el Editor de VB. Presione Alt + F11, luego haga clic en el menú Herramientas y Referencias:

ingrese la descripción de la imagen aquí

Seleccione la DLL AutomationAddIn:

ingrese la descripción de la imagen aquí

Agregue el código VBA para llamar a la DLL .Net:

Sub Test()

Dim dotNetClass As AutomationAddIn.MyFunctions
Set dotNetClass = New AutomationAddIn.MyFunctions

Dim dbl As Double
dbl = dotNetClass.MultiplyNTimes(3, 2, 5)

End Sub

¡Y listo!

ingrese la descripción de la imagen aquí


Tenga en cuenta que si está trabajando con clases en C #, deberá marcarlas con ClassInterface, con una interfaz marcada con ComVisible = true: ¿Usar clases CLR del complemento COM en Excel VBA?

Por último, hay algunos excelentes artículos de MSDN sobre Excel y .Net de "Andrew Whitechapel". Búscalos en Google.

Aquí está su solución, probada para .NET 2.0 y .NET 4.0, 32 bits y 64 bits, cortesía de Soraco Technologies.

La solución propuesta a continuación utiliza un enlace tardío y no requiere el registro de los ensamblados .NET.

Declaraciones

Agregue las siguientes declaraciones a su proyecto:

#If VBA7 Then
Private Declare PtrSafe Function GetShortPathName Lib “Kernel32.dll” Alias “GetShortPathNameW” (ByVal LongPath As LongPtr, ByVal ShortPath As LongPtr, ByVal Size As Long) As Long
Private Declare PtrSafe Function SetDllDirectory Lib “Kernel32.dll” Alias “SetDllDirectoryW” (ByVal Path As LongPtr) As Long
Private Declare PtrSafe Sub LoadClr_x64 Lib “QlmCLRHost_x64.dll” (ByVal clrVersion As String, ByVal verbose As Boolean, ByRef CorRuntimeHost As IUnknown)
Private Declare PtrSafe Sub LoadClr_x86 Lib “QlmCLRHost_x86.dll” (ByVal clrVersion As String, ByVal verbose As Boolean, ByRef CorRuntimeHost As IUnknown)
#Else
Private Declare Function GetShortPathName Lib “Kernel32.dll” Alias “GetShortPathNameW” (ByVal LongPath As Long, ByVal ShortPath As Long, ByVal Size As Long) As Long
Private Declare Function SetDllDirectory Lib “Kernel32.dll” Alias “SetDllDirectoryW” (ByVal Path As Long) As Long
Private Declare Sub LoadClr_x64 Lib “QlmCLRHost_x64.dll” (ByVal clrVersion As String, ByVal verbose As Boolean, ByRef CorRuntimeHost As IUnknown)
Private Declare Sub LoadClr_x86 Lib “QlmCLRHost_x86.dll” (ByVal clrVersion As String, ByVal verbose As Boolean, ByRef CorRuntimeHost As IUnknown)
#End If ‘ WinAPI Declarations

' Declare variables
Dim m_myobject As Object
Dim m_homeDir As String

Inicialización

Debe inicializar la variable m_homeDir en la ruta donde se encuentran los ensamblados .NET.

Por ejemplo, si instala los ensamblados .NET en la misma carpeta que los archivos de Excel o MS-Access, debe inicializar m_homeDir para:

Excel: m_homeDir = ThisWorkbook.Path

Acceso: m_homeDir = CurrentProject.Path

Creación de objetos .NET

Agregue el siguiente código a su proyecto.

Private Function GetMyObject(dllPath As String, dllClass As String) As Object
    Dim LongPath As String
    Dim ShortPath As String

    LongPath = “\?” & m_homeDir
    ShortPath = String$(260, vbNull)

    PathLength = GetShortPathName(StrPtr(LongPath), StrPtr(ShortPath), 260)
    ShortPath = Mid$(ShortPath, 5, CLng(PathLength – 4))

    Call SetDllDirectory(StrPtr(ShortPath))
    Dim clr As mscoree.CorRuntimeHost

    If Is64BitApp() Then
        Call LoadClr_x64(“v4.0”, False, clr)
    Else
        Call LoadClr_x86(“v4.0”, False, clr)
    End If

    Call clr.Start

    Dim domain As mscorlib.AppDomain
    Call clr.GetDefaultDomain(domain)

    Dim myInstanceOfDotNetClass As Object
    Dim handle As mscorlib.ObjectHandle

    Set handle = domain.CreateInstanceFrom(dllPath, dllClass)

    Dim clrObject As Object
    Set GetMyObject = handle.Unwrap

    Call clr.Stop
End Function

Private Function Is64BitApp() As Boolean

    #If Win64 Then
        Is64BitApp = True
    #End If
End Function

Crear una instancia del objeto .NET

Ahora está listo para crear una instancia de su objeto .NET y comenzar a usarlo. Agregue el siguiente código a su aplicación:

m_homeDir = ThisWorkbook.Path 

m_myobject = GetMyObject(m_homeDir & “yourdotnet.dll”, “namespace.class”)

El primer argumento es la ruta completa a la DLL .NET.

El segundo argumento es el nombre completo del tipo solicitado, incluido el espacio de nombres, pero no el ensamblado, como lo devuelve la propiedad Type.FullName.

DLL requeridos

La solución requiere la implementación de 2 DLL que son responsables de alojar .NET CLR. Se espera que las DLL se implementen en la misma carpeta que su archivo Excel o MS-Access.

Las DLL se pueden descargar del sitio web de Soraco: https://soraco.co/products/qlm/QLMCLRHost.zip

Licencias LGPL-2.1

Por la presente, le otorgamos el derecho a utilizar nuestras DLL siempre que su aplicación no compita directa o indirectamente con Quick License Manager. Puede utilizar estos archivos DLL en sus aplicaciones comerciales o no comerciales.

La política predeterminada impide que CLR 4 ejecute el código heredado de CLR 2:

Set clr = New mscoree.CorRuntimeHost

Para habilitar la ejecución heredada, puede crear el archivo excel.exe.config en la carpeta donde excel.exe se encuentra:



  
    
  

O puede llamar a la función nativa CorBindToRuntimeEx en lugar de New mscoree.CorRuntimeHost :

Private Declare PtrSafe Function CorBindToRuntimeEx Lib "mscoree" ( _
    ByVal pwszVersion As LongPtr, _
    ByVal pwszBuildFlavor As LongPtr, _
    ByVal startupFlags As Long, _
    ByRef rclsid As Long, _
    ByRef riid As Long, _
    ByRef ppvObject As mscoree.CorRuntimeHost) As Long

Private Declare PtrSafe Function VariantCopy Lib "oleaut32" (dest, src) As Long


''
' Creates a .Net object with the CLR 4 without registration.  '
''
Function CreateInstance(assembly As String, typeName As String) As Variant
  Const CLR$ = "v4.0.30319"

  Static domain As mscorlib.AppDomain
  If domain Is Nothing Then
    Dim host As mscoree.CorRuntimeHost, hr&, T&(0 To 7)
    T(0) = &HCB2F6723: T(1) = &H11D2AB3A: T(2) = &HC000409C: T(3) = &H3E0AA34F
    T(4) = &HCB2F6722: T(5) = &H11D2AB3A: T(6) = &HC000409C: T(7) = &H3E0AA34F

    hr = CorBindToRuntimeEx(StrPtr(CLR), 0, 3, T(0), T(4), host)
    If hr And -2 Then err.Raise hr

    host.Start
    host.GetDefaultDomain domain
  End If

  VariantCopy CreateInstance, domain.CreateInstanceFrom(assembly, typeName).Unwrap
End Function

Te mostramos las reseñas y valoraciones de los usuarios

Si tienes alguna desconfianza y disposición de arreglar nuestro escrito eres capaz de añadir una acotación y con placer lo estudiaremos.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *