ABOUT Visual Basic Programmieren Programmierung Download Downloads Tips & Tricks Tipps & Tricks Know-How Praxis VB VBA Visual Basic for Applications VBS VBScript Scripting Windows ActiveX COM OLE API ComputerPC Microsoft Office Microsoft Office 97 Office 2000 Access Word Winword Excel Outlook Addins ASP Active Server Pages COMAddIns ActiveX-Controls OCX UserControl UserDocument Komponenten DLL EXE
Diese Seite wurde zuletzt aktualisiert am 21.03.2000

Diese Seite wurde zuletzt aktualisiert am 21.03.2000
Aktuell im ABOUT Visual Basic-MagazinGrundlagenwissen und TechnologienKnow How, Tipps und Tricks rund um Visual BasicAddIns für die Visual Basic-IDE und die VBA-IDEVBA-Programmierung in MS-Office und anderen AnwendungenScripting-Praxis für IE, Windows Scripting Host und das Scripting-ControlTools, Komponenten und Dienstleistungen des MarktesRessourcen für Programmierer (Bücher, Job-Börse)Dies&Das...

Themen und Stichwörter im ABOUT Visual Basic-Magazin
Code, Beispiele, Komponenten, Tools im Überblick, Shareware, Freeware
Ihre Service-Seite, Termine, Job-Börse
Melden Sie sich an, um in den vollen Genuss des ABOUT Visual Basic-Magazins zu kommen!
Informationen zur AVB-Web-Site, Kontakt und Impressum

Zurück...

Verschachtelte Schachteln

Zurück...

(-hg) mailto:hg_propertybag@aboutvb.de

Wie stopft man eigentlich ein Array oder eine Collection in ein PropertyBag-Objekt? Die Lösung zu dieser Fragestellung werden Sie auf jeden Fall brauchen, wenn ein UserControl oder eine serialisierbare Klasse (letzteres ab Visual Basic 6) Daten-Elemente in das PropertyBag-Objekt schreiben soll, deren Anzahl Sie nicht festlegen können (etwa Listen-Elemente wie bei einer ListBox) und die als Array oder als Collection vorliegen. Mit Ausnahme von Byte-Arrays können Sie nämlich weder Arrays noch Collections direkt in der WriteProperty-Methode des PropertyBag-Objekts wegschreiben lassen. Es hilft alles nichts - Sie müssen die betreffenden Elemente alle einzeln wegschreiben und umgekehrt wieder aus dem PropertyBag-Objekt auslesen.

Auf den ersten Blick mag die Aufgabe trivial erscheinen. Sie durchlaufen einfach der Reihe nach alle Elemente des Arrays oder der Collection und vergeben dafür einen einfachen numerischen Zusatzschlüssel, unter dem Sie das Element dann der WriteProperty-Methode übergeben:

Private Sub ..._WriteProperties(PropBag As PropertyBag)
  Dim l As Long

  With PropBag
    For l = LBound(MeinArray) To UBound(MeinArray)
      .WriteProperty "Test" & l, MeinArray(l)
    Next ' l
  End With
End Sub

Das Auslesen sollte dann folgendermaßen erfolgen können:

Private Sub ..._ReadProperties(PropBag As PropertyBag)
  Dim l As Long

  With PropBag
    For l = ... ??????????????

Ja, wie viele Elemente sollen nun wieder ausgelesen werden? Okay, sorgen wir also schon beim Wegschreiben dafür, dass die Anzahl der Elemente später wieder ermittelt werden kann. Und ehe wir erneut ins Stolpern geraten, schreiben wir besser Unter- und Obergrenze des Arrays weg:

Private Sub ..._WriteProperties(PropBag As PropertyBag)
  Dim l As Long

  With PropBag
    .WriteProperty "TestLBound", LBound(MeinArray), 0
    .WriteProperty "TestUBound", UBound(MeinArray), 0
    For l = LBound(MeinArray) To UBound(MeinArray)
      .WriteProperty "Test" & l, MeinArray(l)
    Next ' l
  End With
End Sub

Jetzt klappt das soweit mit dem Auslesen:

