VBA массив пользовательских объектов из C# DLL
Исходная информация:
Я строю систему SCADA, которая работает на VBA, и я ищу некоторые возможности C#. Я создаю библиотеку DLL в C# и получил базовые данные для обмена между 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'
РЕДАКТИРОВАТЬ: Вот где я застрял: http://puu.sh/hnPGe/472ff863d0.png_
Я безуспешно пытался разработать некоторые документы Microsoft.
Первоначальный гид, которым я следовал, был таким:
http://www.analystcave.com/excel-use-c-sharp-in-excel-vba/
Он заявляет следующее, однако я не совсем понимаю это.
Если вы используете массив в качестве аргумента, обязательно используйте опцию C# "ref", получаемую по ссылке, например, ref int[] ar
Я думаю, что это связано с "MarshalAs" или с тем, как я читаю данные в VBA.
1 ответ
Если вы используете массив в качестве аргумента, обязательно используйте опцию C# "ref", получаемую по ссылке, например, ref int[] ar
Это правда, но у вас нет методов, которые принимают аргумент массива, поэтому он не применим к вашей ситуации.
Вы пытались изменить подпись вашего метода:
public Log CreateLogBook()
на подпись, которая возвращает массив:
public Log[] CreateLogBook()