使用COM互操作将VBA中的数组传递到C#

7

如何使用com-interop从vba向.net(特别是c#)传递用户定义类的数组?

这是我的c#代码。如果我从vba调用Method1,它会失败并显示“期望数组或用户定义类型”或“函数使用visual basic不支持的自动化类型”。

public class MyClass 
{
    public Method1(UserDefinedClass[] Parameters) { ... }
    public Method2(Object Parameters) { ... }
}

我已经了解了一些关于MarshallAsAttribute类的知识。这个类能否成为C#代码中缺失的部分呢?
以下是我正在使用的VBA代码:
Dim udt As New UserDefinedClass
Dim myArray()
myArray(1) = udt
myClass.Method1(myArray)
myClass.Method2(myArray)

我们需要更多的信息。您能否添加该类型的VBA定义以及显示您调用COM接口的一些代码? - JaredPar
你的数组声明正在声明一个变量数组 - 它应该声明一个你自定义的类的数组,例如 "Dim myArray(0 To 3) As UserDefinedClass"。 - Joe
我应该提到一下,我也尝试过同样的方法,但结果是“函数使用了VB不支持的自动化类型”。我本来以为问题出在C#中方法的定义上,但完全有可能问题出在VBA代码中。我对VB完全是新手。 - Freddie
1个回答

6

我记得你需要通过引用传递数组。

尝试声明您的方法为

public class MyClass  
{ 
    public void Method1([In] ref UserDefinedClass[] Parameters) { ... } 
    ...
} 

如果你不想在.NET客户端中使用ref参数来污染你的类,你可以定义一个ComVisible接口供COM客户端使用,并显式实现它,如下所示:

[ComVisible(true)]
public interface IMyClass  
{ 
    void Method1([In] ref UserDefinedClass[] Parameters) { ... } 
    ...
} 

public class MyClass : IMyClass
{
    void IMyClass.Method1(ref UserDefinedClass[] Parameters)
    {
        this.Method1(Parameters);
    }

    public Method1(UserDefinedClass[] Parameters)
    {
        ...
    }
}

**回复评论** 如果您想将集合暴露给VBA而不是数组,只需公开一个枚举器和任何其他您希望VBA代码能够调用的方法(例如Add、Remove、Insert、Clear等)。例如:

[ComVisible]
public interface IUserDefinedClassCollection
{
    IEnumerator GetEnumerator();

    int Count { get; };

    IUserDefinedClass this[int index] { get; }

    int Add(IUserDefinedClass item);

    // etc, other methods like Remove, Clear, ...
}

你可以像往常一样在 VBA 中使用它:

Dim objUserDefinedClasses As UserDefinedClassCollection
...
objUserDefinedClasses.Add objUserDefinedClass 
...
For nIndex = 0 To objUserDefinedClasses.Count

Next nIndex

我已经尝试过那个,但我还没有明确尝试添加'in'子句。我也会尝试一下这个。使用'ref UserDefinedClass[] foo'也导致了同样的错误,我很抱歉。 - Freddie
所以,您的意思是我不需要在“参数”参数上包含任何其他属性。我看到其他代码在这里使用MarshallAs,但正如我提到的那样,在我的情况下似乎不起作用。 - Freddie
所以,你的意思是... - 我知道你需要原始类型数组参数的引用。 [In] 属性影响 IDL 的生成,不是必需的。通常我会使用集合类型将用户定义的类传递给 VBA(public class MyUserDefinedClassCollection : Collection<UserDefinedClass>),所以我实际上还没有尝试过这个。 - Joe
一个集合类也可以。如何编写VBA代码将集合传递给C#? - Freddie
你不需要将它作为 ref 传递。例如:"void Method1(MyUserDefinedClassCollection collection);"。当然,集合类以及 MyUserDefinedClass 需要 ComVisible。 - Joe
我理解了集合的C#代码是什么样子,但VB的等效代码会是什么呢? - Freddie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接