簡體   English   中英

可以使用com interop將變量數組傳遞給C#嗎?

[英]Can a variant array be passed to C# using com interop?

我嘗試在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

有什么建議我怎么能這樣做,而不是一次一個地設置變量數組中的每個值?

我找到了一個基於此處發布的代碼的解決方案。 變量數組必須作為對象從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 - 它可以作為object [,]或double [,]傳遞得更舒服。
希望沒有語法拼寫錯誤:)。

通過使用Set,你告訴VBA“values”是一個對象(在本例中是一個Range),但是當你將它賦給ExcelValues時你沒有使用set。 在讀取值時嘗試刪除Set。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM