2012-10-19 84 views
2

此C#代碼是在.NET 4.5 ComVisible組件:暴露於VBA(COM)C#屬性:運行時錯誤 '424':對象需要

C#代碼

[InterfaceType(ComInterfaceType.InterfaceIsDual)] 
[Guid("22341123-9264-12AB-C1A4-B4F112014C31")] 
public interface IComExposed 
{ 
    double[] DoubleArray { get; set; } 
    object[] ObjectArray { get; set; } 
    object PlainObject { get; set; } 
    double ScalarDouble { get; set; } 
} 

[ClassInterface(ClassInterfaceType.None)] 
[Guid("E4F27EA4-1932-2186-1234-111CF2722C42")] 
[ProgId("ComExposed")] 
public class ComExposed : IComExposed 
{ 
    public double[] DoubleArray { get; set; } 
    public object[] ObjectArray { get; set; } 
    public object PlainObject { get; set; } 
    public double ScalarDouble { get; set; } 
} 

從Excel 2010中32位VBA,我有以下行爲:

VBA代碼

Dim VBArray(1 To 3) As Double 
VBArray(1) = 1 
VBArray(2) = 2 
VBArray(3) = 3 

Dim oComExposedEarlyBinding As New ComExposed 

' Works 
oComExposedEarlyBinding.ScalarDouble = 5 

' Compile Error: Function or interface marked as restricted, 
' or the function uses an Automation type not supported in Visual Basic 
oComExposedEarlyBinding.DoubleArray = VBArray 

' Compile Error: Function or interface marked as restricted, 
' or the function uses an Automation type not supported in Visual Basic 
oComExposedEarlyBinding.ObjectArray = VBArray 

' Run-time error '424': Object required 
oComExposedEarlyBinding.PlainObject = VBArray 

' Run-time error '424': Object required 
oComExposedEarlyBinding.PlainObject = 5 

Dim oComExposedLateBinding As Variant 
Set oComExposedLateBinding = New ComExposed 

' Works 
oComExposedLateBinding.ScalarDouble = 5 

' Run-time error '5': Invalid procedure call or argument 
oComExposedLateBinding.DoubleArray = VBArray 

' Run-time error '13': Type mismatch 
oComExposedLateBinding.ObjectArray = VBArray 

' Works 
oComExposedLateBinding.PlainObject = VBArray 

' Works 
oComExposedLateBinding.PlainObject = 5 

正如您所注意到的PlainObject正在後期綁定模式下工作,但很顯然,這是由於輸入丟失而導致VBA中的自動完成(IntelliSense)失敗,這在我的場景中是不可接受的。

,我關心的皺紋在我的例子是以下行:

oComExposedEarlyBinding.DoubleArray = VBArray 
oComExposedEarlyBinding.ObjectArray = VBArray 
oComExposedEarlyBinding.PlainObject = VBArray 

得到任何的三條線以上工作會滿足我的需要,所以你有什麼解決方法或解決方案,這將使這項工作(請注意,我不想將數組作爲參數傳遞給函數)?

更新: 將此問題提交給Microsoft的支持並等待將近三週後。他們確認這是一個bug,這是KB:http://support.microsoft.com/kb/327084,C#中唯一的解決方法就是標記爲下面的解決方案。 但是,如果用C++/CLI編寫,我能夠確認此代碼的工作方式與預期的相同。

+2

甲VBA陣列必須0下界是與C#陣列兼容。 –

+0

我一直在將數組作爲函數參數從COM傳遞給.NET,然後將它們轉換爲.NET中的基於零的數據。你是說因爲這個問題上面的代碼失敗了嗎? – Adam

回答

2

VBA陣列必須基於零和在c#使用ref參數,樣品:

Option Explicit 

Sub test() 
    Dim VBArray(0 To 2) As Double 
    VBArray(0) = 1 
    VBArray(1) = 2 
    VBArray(2) = 3 

    Dim oComExposedEarlyBinding As New ComExposed 
    oComExposedEarlyBinding.SetDoubleArray VBArray 

End Sub 

using System.Runtime.InteropServices; 

namespace COMVisibleTest 
{ 
    [InterfaceType(ComInterfaceType.InterfaceIsDual)] 
    [Guid("22341123-9264-12AB-C1A4-B4F112014C31")] 
    public interface IComExposed 
    { 
     void SetDoubleArray(ref double[] doubleArray); 
    } 

    [ClassInterface(ClassInterfaceType.None)] 
    [Guid("E4F27EA4-1932-2186-1234-111CF2722C42")] 
    [ProgId("ComExposed")] 
    public class ComExposed : IComExposed 
    { 
     private double[] _doubleArray; 

     public void SetDoubleArray(ref double[] doubleArray) 
     { 
      _doubleArray = doubleArray; 
     } 
    } 
} 
+0

這已經在我刪除的答案中說過了,因爲OP不喜歡這個解決方案。 – yms

+0

謝謝丹尼爾。我沒有問題將它作爲參數傳遞給函數。但是我特意要求物業,因此最終的標題和票據。 – Adam

+0

亞當,我沒有注意到你要求財產...即使你在你的問題的標題中寫道:-) ...對不起!這是我知道如何將數據從C#傳遞到VBA的唯一途徑。祝你好運! – dee

1

VBA總是按照引用(VT_VARIANT | VT_BYREF)傳遞包裝在變體中的數組,因爲其中包含實際數組的其他變體,所以在指定元素類型時不能在屬性中使用數組,所以需要使用方法您可以將參數指定爲「通過參考」。

[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] 
[Guid("22341123-9264-12AB-C1A4-B4F112014C31")] 
public interface IComExposed 
{ 
    void setDoubleArray(ref double[] myArray); 
    //(...) 
} 

一個類似的問題:
Pass an array from vba to c# using com-interop

對這個問題的回答中提到使用用戶定義的集合,而不是原始類型的數組中的選項,也許這也可以成爲解決你的問題。在文檔中

相關參考文獻:

Marshaling ByRef Variants

VARIANT and VARIANTARG in WinAPI

MarshalAsAttribute class in .Net

Passing Arrays to COM in .Net

+0

用戶定義的集合dosn't幫助我,因爲此示例中的數組表示Range.Value,它是一個本地數組。儘管您提供的解決方案是一種解決方案,但我認爲還沒有其他解決方案。 – Adam

相關問題