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.
Ahora inicie Excel y acceda al cuadro de diálogo Servidores de automatización siguiendo estos pasos:
-
Launch Excel and click the Microsoft Office button in the top left corner of the window.
-
Choose Excel Options.
-
Click the Add-Ins tab in the Excel Options dialog.
-
Choose Excel Add-Ins from the combo box labeled Manage. Then click the Go button.
-
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:
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:
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".
Luego haga clic en la función MultiplyNTimes como se muestra 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í:
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.
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:
Seleccione la DLL AutomationAddIn:
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!
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.