2015-04-17 8 views
5

Hintergrundinformationen:
Ich baue ein SCADA-System, das auf VBA läuft und ich suche einige der Kräfte von C#. Ich baue eine DLL-Bibliothek in C# und bekam grundlegende Daten zwischen der DLL und VBA fließen.VBA Array von benutzerdefinierten Objekten aus einer C# DLL

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

} 

Und ich kehrte die Klasse wie folgt:

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

Meine Datenschicht:

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

Die statische Methode VBA ruft:

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

In VBA i habe die Daten so:

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 

Nun zu meiner Frage:
Wie kehre ich eine Array oder Liste der Klasse 'BE_Log'
EDIT:Dies ist, wo ich bin stecken: http://puu.sh/hnPGe/472ff863d0.png

Ich habe versucht, einige von Microsofts Dokumentationen ohne viel Glück zu erarbeiten.

Die orginal Guide i folgte, war diese:
http://www.analystcave.com/excel-use-c-sharp-in-excel-vba/

er folgendes besagt jedoch nicht, verstehe ich es völlig.

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

Ich denke, es ist etwas mit ‚MarshalAs‘ oder der Art, wie ich die Daten in VBA

Antwort

1

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

Das ist wahr, aber Sie haben noch keine Methoden gelesen zu tun, die ein Array Argument Es trifft also nicht auf deine Situation zu.

Haben Sie Ihre Methodensignatur versucht zu ändern:

public Log CreateLogBook() 

einer Signatur, die ein Array zurückgibt:

public Log[] CreateLogBook() 
+0

ich mit einer Reihe sowohl versuchte und eine Liste 'öffentlichen Log [] CreateLogBook() ' ' öffentliche Liste CreateLogBook() ' –

+0

" Ich habe es versucht ... "- und was war das Ergebnis? – Joe

+0

Ich kann VBA nicht bekommen, um die Daten zu lesen, oder vielleicht habe ich nicht den "Marshal" richtig gemacht? Können Sie ein Beispiel für das Lesen eines Arrays in VBA aus einer DLL bereitstellen? –