创建一个C# COM可见类非常容易,而且(正如您在评论中所说)它还很有趣。这是一个小示例。
在一个新的C#库项目中添加:
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace CSharpCom
{
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
[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);
}
[Guid("5D338F6F-A028-41CA-9054-18752D14B1BB")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
interface ICSharpComEvents
{
}
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
[ComSourceInterfaces(typeof(ICSharpComEvents))]
[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时出现版本问题。
编译后,在Visual Studio命令提示符中使用regasm
注册DLL。根据您使用的Office版本选择32位或64位的regasm...您可以在以下路径中找到RegAsm:C:\windows\Microsoft.NET\Framework
或 C:\windows\Microsoft.NET\Framework64
(分别对应32位和64位):
C:\windows\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe /codebase /tlb CSharpCom.dll
这将在Windows中注册您的DLL,因此现在在VBA编辑器中,您应该能够转到工具->引用并找到您的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()方法;这可以在“close”方法中完成,但如果VBA崩溃并且您的关闭方法从未被调用,这可能会引起内存泄漏/问题,只是另一个需要考虑的问题。