Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/291.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
可以使用com互操作将变量数组传递给C#吗?_C#_Vba_Com Interop - Fatal编程技术网

可以使用com互操作将变量数组传递给C#吗?

可以使用com互操作将变量数组传递给C#吗?,c#,vba,com-interop,C#,Vba,Com Interop,我尝试在Excel和C#之间传输一些数据。为此,我编写了一个简单的C#类,其中包含一个属性来设置和获取数据 [Guid("xxx")] [ClassInterface(ClassInterfaceType.AutoDual)] [ComVisible(true)] public class Vector { private object[,] _values; public object[,] ExcelValues { get { ... }

我尝试在Excel和C#之间传输一些数据。为此,我编写了一个简单的C#类,其中包含一个属性来设置和获取数据

[Guid("xxx")]
[ClassInterface(ClassInterfaceType.AutoDual)]
[ComVisible(true)]
public class Vector
{
    private object[,] _values;

    public object[,] ExcelValues
    {
        get { ... }
        set { ... }
    }
}
在VBA中获取ExcelValues属性效果很好,但无法在VBA中设置它。如果尝试设置属性,则VBA代码不会编译:

    Dim values As Variant
    With myRange
        ' typo: Set values = Range(.Offset(0, 0), .Offset(100, 0))
        values = Range(.Offset(0, 0), .Offset(100, 0))
    End With

    Dim data As New Vector

    ' this doesn't compile
    data.ExcelValues = values      

    ' this works
    values = data.ExcelValues

有没有什么建议可以让我完成这项工作,而不必每次从变量数组中设置一个值

通过使用Set,您告诉VBA“值”是一个对象(在本例中是一个范围),但在将其指定给值时,您没有使用Set。读取值时,请尝试删除集合

With myRange         
    values = Range(.Offset(0, 0), .Offset(100, 0)).Value     
End With 

我根据发布的代码找到了一个解决方案。变量数组必须作为对象(而不是对象[,])从VBA传递到C。然后可以使用反射将其转换为更方便的内容:

[Guid("xxx")]
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.AutoDual)]
public class Vector
{        
    [ComVisible(false)]
    public IList<double> Values { get; set; }

    public object[,] GetExcelValues()
    {
        // own extension method
        return Values.ConvertToExcelColumn();
    }

    public void SetExcelValues(object comArray)
    {
        IEnumerable<object> values = ConvertExcelCloumnToEnumerable(comArray);
        Values = new List<double>(values.Select(Convert.ToDouble));
    }

    private static IEnumerable<object> ConvertExcelCloumnToEnumerable(object comObject)
    {
        Type comObjectType = comObject.GetType();

        if (comObjectType != typeof(object[,]))
            return new object[0];

        int count = (int)comObjectType.InvokeMember("Length", BindingFlags.GetProperty, null, comObject, null);
        var result = new List<object>(count);

        var indexArgs = new object[2];
        for (int i = 1; i <= count; i++)
        {
            indexArgs[0] = i;
            indexArgs[1] = 1;
            object valueAtIndex = comObjectType.InvokeMember("GetValue", BindingFlags.InvokeMethod, null, comObject, indexArgs);
            result.Add(valueAtIndex);
        }

        return result;
    }
}
[Guid(“xxx”)]
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.AutoDual)]
公共类向量
{        
[ComVisible(false)]
公共IList值{get;set;}
公共对象[,]GetExcelValues()
{
//自身扩展方法
返回值。ConvertToExcelColumn();
}
public void SetExcelValues(对象comArray)
{
IEnumerable values=ConvertExcelCloumnToEnumerable(comArray);
Values=新列表(Values.Select(Convert.ToDouble));
}
私有静态IEnumerable ConvertExcelCloumnToEnumerable(对象comObject)
{
类型comObjectType=comObject.GetType();
if(comObjectType!=typeof(对象[,]))
返回新对象[0];
int count=(int)comObjectType.InvokeMember(“长度”,BindingFlags.GetProperty,null,comObject,null);
var结果=新列表(计数);
var indexArgs=新对象[2];

对于(inti=1;i),你是对的。这是一个打字错误,但不是问题的解决方案。