Private Sub ..._ReadProperties(PropBag As PropertyBag)
  Dim l As Long
  Dim nLBound As Long
  Dim nUBound As Long

  With PropBag
    nLBound = .ReadProperty("TestLBound", 0)
    nUbound = .ReadProperty("TestUBound", 0)
    ReDim MeinArray(nLBound To nUBound)
    For l = nLBound To nUBound
      MeinArray(l) = .ReadProperty("Test" & l)
    Next ' l
  End With
End Sub

Bei einer Collection brauchen Sie jedoch nur die Anzahl zu berücksichtigen - die Untergrenze einer Collection ist ja immer 1. Das Prinzip auf eine Collection zu übertragen, sollte eigentlich kein Problem für Sie darstellen, oder? Na gut, ich bin ja nicht so...

Private Sub ..._WriteProperties(PropBag As PropertyBag)
  Dim l As Long

  With PropBag
    .WriteProperty "TestCount", MeineCollection), 0
    For i = 1 To MeineCollection.Count
      .WriteProperty "Test" & l, MeineCollection(l)
    Next ' l
  End With
End Sub

Private Sub ..._ReadProperties(PropBag As PropertyBag)
  Dim l As Long
  Dim nCount As Long

  With PropBag
    nCount = .ReadProperty("TestCount", 0)
    Set MeineCollection = New Collection
    For l = 1 To nCount
      MeineCollection.Add .ReadProperty("Test" & l)
    Next ' l
  End With
End Sub

So weit, so gut, aber... hatte ich nicht geschrieben: "...auf den ersten Blick trivial..."? Nun, wenn Sie Arrays einfacher Datentypen oder Collections, die gleichfalls nur Elemente einfacher Datentypen enthalten, wegschreiben wollen, war es das tatsächlich schon.

Enthalten Ihre Arrays jedoch Objekte, dann müssen Sie beim Einlesen noch ein Set hinzufügen (beim Einlesen in eine Collection erübrigt sich dies ja):

  ' ...
    For l = nLBound To nUBound
      Set MeinArray(l) = .ReadProperty("Test" & l)
    Next ' l
  ' ...

Nun sind wir fertig, ja? Jawohl - wenn Sie es so eilig haben, das gleich auszuprobieren, dann nur zu! Aber schimpfen Sie bitte nicht auf mich, wenn das hier und da denn doch nicht so glatt über die Bühne geht. Etwa, weil Ihre Arrays sowohl Objekte als auch Elemente einfacher Datentypen enthalten. Oder weil womöglich die Elemente eines Arrays oder einer Collection selbst wieder Arrays oder Collections sind, die wiederum Arrays und/oder Collections enthalten können, die wiederum Arrays und/oder Collections enthalten können, die wiederum Arrays und/oder Coll...

Überredet - und Sie lesen noch weiter? Fein, dann befassen wir uns zunächst mit dem ersten Punkt meiner Befürchtungen, dem Mix aus Objekten und anderen Elementen. Diesen Punkt abzuhaken ist auch noch recht trivial - das Problem tritt ja auch nur beim Einlesen von Arrays auf:

Private Sub ..._ReadProperties(PropBag As PropertyBag)
  Dim l As Long
  Dim nLBound As Long
  Dim nUBound As Long

  With PropBag
    nLBound = .ReadProperty("TestLBound", 0)
    nUbound = .ReadProperty("TestUBound", 0)
    ReDim MeinArray(nLBound To nUBound)
    On Error Resume Next
    For l = nLBound To nUBound
      Set MeinArray(l) = .ReadProperty("Test" & l)
      If Err.Number Then
        MeinArray(l) = .ReadProperty("Test" & l)
        Err.Clear
      End If
    Next ' l
  End With
End Sub

Richtig kompliziert wird es allerdings, wenn Sie absolut keine Ahnung haben, was auf das PropertyBag-Objekt zukommen kann: ein bunter Mix von einfachen Datentypen, Objekten, Arrays und Collections, verschachtelt bis in unbekannte Tiefen...

Zur Bearbeitung von solchen Verschachtelungen eignet sich am besten eine so genannte "Rekursion". Das bedeutet hier, dass sich eine Prozedur nur genau eine Ebene vornimmt und zur Bearbeitung der nächsttieferliegenden Ebene eine weitere Prozedur aufruft - und zwar erneut sich selbst.

