c# - 来自 C# DLL 的用户定义对象的 VBA 数组

标签 c# vba marshalling interopservices

背景资料:
我正在构建一个在 VBA 上运行的 SCADA 系统,我寻求 C# 的一些功能。我在 C# 中构建了一个 DLL 库,并获得了在 DLL 和 VBA 之间流动的基本数据。

[ComVisible(true), ClassInterface(ClassInterfaceType.AutoDual)]
public class BE_Log
{
    public string DateTime
    {
        [return: MarshalAs(UnmanagedType.BStr)]
        get;
        [param: MarshalAs(UnmanagedType.BStr)]
        set;
    }
    public string User
    {
        [return: MarshalAs(UnmanagedType.BStr)]
        get;
        [param: MarshalAs(UnmanagedType.BStr)]
        set;
    }
    public string SCADA
    {
        [return: MarshalAs(UnmanagedType.BStr)]
        get;
        [param: MarshalAs(UnmanagedType.BStr)]
        set;
    }
    public string Tag
    {
        [return: MarshalAs(UnmanagedType.BStr)]
        get;
        [param: MarshalAs(UnmanagedType.BStr)]
        set;
    }
    public string Area1
    {
        [return: MarshalAs(UnmanagedType.BStr)]
        get;
        [param: MarshalAs(UnmanagedType.BStr)]
        set;
    }
    public string Area2
    {
        [return: MarshalAs(UnmanagedType.BStr)]
        get;
        [param: MarshalAs(UnmanagedType.BStr)]
        set;
    }
    public string Description
    {
        [return: MarshalAs(UnmanagedType.BStr)]
        get;
        [param: MarshalAs(UnmanagedType.BStr)]
        set;
    }
    public string ValueOld
    {
        [return: MarshalAs(UnmanagedType.BStr)]
        get;
        [param: MarshalAs(UnmanagedType.BStr)]
        set;
    }
    public string ValueNew
    {
        [return: MarshalAs(UnmanagedType.BStr)]
        get;
        [param: MarshalAs(UnmanagedType.BStr)]
        set;
    }

    public BE_Log(string DataTime, string User, string SCADA, string Tag, string Area1, string Area2,string Description)
    {
        this.DateTime = DateTime;
        this.User = User;
        this.SCADA = SCADA;
        this.Tag = Tag;
        this.Area1 = Area1;
        this.Area2 = Area2;
        this.Description = Description;
    }

    public BE_Log(string DataTime, string User, string SCADA, string Tag, string Area1, string Area2, string Description, string ValueOld, string ValueNew)
    {
        this.DateTime = DateTime;
        this.User = User;
        this.SCADA = SCADA;
        this.Tag = Tag;
        this.Area1 = Area1;
        this.Area2 = Area2;
        this.Description = Description;
        this.ValueOld = ValueOld;
        this.ValueNew = ValueNew;
    }

}

然后我像这样返回了类:

[ComVisible(true), ClassInterface(ClassInterfaceType.AutoDual)]
public class TI
{
    private BLL_LogBook bll;

    public TI()
    {
        bll = new BLL_LogBook();
    }

    [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType=VarEnum.VT_USERDEFINED)]  //  SafeArrayUserDefinedSubType = typeof(BE_Log)
    public BE_Log[] CreateLogBook()
    {
        List<BE_Log> logs = bll.GetLogEntry();
        return logs.ToArray();
    }
}

我的数据层:

public class BLL_LogBook
{
    public List<BE_Log> GetLogEntry()
    {
        List<BE_Log> logs = new List<BE_Log>();
        logs.Add(new BE_Log("05-05-2015", "some user", "scada01", "LA010NDA10CU12XQ12", "Ribe", "Esbjerg", "Some short description"));
        logs.Add(new BE_Log("06-05-2015", "test user", "scada01", "LA010NDA10CU12XB05", "Herning", "KBH", "Some long description"));
        logs.Add(new BE_Log("07-05-2015", "normal user", "scada02", "LA010NDA10CU12YQ01", "Åhus", "Tønder", "Some test description"));

        return logs;
    }
}

VBA 正在调用的静态方法:

static class UnmanagedExports
{
    [DllExport]
    [return: MarshalAs(UnmanagedType.IDispatch)]
    static Object TI_Object()
    {
        return new TI();
    }
}

在 VBA 中,我以这种方式获取数据:

Declare Function TI_Object Lib "<path>\\TJI.dll" () As Object

Sub TestTheTestClass()
    Dim TJI As Object
    Set TJI = TI_Object()

    Dim test As Variant
    test = TJI.CreateLogBook()

    Dim log As Variant
    Set log = test(0)

    Debug.Print log.User
End Sub

现在回答我的问题:
如何返回“BE_Log”类的ArrayList
编辑: 这是我卡住的地方:http://puu.sh/hnPGe/472ff863d0.png

我一直在尝试整理一些 Microsoft 的文档,但运气不佳。

我遵循的原始指南是这个:
http://www.analystcave.com/excel-use-c-sharp-in-excel-vba/

他说了以下内容,但我并不完全理解。

If you are using an array as an argument be sure to use the C# “ref” get by reference option e.g. ref int[] ar

我认为这与“MarshalAs”或我在 VBA 中读取数据的方式有关

最佳答案

If you are using an array as an argument be sure to use the C# “ref” get by reference option e.g. ref int[] ar

这是对的,但是您没有任何采用数组参数的方法,因此它不适用于您的情况。

您是否尝试过更改您的方法签名:

public Log CreateLogBook()

返回数组的签名:

public Log[] CreateLogBook()

关于c# - 来自 C# DLL 的用户定义对象的 VBA 数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29695123/

相关文章:

c# - 从 C++ 接收一个 char* 到 C#,然后再传回

namespaces - 在 JAXB 编码时删除命名空间前缀

c - C 中的别名模块方法(Ruby 扩展)

c# - 从 ViewModel 调用异步方法

c# - 如何在没有用户提示的情况下添加到日历 UWP C#

c# - IDX10500 : Signature validation failed. 无法解析 SecurityKeyIdentifier

c# - 创建供 Excel 和 C# 使用的 C++ .dll(32/64 位窗口)

vba - VBA 有没有办法了解未使用的变量?

VBA复制行范围

C# 编码非托管指针返回类型