Csharp/C#教程:在C#和VBA之间进行通信分享


在C#和VBA之间进行通信

应我老板的要求,我创建了一小组脚本,用于定期监控某些设备和进程的状态。 随后使用相对复杂的VBA模块处理此信息,该模块收集所有信息,应用公式,设置范围并生成图表等。

但是有两个问题:我是业余程序员,所以我的VBA例程非常低效。 这对我来说不是一个大问题(我只是在跑步时起床喝咖啡),但对于其他用户来说,这可能很麻烦,因为不知道为什么这么长时间。 我想要一个进度的图形表示。 应用程序的配置是通过文本文件完成的。 我想提供一个体面的GUI来设置配置。

为了实现这一点,我正在寻找一种让我的C#WinForms应用程序与我的VBA应用程序通信的方法。 我知道如何从我的C#应用​​程序运行VBA例程,但我不知道如何让它们实时进行操作。

以下是我特别想要实现的两件事:

我已经考虑过通过标准输出进行通信。 我知道如何使用C#/ .Net从标准输出中读取,但我不确定如何使用VBA写入StdOut流。

我相信很多人会指出我想要实现的是愚蠢和老式(或完全没必要),但作为业余程序员,对我来说这似乎是一个非常具有挑战性和有趣的项目,可以教我一件事或两个。

创建一个C#COM可见类非常简单,并且(正如您在评论中所说)很有趣。 这是一个小样本。

在新的C#Library项目中,添加:

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的版本控制问题。

编译它,并在Visual Studio命令提示符中使用regasm注册DLL。 您将使用32或64位regasm,具体取决于您使用的Office版本…您将在C:windowsMicrosoft.NETFrameworkC:windowsMicrosoft.NETFramework64 (32)中找到RegAsm和64位,分别):

C:windowsMicrosoft.NETFrameworkv4.0.30319RegAsm.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-visible类中创建3个方法:一个用于打开表单,一个用于更新进度(在VBA调用COM对象上的update()方法之后立即调用VBA的DoEvents()方法,允许Office处理屏幕更新),并关闭它。 你应该在表单上调用Dispose(); 这可以在“关闭”方法中完成,但我认为如果您的VBA崩溃,它可能会导致内存泄漏/问题,并且您的close方法永远不会被调用 – 只需要考虑其他事项。

您可以将.NET DLL与VB6项目一起使用,并创建在程序集中定义的任何对象的实例。 这是通过创建类型库文件(.tlb)为COM互操作(在VB6中使用)注册.NET程序集(.dll)来完成的。 .tlb文件包含额外信息,以便您的VB6项目可以使用.dll。 注意,您的VB6项目不会引用.dll而是相应的.tlb文件。 您可以使用Regasm.exe实用程序生成并注册类型库并注册托管程序集的位置。 然后它只是创建一个.NET对象的实例,无论是WinForm还是其他一些很酷的类。 =)。

 Dim MyDotNetObject As MyDotNetClass Set MyDotNetObject = New MyDotNetClass MyDotNetObject.SomeMethod(value1, value2) ''end of execution Set MyDotNetObject = Nothing 

请参阅: http : //support.microsoft.com/default.aspx?scid = kb; en-us; 817248

我相信此链接中的代码大致符合您的要求:

https://msdn.microsoft.com/en-us/library/66ahbe6y.aspx

我不自称理解这段代码,我的目标是表明这个解决方案会错综复杂! 你应该只用一个解决方案来构建它。 一个完整的VBA解决方案将更快开发(您只需要学习简单的VBA表格),但旧技术。 一个完整的C#解决方案开发会比较慢,但之后你就可以学习C#了。

性能实际上是一个问题。 如果它现在执行效率低下,当你有5倍的记录需要处理时会发生什么? 获得那么多记录之前,您应该解决性能问题。

上述就是C#学习教程:在C#和VBA之间进行通信分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/cdevelopment/960945.html

(0)
上一篇 2021年11月25日
下一篇 2021年11月25日

精彩推荐