Das grundsätzliche Problem einer solchen Rekursion ist, dass sie wissen muss, wann das Weitergeben nach unten ein Ende haben soll. Anderenfalls könnte sich eine rekursive Prozedur immer weiter selbst aufrufen, bis in alle Ewigkeit... oder bis der Speicher alle ist. Bei der Bearbeitung unserer Arrays und Collections brauchen wir das jedoch nicht zu fürchten, da ein Array definitiv eine Obergrenze hat und eine Collection auch nur eine feststellbare Anzahl an Elementen enthalten kann.

Als "Hülle" für die Rekursion dienen uns die beiden folgenden öffentlichen Prozeduren in einem Standard-Modul:

Public Sub WritePropertiesEx(Item As Variant, Key As String, _
 PropBag As PropertyBag)

  zWriteItem Key, Item, PropBag
End Sub

Public Sub ReadPropertiesEx(Item As Variant, Key As String, _
 PropBag As PropertyBag, Optional IsObj As Boolean)

  zReadItem Item, Key, PropBag, IsObj
End Sub

Sie übergeben in beiden Fällen die wegzuschreibende Variable, den gewünschten Schlüsselnamen und das vorhandene PropertyBag-Objekt. Der Prozedur ReadPropertiesEx übergeben Sie zusätzlich noch den Bool'schen Parameter IsObj. Ist der Wert dieses Parameters nach der Bearbeitung der Prozedur gleich True, wissen Sie, dass Ihnen im Parameter Item ein Objekt zurückgegeben wird und Sie bei einer eventuellen weiteren Verwendung die Zuweisung mit Set vornehmen müssen.

Private Sub ..._WriteProperties(PropBag As PropertyBag)
  ' ...
  WritePropertiesEx MeineVariable, "Test", PropBag
  ' ...
End Sub

Private Sub ..._ReadProperties(PropBag As PropertyBag)
  Dim nIsObject As Boolean

  ' ...
  ReadPropertiesEx MeineVariable, "Test", PropBag
  ' ...
End Sub

Die beiden Prozeduren rufen nun jeweils das erste (und einzige) Mal die jeweils zugehörige rekursive Prozedur auf, also zWriteItem bzw. zReadItem. Schauen wir uns zunächst die Schreib-Prozedur an.

Private Sub zWriteItem(Key As String, Item As Variant, _
 PropBag As PropertyBag)

  Dim l As Long
  Dim nBytes() As Byte

Zuerst wird geprüft, ob im Parameter Item ein Objekt übergeben worden ist und ob es sich dabei um eine Collection oder um irgend ein beliebiges Objekt handelt.

  With PropBag
    If IsObject(Item) Then
      If TypeOf Item Is Collection Then

Im Falle einer Collection wird dann zunächst eine spezielle Kennung in das PropertyBag-Objekt geschrieben, damit sich das spätere Auslesen vereinfacht und eindeutiger handzuhaben sein wird.

        .WriteProperty Key & "VarType", vbCollection, vbVariant

Da wir auch noch andere Kennungen benötigen, die einen Variablentyp kennzeichnen, und wir dabei die Visual Basic-Datentyp-Konstanten verwenden werden, erweitern wir die Reihe der Konstanten. Welchen Wert wir dafür wählen, wäre eigentlich egal - er dürfte nur nicht mit den VB-eigenen Variablentyp-Konstanten kollidieren. Zwar ist die VB-Reihe nach oben hin offen, aber wer weiß, ob da nicht irgendwann noch Werte hinzukommen werden. Sicherer ist es dagegen, wenn wir die Reihe in negativer Richtung erweitern. Wir definieren die Konstante im Deklarationsteil des Moduls:

Private Const vbCollection = -1

Zur weiteren Bearbeitung der Collection dient die spezielle Prozedur CollWriteProperties, die Sie als öffentliche Prozedur sogar direkt verwenden können, wenn Sie sicher sein können, dass das Ausgangselement eine Collection ist.

        CollWriteProperties CColl(Item), Key & "_", PropBag

Da der Parameter der Prozedur für die Übergabe der Collection als Datentyp Collection deklariert ist, stoßen wir hier auf eine kleine Meuterei des Kompilers. Er verweigert die direkte Annahme des als Variant übergebenen Collection-Objekts. Wie im Artikel Schnittstellen "chamäleonieren"Schnittstellen "chamäleonieren" gezeigt, behelfen wir uns mit einer selbstgebauten Konvertierung:

Private Function CColl(Collection As Variant) As Collection
  Set CColl = Collection
End Function

Kümmern wir uns zunächst einmal nicht um die Bearbeitung der Collection, sondern verfolgen wir das weitere Geschehen, falls das Item-Element keine Collection ist. Die nächste Möglichkeit, die wir hier berücksichtigen, wäre ein woher auch immer stammendes weiteres PropertyBag-Objekt. Dieses lässt sich nämlich auch nicht in ein anderes PropertyBag-Objekt schreiben. Der Umgang damit ist jedoch einfach. Denn es bietet seinen Inhalt als Byte-Array in der Eigenschaft Contents an. Wie bereits zu Anfang des Artikels erwähnt, kann ein Byte-Array problemlos weggeschrieben werden (weiß der Henker, warum das ausnahmsweise funktioniert). Zur Kennzeichnung definieren wir eine weitere eigene Variablentyp-Konstante (wieder im Deklarationsteil des Moduls)

Private Const vbPropertyBag = -2

und schreiben das Byte-Array weg:

      ElseIf TypeOf Item Is PropertyBag Then
        .WriteProperty Key & "VarType", vbPropertyBag, vbVariant
        nBytes = Item.Contents
        .WriteProperty Key, nBytes

Ist nun das Item-Element ein beliebiges anderes Objekt, könnte es an sich, wie Sie es gewohnt sind, direkt in das PropertyBag-Objekt geschrieben werden. Allerdings haben wir es hier erneut mit einer Sabotage des Kompilers zu tun, diesmal mit einer uns stillschweigend und verdeckt untergejubelten Feinheit. Stammt nämlich das hier ja im Parameter als Variant übergebene Item-Element von einer Picture-Eigenschaft eines Steuerelemets ab, wird nicht etwa das Picture-Objekt weggeschrieben, sondern nur der Long-Wert des Bitmap-Handles (siehe auch: "Wenn Nichts nicht Nichts ist..."). Vermutlich liegt das an schier verzweifelten erscheinenden Bemühungen der VB-Entwickler-Crew, die Kompatibilität zur Picture-Eigenschaft der Steuerelemente aus den 16-bittigen VB 3-Zeiten zu wahren - damals enthielt diese nämlich lediglich das Bitmap-Handle, und zum Objekt wurde sie erst ab VB 4.

Wir behelfen uns wieder mit einer expliziten Typ-Konvertierung. Vorsorglich belassen wir diese "Explizitität" bei der allgemeinen Konvertierung in ein Objekt (es könnte ja sein, dass uns irgend jemand irgendwann noch andere "spinnerte" Objekte unterzujubeln versucht). Das reicht offensichtlich für jeden Objekt-Typ aus, und eine eigene Konvertierung in ein Objekt des Typs StdPicture erübrigt sich somit glücklicherweise.

Private Function CObj(Obj As Variant) As Object
  Set CObj = Obj
End Function

Nun können wir also weiter schreiben:

      Else
        On Error Resume Next
        .WriteProperty Key, CObj(Item), Nothing

Doch für alle Fälle gehen wir noch einmal auf Nummer sicher. Falls sich ein Objekt um keinen Preis serialisieren lassen will, sind wir diejenigen, die nachgeben (schließlich sind wir ja klüger als so ein Objekt...) und schreiben statt dessen nur Nothing in das PropertyBag. Damit wahren wir wenigstens die Konsistenz der Anzahl der weggeschriebenen Objekte und überlassen es dem die ganze Geschichte wieder einlesenden Code (den Sie ja schreiben müssen, und nicht ich...), sich über das Nothing zu wundern und entsprechend zu reagieren.

        If Err.Number Then
          .WriteProperty Key, Nothing, Nothing
          Err.Clear
        End If
      End If

Nun sind wir endlich soweit, uns um Arrays kümmern zu können.

    ElseIf IsArray(Item) Then
      .WriteProperty Key & "LBound", LBound(Item), 0
      .WriteProperty Key & "UBound", UBound(Item), 0

Ordentlich, wie wir nun mal sind, schreiben wir auch den Variablentyp des Arrays in das PropertyBag-Objekt. Denn dann können wir später auch wieder Arrays des korrekten, ursprünglichen Datentyps zurückerhalten.

            .WriteProperty Key & "VarType", VarType(Item), vbVariant

Nun wie gehabt die Schreibaktion der Array-Elemente in der bekannten Schleife:

      For l = LBound(Item) To UBound(Item)
        zWriteItem Key & l, Item(l), PropBag
      Next 'l

Doch nicht ganz wie gehabt? Richtig, hier kommt die Rekursion ins Spiel. Wir übergeben das jeweilige Array-Element einem erneuten Aufruf der Prozedur zWriteItem (in deren erstem Aufruf wir uns ja bei dieser Betrachtung nach wie vor befinden) und überlassen es wiederum dieser, das Element zu prüfen und gegebenenfalls weiter zu zerpflücken. Ein gutgemeinter Rat: Lesen Sie erst einmal weiter, ehe Sie den Aufruf der Rekursion weiter verfolgen wollen und dazu erneut zum Anfang der Beschreibung dieser Prozedur zurückhüpfen. Die Rekursion lässt sich besser "live" im Einzelschrit-Modus verfolgen (etwa im Beispiel-Projekt zu diesem Artikel).

Hatte keine der Prüfungen bis hier hin Erfolg, sollten wir schließlich annehmen können, dass es sich um ein Item-Element eines einfachen Datentyps handelt.

    Else
      Select Case VarType(Item)
        Case vbBoolean
          .WriteProperty Key, CBool(Item)
        Case vbCurrency
          .WriteProperty Key, CCur(Item)
        Case vbDate
          .WriteProperty Key, CDate(Item)
        Case vbDouble
          .WriteProperty Key, CDbl(Item)
        Case vbInteger
          .WriteProperty Key, CInt(Item)
        Case vbLong
          .WriteProperty Key, CLng(Item)
        Case vbSingle
          .WriteProperty Key, CSng(Item)
        Case vbString
          .WriteProperty Key, CStr(Item)
        Case vbVariant
          .WriteProperty Key, Item
        Case Else
          .WriteProperty Key, vbEmpty
      End Select
    End If

Je nach Variablentyp des Variant-Item-Elements überführen wir dieses mit den Cxxx-VB-Funktionen in den entsprechenden Datentyp. Das ist reine PropertyBag-Routine. Für den Fall der Fälle, dass kein Datentyp passen sollte, ja noch nicht einmal ein Variant erkannt und akzeptiert wird, schreiben wir zur Konsistenzwahrung ein vbEmpty in das PropertyBag-Objekt. Und damit können wir jetzt die Prozedur abschließen:

  End With
End Sub

Kommen wir nun zur Prozedur CollWriteProperties, die sich speziell um das Wegschreiben einer Collection kümmert. Diese gleicht wieder der oben bereits beschriebenen einfachen Routinebehandlung einer Collection. Der Unterschied liegt lediglich darin, dass auch hier der Variablentyp zusätzlich weggeschrieben wird, und dass zur Bearbeitung der einzelnen Elemente die gerade beschriebene rekursive Prozedur zWriteItem verwendet wird.

Public Sub CollWriteProperties(Coll As Collection, _
 Key As String, PropBag As PropertyBag)

  Dim l As Long
  
  With PropBag
    .WriteProperty Key & "VarType", vbCollection, vbVariant
    .WriteProperty Key & "Count", Coll.Count, 0
    If Coll.Count Then
      On Error Resume Next
      For l = 1 To Coll.Count
        zWriteItem Key & l, Coll(l), PropBag
      Next 'l
    End If
  End With
End Sub

Den Rückwärtsgang des PropertyBag-Objekts legen wir mit der ebenfalls rekursiv verwendeten Prozedur zReadItem ein.

Private Sub zReadItem(Item As Variant, Key As String, _
 PropBag As PropertyBag, IsObj As Boolean)

  Dim nItem As Variant
  Dim nVarType As Long
  Dim l As Long
  Dim nLBound As Long
  Dim nUBound As Long
  Dim nIsObject As Boolean
  Dim nArray As Variant
  Dim nBytes() As Byte

Wie bereits erwähnt, verfügt sie über den weiteren Parameter IsObj, der die höherliegende Ebene darüber informiert, dass das in Item zurückgebebene, ausgelesene Element ein Objekt ist. Damit beim rekursiven Aufruf nichts schief geht, wird zuallererst der Wert des Parameters vorsorglich auf False gesetzt.

  IsObj = False

Dann versuchen wir anhand des übergebenen Schlüssels den möglichen Vaiablentyp des Item-Elements auszulesen.

  With PropBag
    On Error Resume Next
    nVarType = .ReadProperty(Key & "VarType", vbVariant)
    If Err.Number Then
      nVarType = vbVariant
      Err.Clear
    End If
    On Error GoTo 0

Sollte der Variablentyp nicht gelesen werden können (wir haben ja für einfache Elemente keinen weggeschrieben), nehmen wir einen Variant-Datentyp an. Eine weitere Differenzierung ist gar nicht notwendig, da wir ja nur ein Variant-Item im Parameter zurückgeben können.

Werten wir nun den Variablentyp aus und kümmern wir uns als erstes um Collections.

    Select Case nVarType
      Case vbCollection
        Set Item = CollReadProperties(Key & "_", PropBag)
        IsObj = True
        Exit Sub

Auch hier haben wir wieder eine spezialisierte Prozedur zur Hand, diesmal eine Funktion, die die komplett eingelesene Collection zurückgibt. Wir setzen den Parameter IsObj gleich True und können die rekursive Prozedur-Ebene an dieser Stelle bereits verlassen.

      Case vbPropertyBag
        nBytes = .ReadProperty(Key)
        Set Item = New PropertyBag
        Item.Contents = nBytes
        IsObj = True
        Exit Sub

Ähnlich kurz geht das Einlesen eines PropertyBag-Objekts vonstatten. Wir wissen, dass wir ein Byte-Array einlesen können, weisen dem Item-Element eine neu angelegte PropertyBag-Instanz zu, und füllen dessen Inhalt mit dem Byte-Array. IsObj wird wieder gleich True gesetzt und die Prozedur kann verlassen werden.

      Case Else
        If Not ((nVarType And vbArray) = vbArray) Then

Nun prüfen wir, ob wir es mit einem Array zu tun haben könnten. Ist das nicht der Fall, bemühen wir uns (wie bereits bei den einfachen Einlese-Routinen oben gezeigt), ein einfaches Item-Element auszulesen. Wir versuchen zuerst ein Objekt auszulesen und vergessen im Erfolgsfalle nicht, IsObj auf True zu setzen. Geht dieser Leseversuch schief, lesen wir eben ein gewöhnliches Element ein. In jedem dieser beiden Fälle verlassen wir danach die Prozedur.

          On Error Resume Next
          Set Item = .ReadProperty(Key)
          If Err.Number = 0 Then
            IsObj = True
          Else
            Item = .ReadProperty(Key, vbEmpty)
          End If
          Exit Sub
        End If
    End Select

Haben wir es letztlich mit einem Array zu tun, lesen wir zunächst die Informationen über das Array aus.

    nLBound = .ReadProperty(Key & "LBound", 0)
    nUBound = .ReadProperty(Key & "UBound", 0)

