创建一个 C# COM 可见类非常简单,而且(正如您在评论中所说)它很有趣。这是一个小样本。
在新的 C# 库项目中,添加:
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace CSharpCom
{
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
//The 3 GUIDs in this file need to be unique for your COM object.
//Generate new ones using Tools->Create GUID in VS2010
[Guid("18C66A75-5CA4-4555-991D-7115DB857F7A")]
public interface ICSharpCom
{
string Format(string FormatString, [Optional]object arg0, [Optional]object arg1, [Optional]object arg2, [Optional]object arg3);
void ShowMessageBox(string SomeText);
}
//TODO: Change me!
[Guid("5D338F6F-A028-41CA-9054-18752D14B1BB")] //Change this
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
interface ICSharpComEvents
{
//Add event definitions here. Add [DispId(1..n)] attributes
//before each event declaration.
}
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
[ComSourceInterfaces(typeof(ICSharpComEvents))]
//TODO: Change me!
[Guid("C17C5EAD-AA14-464E-AD32-E9521AC17134")]
public sealed class CSharpCom : ICSharpCom
{
public string Format(string FormatString, [Optional]object arg0, [Optional]object arg1, [Optional]object arg2, [Optional]object arg3)
{
return string.Format(FormatString, arg0, arg1, arg2, arg3);
}
public void ShowMessageBox(string SomeText)
{
MessageBox.Show(SomeText);
}
}
}
您将需要进入您的项目属性,进入“签名”选项卡,选中复选框以签署您的程序集,并创建一个新的“强名称密钥文件”。这将有助于防止您注册的 DLL 出现版本控制问题。
编译它,并regasm
在 Visual Studio 命令提示符下注册 DLL。您将使用 32 位或 64 位 regasm,具体取决于您使用的 Office 版本...您将在C:\windows\Microsoft.NET\Framework
或C:\windows\Microsoft.NET\Framework64
(分别为 32 位和 64 位)中找到 RegAsm:
C:\windows\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe /codebase /tlb CSharpCom.dll
这将在 Windows 中注册您的 DLL,因此现在在 VBA 编辑器中,您应该能够转到 Tools->References 并找到您的 COM 命名空间“CSharpCom”。选中该框,现在您应该能够在 VBA 中创建 COM 对象:
Sub TestCom()
Dim c As CSharpCom.CSharpCom
Set c = New CSharpCom.CSharpCom
c.ShowMessageBox c.Format("{0} {1}!", "Hello", "World")
End Sub
您可以将表单添加到您的 COM 对象,并在 VBA 调用特定方法时打开它们;您应该能够使用它来创建带有进度条的表单。不过,要考虑的一件事是 VBA 是单线程的。这意味着在您的代码运行时,其他所有内容都会被冻结,因此事情可能会变得有些棘手。
在我的脑海中,你可以在你的 COM 可见类中创建 3 个方法:一个打开表单,一个更新进度(在 VBA 调用 COM 对象上的 update() 方法后立即调用 VBA 的 DoEvents() 方法,以允许 Office 处理屏幕更新),以及关闭它。您应该在表单上调用 Dispose();这可以在“关闭”方法中完成,但我认为如果你的 VBA 崩溃,它可能会导致内存泄漏/问题,并且你的 close 方法永远不会被调用——只是需要考虑的其他事情。