从 Excel VBA 将双精度数组发送到 C#( 使用 COM 互操作)






3.20/5 (6投票s)
2005年12月20日
2分钟阅读

92979

374
关于从 Excel VBA 向 C# 发送数据数组的技巧。
引言
Excel VBA 方法可以通过 COM 互操作调用 C# 对象方法。基本起点是通过 COM 互操作暴露 .Net 对象(如下所述)。然后您可以调用 .net 对象方法并传递参数——但是,如果其中一个参数是 double[],VBA 会在您尝试运行时抱怨。
"函数或接口被标记为受限,或者函数使用了 Visual Basic 中不支持的自动化类型"
如果您想要一种技术和一些代码片段,帮助您从 VBA 函数向 C# 方法发送数据数组,那么本文就是为您准备的。
背景 - 关于如何设置 VBA 以使用 C# 对象的一般信息
可能还有其他(也许更好/更简单)的技术,但这是我发现我必须做的事情。我想要调用的 C# 类必须实现一个接口 (interfaceExposer)。interfaceExposer 必须暴露我在 VBA 中想要访问的方法。//interfaceExposer.cs
using System;
namespace blah
{
public interface interfaceExposer
{
int callableMethodSimple(double a);
}
}
您的类应该实现此方法//cssClass.cs
using System;
namespace blah
{
public class callableClass : interfaceExposer
{
public int callableMethodSimple(double a)
{
return (int)a;
}
}
}
重要提示:指定您希望将此项目注册为 COM 互操作。转到项目菜单/项目属性,选择配置属性/生成,然后将“注册 COM 互操作”设置为 TRUE。
准备好尝试调用 callableClass.callableMethodSimple() 时进行编译
在 VBA 中:选择工具/引用,然后选择 COM 对象(在我的例子中为 SendArray)。要实例化类
'VBA code
Public cssObject As New SendArray.callableClass
'SendArray is the name of the project in which callableClass resides.
Dim iClass As interfaceExposer
Sub MyRoutine()
Set iClass = cssObject
Dim result As Integer
result = IClass.callableMethodSimple(5.0)
End Sub
但是,当您想要将数组发送到您的 cssObject 方法时…
如果您只是指定类似的内容,您会收到一个错误
...
public int callableMethodArray(double[] inputArray)
// this will not work at run time.
{
…
}
"函数或接口被标记为受限,或者函数使用了 Visual Basic 中不支持的自动化类型"。以下是您需要做的事情。首先在 interfaceExposer 上工作
//interfaceExposer.cs
using System;
namespace blah
{
public interface interfaceExposer
{
int callableMethodSimple(double a);
int callableMethodArray(object a);
// notice you are using object not a double[]
}
}
然后修复类代码//cssClass.cs using System; namespace blah { public class callableClass : interfaceExposer { .. . public int callableMethodArray(object a) { return 0; } }
现在,如果您要单步执行代码,当它进入 callableMethodArray() 时,您会看到对象 a 是一个包含数组元素的数组。
实际上使用数组的元素
您可能会想到将对象转换为 double[],然后像往常一样使用您的数据。但是类型转换不起作用//cssClass.cs using System; namespace blah { public class callableClass : interfaceExposer { .. . public int callableMethodArray(object a) { double[] receiverArray = new double[10]; receiverArray = (double[])a; // will bomb at run time return 0; } }
您可以使用反射从通用对象“a”中提取数据到 double[]。幸运的是,如果您计划接收一维 double[],这里有一个您可以使用的示例方法。您可以使用此方法作为原型,为其他格式的数组创建更多方法。
//cssClass.cs using System; using System.Reflection; // ADD THIS. namespace blah { public class callableClass : interfaceExposer { .. . public int callableMethodArray(object a) { double[] thisVect = LoadComObjectIntoDoubleArray(a); return 0; } private double[] LoadComObjectIntoDoubleArray(object comObject) { Type thisType = comObject.GetType(); Type dblType = Type.GetType("System.Double[*]"); double[] doubleArray = new double[1]; // temporary allocation to keep compiler happy. if(thisType == dblType) { object[] args = new object[1]; int numEntries = (int)thisType.InvokeMember("Length", BindingFlags.GetProperty, null, comObject, null); doubleArray = new double[numEntries]; for(int j1=0; j1 < numEntries; j1++) { args[0] = j1+1; // since VB arrays index from 1 doubleArray[j1] = (double)thisType.InvokeMember("GetValue", BindingFlags.InvokeMethod, null, comObject, args); } } // End if(thisType == dblType) return doubleArray; } // End LoadComObjectIntoDoubleArray() } }
这将成功地将您的数组数据从 VBA 导入到 C# 方法。要从 VBA 调用此方法,请查看下面的代码示例。
'VBA code
Public cssObject As New SendArray.callableClass
'SendArray is the name of the project
'in which callableClass resides.
Dim iClass As interfaceExposer
Sub MyRoutine()
Set iClass = cssObject
Dim result As Integer
Dim SendArray(1 To 2) As Double
SendArray(1) = 5.2
SendArray(2) = 7.5
result = iClass.callableMethodArray(SendArray)
End Sub
联系方式
请就讨论论坛中的澄清或建议给我写信。祝您愉快。