Anhand des Variablentyps entscheiden wir nun den Datentyp, für den das Array dimensioniert werden soll. Da eine alternative Dimensionierung innerhalb einer Prozedur nicht möglich ist, lagern wir diese in kleine Hilfsfunktionen aus, die jeweils ein Array des gewünschten Typs zurückgeben und zugleich die Grenzen festlegen:

    Select Case nVarType
      Case vbArray Or vbVariant
        nArray = zDimArrayVariant(nLBound, nUBound)
      Case vbArray Or vbString
        nArray = zDimArrayString(nLBound, nUBound)
      Case vbArray Or vbBoolean
        nArray = zDimArrayBoolean(nLBound, nUBound)
      Case vbArray Or vbInteger
        nArray = zDimArrayInteger(nLBound, nUBound)
      Case vbArray Or vbLong
        nArray = zDimArrayLong(nLBound, nUBound)
      Case vbArray Or vbSingle
        nArray = zDimArraySingle(nLBound, nUBound)
      Case vbArray Or vbDouble
        nArray = zDimArrayDouble(nLBound, nUBound)
      Case vbArray Or vbCurrency
        nArray = zDimArrayCurrency(nLBound, nUBound)
      Case vbArray Or vbDate
        nArray = zDimArrayDate(nLBound, nUBound)
      Case vbArray Or vbObject
        nArray = zDimArrayObject(nLBound, nUBound)
    End Select

Als Beispiel für diese Funktionen zur Dimensionierung mag hier die String-Variante reichen (im Modul zum Herunterladen sind natürlich alle Varianten enthalten). Die Funktionen sind alle gleich und ohne individuelle Besonderheiten aufgebaut:

Private Function zDimArrayString(ByVal LB As Long, _
 ByVal UB As Long) As String()

  Dim nArray() As String
  
  ReDim nArray(LB To UB)
  zDimArrayString = nArray
End Function

Nun marschieren wir durch die Anzahl der Elemente des Arrays. Auch hier wieder kümmert sich ein rekursiver Aufruf der Prozedur zReadItem um die einzelnen Elemente. Und je nach dem, was die Objekt-Anzeige (für diese Ebene heißt sie lokal nIsObject) anzeigt, wird das von der unteren Ebene zurückgegebene Item-Element dem jeweiligen Array-Element mit oder ohne Set-Anweisung zugewiesen.

    For l = nLBound To nUBound
      zReadItem nItem, Key & l, PropBag, nIsObject
      If nIsObject Then
        Set nArray(l) = nItem
      Else
        nArray(l) = nItem
      End If
    Next 'l
  End With

Als letztes weisen wir nun noch das Array dem Item-Element zur Rückgabe an die höhergelegene Ebene zu und beenden die Prozedur.

  Item = nArray
End Sub

Auch die spezialisierte Funktion CollReadProperties ist wieder nach dem bekannten Schema ausgeführt und greift ebenfalls auf den rekursiven Aufruf von zReadItem zurück.

Public Function CollReadProperties(Key As String, _
 PropBag As PropertyBag) As Collection

  Dim nCount As Long
  Dim l As Long
  Dim nColl As Collection
  Dim nItem As Variant
  Dim nVarType As Long
  Dim nIsObject As Boolean
  
  With PropBag
    Set nColl = New Collection
    On Error Resume Next
    nVarType = .ReadProperty(Key & "VarType", vbVariant)
    On Error GoTo 0
    If nVarType = vbCollection Then
      nCount = .ReadProperty(Key & "Count", 0)
      If nCount Then
        With nColl
          For l = 1 To nCount
            zReadItem nItem, Key & l, PropBag, nIsObject
            .Add nItem
          Next 'l
        End With
      End If
    End If
  End With
  Set CollReadProperties = nColl
End Function

Damit wären wir am Ende der verschachtelten "Eigenschaften-Schachtel" (PropertyBag mal etwas frei übersetzt...) angekommen. Sollten Sie immer noch etwas ungläubig staunen, beweist Ihnen das Beispiel-Projekt zum Herunterladen, dass die Sache funktionert. Marschieren Sie ruhig einmal im Einzelschritt-Modus durch das Beispiel und verfolgen Sie die rekursiven Aufrufe von zWriteItem und zReadItem.


Modul und Beispiel-Projekt PropertyBag (propertybag.zip - ca. 5 KB)



Komponenten-Übersicht

Schnellsuche



Zum Seitenanfang

Copyright © 1999 - 2023 Harald M. Genauck, ip-pro gmbh  /  Impressum

Zum Seitenanfang

Zurück...

Zurück...