简体   繁体   English

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

[英]VBA array of User-Defined objects from a C# DLL

Background information: 背景资料:
I'm building a SCADA system, which runs on VBA and I seek some of the powers of C#. 我正在构建一个SCADA系统,它运行在VBA上,我寻求C#的一些功能。 I build a DLL library in C# and got basic data to flow between the DLL and VBA. 我在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;
    }

}

And I returned the class like this: 我这样回来了这堂课:

[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();
    }
}

My data layer: 我的数据层:

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;
    }
}

The static method VBA is calling: 静态方法VBA正在调用:

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

In VBA i got the data this way: 在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

Now to my question: 现在问我的问题:
How do I return an Array or List of the class 'BE_Log' 如何返回类'BE_Log'的数组列表
EDIT: This is where I'm stuck: http://puu.sh/hnPGe/472ff863d0.png 编辑: 这是我被困的地方: http//puu.sh/hnPGe/472ff863d0.png

I have been trying to work out some of Microsofts documentations, without much luck. 我一直试图找出一些微软的文件,没有太多运气。

The orginal guide i followed was this one: 我遵循的原始指南就是这个:
http://www.analystcave.com/excel-use-c-sharp-in-excel-vba/ http://www.analystcave.com/excel-use-c-sharp-in-excel-vba/

He states the following, however I dont completely understand it. 他陈述了以下内容,但我并不完全理解。

If you are using an array as an argument be sure to use the C# “ref” get by reference option eg ref int[] ar 如果您使用数组作为参数,请务必使用C#“ref”get by reference选项,例如ref int [] ar

I think it's something to do with 'MarshalAs' or the way I read the data in VBA 我认为这与“MarshalAs”或我在VBA中读取数据的方式有关

If you are using an array as an argument be sure to use the C# “ref” get by reference option eg ref int[] ar 如果您使用数组作为参数,请务必使用C#“ref”get by reference选项,例如ref int [] ar

This is true, but you don't have any methods that take an array argument, so it doesn't apply to your situation. 这是事实,但是您没有任何采用数组参数的方法,因此它不适用于您的情况。

Have you tried changing your method signature: 您是否尝试更改方法签名:

public Log CreateLogBook()

to a signature that returns an array: 到返回数组的签名:

public Log[] CreateLogBook()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用 C# 中的用户定义类型调用 VBA 宏? - Calling VBA-Macros with user-defined Types from C#? 带有用户定义的行数和列数的C#Jagged数组 - C# Jagged Array With User-Defined Number of Rows and Columns 记录用户定义的异常C# - Logging user-defined exception C# EF:将表值参数从 C# 传递给用户定义的函数 - EF: Passing a table valued parameter to a user-defined function from C# 如何从存储过程插入表(用户定义类型)并传递给C# - How insert into table(User-defined type) from Stored procedure and passing to c# 从C#将用户定义类型的值作为输入参数传递给Oracle中的存储过程 - Pass value of user-defined type as input parameter to stored procedure in Oracle from C# EF Core:从 C# 类创建 SQL 用户定义类型 - EF Core: Create a SQL user-defined type from a C# class 有没有办法从 C# 代码在 mongo 中调用用户定义的 function ? - Is there a way to call a user-defined function in mongo from C# code? C#中的可选参数 - 将用户定义的类默认为null - Optional Parameters in C# - Defaulting a user-defined Class to null 在C#MSSQL中创建用户定义的表名 - Create User-Defined Table Name in C# MSSQL
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM