除了已有的答案之外,使用 .NET 4.0,在不注册COM的情况下,在您的VBA项目中使用C# dll实际上非常简单。
编辑: 我刚试过了在C:\windows\Microsoft.NET\Framework\v2.0.50727
中的mscorlib.tlb
和mscoree.tlb
--加载一个在3.5编译的程序集-- 它完全可以正常工作。因此显然您不需要.NET 4.0。
以下是如何在您的VBA项目中使用C# dll的示例。它略微修改自这个答案。
1)在您的VBA项目中添加对以下类型库的引用(工具->引用):
C:\windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.tlb
C:\windows\Microsoft.NET\Framework\v4.0.30319\mscoree.tlb
(如果您正在运行 64 位 Office,请使用 Framework64 文件夹)
2)在您的 C# 项目中,请确保向您的类添加 [ComVisible(true)]
属性:
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace VB6FuncLib
{
[ComVisible(true)]
public class VB6FuncLib
{
public VB6FuncLib()
{ }
public void test()
{
MessageBox.Show("Test Successful");
}
}
}
您无需勾选“注册COM互操作”选项。那只适用于构建标准的COM对象。除非您希望整个程序集可见 (这也会消除需要使用COMVisible
属性),否则也不必勾选“使程序集对COM可见”选项。
3)在您的VBA代码中,添加一个新模块,并加入此代码:
Sub Test()
Dim Host As mscoree.CorRuntimeHost
Set Host = New CorRuntimeHost
Host.Start
Dim Unk As IUnknown
Host.GetDefaultDomain Unk
Dim AppDomain As AppDomain
Set AppDomain = Unk
Dim ObjHandle As ObjectHandle
Set FS = CreateObject("Scripting.FileSystemObject")
Path = FS.GetParentFolderName(CurrentDb().Name)
Set ObjHandle = AppDomain.CreateInstanceFrom(Path & "\VB6 Function Library.dll", "VB6FuncLib.VB6FuncLib")
Dim ObjInstance As Object
Set ObjInstance = ObjHandle.Unwrap
ObjInstance.test
Host.Stop
End Sub
4) 将DLL复制到与您的Office项目相同的文件夹中,并在VBA中运行Test()子程序。
注意:
需要注意的是,这种技术的局限性之一是,如果.DLL存储在远程网络共享上,它将无法工作。一个简单的解决方案是将其复制到每台PC上使用的同一本地文件夹中。另一个解决方案是将二进制文件包含在您的Access应用程序/VBA项目中,并让MS-Access导出它们。可以通过将它们存储在表格或电子表格中的Base64中,然后将它们转换并导出为二进制来实现这一点。
我能够通过创建一个类型库与DLL配合(使用tlbexp),并在我的VBA项目中添加对TLB的引用来使早期绑定(因此Microsoft IntelliSense)工作,但它确实使问题有些复杂,因为它需要您的VBA应用程序知道DLL和TLB文件在哪里(还需要有人确保它们在那里)。
C#库不是普通的DLL。它们更类似于COM库,需要在使用之前进行注册(就像ActiveX控件一样),特别是当从非.NET代码中调用时。
(当然,除非事情已经改变...)