gpt4 book ai didi

.net - 从 vba 调用 .net 库方法

转载 作者:行者123 更新时间:2023-12-03 21:19:00 24 4
gpt4 key购买 nike

我在 ASP.net、c# 中开发了一个 Web 服务,并托管在 IIS 上,供 vba 客户端使用。下载了 Office 2003 Web Services 2.01 工具包后,我在成功创建所需的代理类时遇到了问题(许多用户在线记录),并决定改为创建一个 .net dll 库。我已经创建了库,它引用了 Web 服务并将其方法之一公开给 c# 中的公共(public)函数。

我现在有三个问题:

  • 如何在 VBA 中引用 dll 类?我试图转到工具-> 引用并浏览到 dll 位置,但我收到错误“无法添加对指定文件的引用”。磁盘上是否有我必须复制 .dll 的特定位置?
  • 我还可以将 dll.config 文件复制到 dll 文件旁边,以便在那里有端点 url 吗?
  • 由于调用的方法是接受一个对象(由各种成员和几个 List<> 成员组成,这些如何在 VBA 代码中实现?
  • 最佳答案

    您需要为您的程序集 (DLL) 创建一个可调用 COM 的包装器 (CCW)。 .NET 互操作性是一个相当深入的话题,但它相对容易实现。

    首先,您需要确保您的整个程序集都注册了 COM 互操作。您可以通过选中“注册 COM 互操作”在 Visual Studio 的“构建”选项卡上执行此操作。其次,您应该在所有类中包含 System.Runtime.InteropServices:

    using System.Runtime.InteropServices;

    接下来,您应该使用 [Serializable(), ClassInterface(ClassInterfaceType.AutoDual), ComVisible(true)] 装饰所有要公开的类。属性。这将使您可以正确访问类成员并在 VBA 编辑器中使用智能感知。

    您需要有一个入口点——即一个主类,并且该类应该有一个不带参数的公共(public)构造函数。从该类中,您可以调用返回其他类实例的方法。这是一个简单的例子:
    using System;
    using System.Collections.Generic;
    using System.Runtime.InteropServices;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;

    namespace MyCCWTest
    {
    [Serializable(), ClassInterface(ClassInterfaceType.AutoDual), ComVisible(true)]
    public class Main
    {
    public Widget GetWidget()
    {
    return new Widget();
    }
    }

    [Serializable(), ClassInterface(ClassInterfaceType.AutoDual), ComVisible(true)]
    public class Widget
    {
    public void SayMyName()
    {
    MessageBox.Show("Widget 123");
    }
    }
    }

    编译程序集后,您应该能够通过转到“工具 > 引用”在 VBA 中包含对它的引用:

    enter image description here
    然后你应该能够访问你的主类和任何其他类,如下所示:
    Sub Test()
    Dim main As MyCCWTest.main
    Set main = New MyCCWTest.main
    Dim myWidget As MyCCWTest.Widget
    Set myWidget = main.GetWidget
    myWidget.SayMyName
    End Sub

    回答您关于 List<> 的问题:COM 对泛型一无所知,因此不支持它们。事实上,在 CCW 中使用数组甚至是一个棘手的问题。根据我的经验,我发现最简单的方法是创建自己的集合类。使用上面的示例,我可以创建一个 WidgetCollection 类。这是一个稍加修改的项目,其中包含 WidgetCollection 类:
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Runtime.InteropServices;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;

    namespace MyCCWTest
    {
    [Serializable(), ClassInterface(ClassInterfaceType.AutoDual), ComVisible(true)]
    public class Main
    {
    private WidgetCollection myWidgets = new WidgetCollection();

    public Main()
    {
    myWidgets.Add(new Widget("Bob"));
    myWidgets.Add(new Widget("John"));
    myWidgets.Add(new Widget("Mary"));
    }

    public WidgetCollection MyWidgets
    {
    get
    {
    return myWidgets;
    }
    }
    }

    [Serializable(), ClassInterface(ClassInterfaceType.AutoDual), ComVisible(true)]
    public class Widget
    {
    private string myName;

    public Widget(string myName)
    {
    this.myName = myName;
    }

    public void SayMyName()
    {
    MessageBox.Show(myName);
    }
    }

    [Serializable(), ClassInterface(ClassInterfaceType.AutoDual), ComVisible(true)]
    public class WidgetCollection : IEnumerable
    {
    private List<Widget> widgets = new List<Widget>();

    public IEnumerator GetEnumerator()
    {
    return widgets.GetEnumerator();
    }

    public Widget this[int index]
    {
    get
    {
    return widgets[index];
    }
    }

    public int Count
    {
    get
    {
    return widgets.Count;
    }
    }

    public void Add(Widget item)
    {
    widgets.Add(item);
    }

    public void Remove(Widget item)
    {
    widgets.Remove(item);
    }
    }
    }

    您可以在 VBA 中像这样使用它:
    Sub Test()
    Dim main As MyCCWTest.main
    Set main = New MyCCWTest.main
    Dim singleWidget As MyCCWTest.Widget

    For Each singleWidget In main.myWidgets
    singleWidget.SayMyName
    Next
    End Sub

    注意:我已包含 System.Collections;在新项目中,所以我的 WidgetCollection 类可以实现 IEnumerable。

    关于.net - 从 vba 调用 .net 库方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19954001/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com