c# - 如何从 Excel VBA 调用 .NET 方法?

标签 c# .net vba runtime clr

我找到了一种直接从 VBA 代码调用 .NET 2 代码的方法:

Dim clr As mscoree.CorRuntimeHost
Set clr = New mscoree.CorRuntimeHost
clr.Start
Dim domain As mscorlib.AppDomain
clr.GetDefaultDomain domain
Dim myInstanceOfDotNetClass As Object
Set myInstanceOfDotNetClass = domain.CreateInstanceFrom("SomeDotNetAssembly.dll", "Namespace.Typename").Unwrap
Call myInstanceOfDotNetClass.ExecuteSomeDotNetMethod

我使用工具 -> 引用向 Excel VBA 添加了对 mscoree.tlb 和 mscorlib.tlb 的引用。

这适用于 .NET CLR 2 程序集,直到 .NET Framework 版本 3.5。

我需要让它与 .NET 4 一起工作。

我了解到 .NET CLR4 引入了另一种与版本无关的创建运行时实例的方法,并且我找到了一个用 C++ 编写的代码示例: http://dev.widemeadows.de/2014/02/04/hosting-the-net-4-runtime-in-a-native-process/

我的 Excel VBA 技能不足以翻译那几行代码。

最佳答案

这是一个canonical回答从 Excel(或 VBA)调用 .Net 的 3 种主要方法。

这三种方式都适用于 .Net 4.0。

1. XLL

第 3 方供应商 Add-In Express 提供 XLL 功能,但其免费且易于使用的 Excel-DNA 作者在这里 https://stackoverflow.com/users/44264

这是 Excel-DNA 页面的摘录:https://excel-dna.net/

Introduction

Excel-DNA is an independent project to integrate .NET into Excel. With Excel-DNA you can make native (.xll) add-ins for Excel using C#, Visual Basic.NET or F#, providing high-performance user-defined functions (UDFs), custom ribbon interfaces and more. Your entire add-in can be packed into a single .xll file requiring no installation or registration.

Getting Started

If you are using a version of Visual Studio that supports the NuGet Package Manager (including Visual Studio 2012 Express for Windows Desktop), the easiest way to make an Excel-DNA add-in is to:

Create a new Class Library project in Visual Basic, C# or F#. Use the Manage NuGet Packages dialog or the Package Manager Console to install the Excel-DNA package:

PM> Install-Package Excel-DNA

Add your code (C#, Visual Basic.NET or F#):

using ExcelDna.Integration;
public static class MyFunctions
{
    [ExcelFunction(Description = "My first .NET function")]
    public static string SayHello(string name)
    {
        return "Hello " + name;
    }
}

Compile, load and use your function in Excel:

=SayHello("World!")

<强>2。自动化插件

Eric Carter 的这篇文章展示了如何做到这一点,这篇文章缺少大量图像,所以我复制/粘贴了整篇文章并重新创建了图像以供保存。

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

Excel enables the creation of user defined functions that can be used in Excel formulas. A developer must create a special kind of DLL called an XLL. Excel also allows you to write custom functions in VBA that can be used in Excel formulas. Unfortunately, Excel does not support or recommend writing an XLL that uses managed code. If you are willing to take your chances that your XLL might not run in current or future versions of Excel, there are solutions available that enable this scenario—search the web for “managed XLL”.

Fortunately, there is an easier way to create a user defined function that doesn’t require you to create an XLL dll. Excel XP, Excel 2003, and Excel 2007 support something called an Automation Add-in. An Automation Add-in can be created quite simply in C# or VB.NET. I’m going to show you an example in C#.

First, launch Visual Studio and create a new C# class library project called AutomationAddin for this example.

Then, in your Class1.cs file, enter the code shown below. Replace the GUID with your own GUID that you create by using Generate GUID in the Tools menu of 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();
    }  
  }
}

With this code written, show the properties for the project by double clicking on the properties node under the project in Solution Explorer. Click on the Build tab and check the check box that says “Register for COM Interop”. At this point you have an extra step if you are running on Windows Vista or higher. Visual Studio has to be run with administrator privileges to register for COM interop. Save your project and exit Visual Studio. Then find Visual Studio in the Start menu and right click on it and choose “Run as Administrator”. Reopen your project in Visual Studio. Then choose “Build” to build the add-in.

enter image description here

Now launch Excel and get to the Automation servers dialog by following these steps:

  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.
    

You can find the class you created by looking for AutomationAddin.MyFunctions in the list of Automation add-ins:

enter image description here

Now, let’s try to use the function MultiplyNTimes inside Excel. First create a simple spreadsheet that has a number, a second number to multiple the first by, and a third number for how many times you want to multiply the first number by the second number. An example spreadsheet is shown here:

enter image description here

Click on an empty cell in the workbook below the numbers and then click on the Insert Function button in the formula bar. From the dialog of available formulas, drop down the “Or select a category” drop down box and choose “AutomationAddin.MyFunctions.

enter image description here

Then click on the MultiplyNTimes function as shown here:

enter image description here

When you press the OK button, Excel pops up a dialog to help you grab function arguments from the spreadsheet as shown here:

enter image description here

Finally, click OK and see your final spreadsheet as shown here with your custom formula in cell C3.

enter image description here


3.从 Excel VBA 调用 .Net

使用 Automation.AddIn 项目中的代码,我们可以轻松地从 Excel VBA 调用 MultiplyNTimes 函数。

首先从 Excel 添加对 DLL 的引用,为此您需要在 VB 编辑器中。按 Alt + F11,然后单击“工具”菜单和“引用”:

enter image description here

选择 AutomationAddIn DLL:

enter image description here

添加 VBA 代码以调用 .Net DLL:

Sub Test()

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

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

End Sub

嘿嘿!

enter image description here


请注意,如果您在 C# 中使用类,则需要使用 ClassInterface 标记它们,并使用标记为 ComVisible = true 的接口(interface):Use CLR classes from COM addin in Excel VBA?

最后还有一些关于 Excel 和 .Net 的优秀 MSDN 文章,作者是“Andrew Whitechapel”- google them

关于c# - 如何从 Excel VBA 调用 .NET 方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37074533/

相关文章:

c# - 维护对象之间的一对一映射

c# - 是否有实时 IIS 流量查看器(或通过 C# 以编程方式获取它的方式)

VBA 数组不起作用?

excel - 在vba中使用LOCALE_NAME_USER_DEFAULT系统常量

C#:如何设计一个泛型类,使得类型参数必须继承某个类?

c# - 以 DataTable 作为源的 GridView 不自动分页或排序

c# - MailItem.HtmlBody 引发未实现异常

c# - 使用完整字符串路径打开注册表项

c# - 异常 : system. IO.FileNotFoundException : cannot find assembly or file Mysql. 数据

regex - 使用正则表达式查找和替换单词 |交替运算符