2011-05-10 48 views
2

我尝试在Excel和C#之间传输一些数据。为此,我编写了一个简单的C#类,使用一个属性来设置和获取数据。使用COM互操作可以将变体数组传递给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 

任何建议,我怎么能acomplish这一点,没有在同一时间从变量数组一个设定每个值?

回答

0

通过使用Set,你告诉VBA“values”是一个对象(在本例中是一个Range),但是当你将它赋值给ExcelValues时,你并没有使用set。尝试在读取值时放下Set。

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

你说得对。这是一个错字,但它不是解决问题的办法。 – 2011-05-11 07:31:55

2

我发现了一个解决方案,它基于已发布的代码here。变体数组必须从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; 
    } 
} 

另一种方法 - 从C#至VBA - 它可以传递更多的舒适对象[,]或双[,]。
希望没有语法错别字:)。

相关问题