Office Forum
www.Office-Loesung.de
Access :: Excel :: Outlook :: PowerPoint :: Word :: Office :: Wieder Online ---> provisorisches Office Forum <-
Datensammlung - Arrays und Collections
zurück: Prozesssteuerung über eine Tabelle weiter: Formular zur Auswahl der Kalenderwoche (dynamisch) Unbeantwortete Beiträge anzeigen
Neues Thema eröffnen   Neue Antwort erstellen     Status: Tutorial Facebook-Likes Diese Seite Freunden empfehlen
Zu Browser-Favoriten hinzufügen
Autor Nachricht
Bitsqueezer
Office-VBA-Programmierer


Verfasst am:
14. Dez 2010, 01:22
Rufname:

Datensammlung - Arrays und Collections - Datensammlung - Arrays und Collections

Nach oben
       Version: (keine Angabe möglich)

Wenn man mit Variablen arbeitet, hat man in VBA eine Reihe Möglichkeiten, Variablen zu speichern - zum Beispiel modulglobal, applikationsglobal, lokal, statisch usw.
Aber oft braucht man auch eine Reihe von Werten als Liste, für die es mehr als umständlich wäre, je eine eigene Variable zu definieren.

Schon seit (mindestens) C64-Zeiten bietet Basic dafür die Arrays an. Sozusagen eine durchnumerierte Variablenliste mit einem einzigen Variablennamen.

Für den Anfang also benötigt man nur den Variablennamen, die benötigte Menge und den Variablentypen.
Code:
Public Sub Demo1_Array()
    Dim i As Long
    Dim x(8) As String
   
    x(0) = "Dies"
    x(1) = "ist"
    x(2) = "ein"
    x(3) = "Beispiel"
    x(4) = "für"
    x(5) = "ein"
    x(6) = "sehr"
    x(7) = "simples"
    x(8) = "Array"
    For i = 0 To 8
        Debug.Print x(i) & " ";
    Next i
End Sub
Der Variablenname ist "x", die Menge ist "8" und der Typ ist "String". Eigentlich ist die Menge 9, denn in Basic fangen Arrays immer mit 0 an, solange man nichts anderes definiert. Man kann in VBA auch so definieren: "Dim x(1 To 8)", dann erhält man wirklich nur 8. Ebenso geht auch "Dim x(3 to 14)" - dann hat man die Indizes 3 bis 14. Alternativ gibt es auch noch die Möglichkeit, mit "Option Base 1" am Beginn eines Moduls alle Arrays immer mit 1 beginnen zu lassen - da das aber zum Beispiel nicht auf den Array-Befehl zutrifft, ist das eher verwirrend als hilfreich.

Der große Vorteil von Arrays ist, daß man auf jedes Element der Liste mit seiner jeweiligen Nummer (dem Index) zugreifen kann. Mit x(7) erhält man sofort den Wert "simples" in dem Beispiel oben. Schnell und effektiv. Arrays können sogar halbwegs flexibel gestaltet werden. Im Gegensatz zu den C64-Arrays können in VBA Arrays auch dynamisch definiert werden. So könnte man die Zeile, die das Array oben fest und unabänderlich mit 9 Elementen (0 bis 8) definiert, auch so definieren:
Code:
    Dim x() As String
    ReDim x(8)
Hierbei wird nur gesagt "ich brauche ein String-Array" und wieviele Elemente, steht dann im ReDim. Das wäre auch noch nicht so wirklich interessant, aber ReDim kann eben Dinge, die Dim nicht kann. So kann die Anzahl aus einer anderen Variable kommen, ebenso kann man mit dem Zusatz "Preserve" die bereits definierten Elemente eines Arrays beibehalten, wohingegen ein einfaches ReDim erst alle Elemente löscht. So kann man das gleiche Array für verschiedene Zwecke nutzen, und das Array kann beliebig kurz oder lang werden, ohne es eingangs festlegen zu müssen.

Für die meisten einfachen Aufgaben genügt das völlig. Wenn man damit leben kann, daß der Variablentyp des Arrays sofort definiert werden muß - im Zweifelsfall "Variant", was dann verschiedene Typen aufnehmen kann, aber auch eigene Sorgfalt beim Auslesen der Werte erfordert.

Ein weiterer Vorteil von Arrays ist, daß sie zwei- und mehrdimensional sein können. Sie können so ganze Tabellen aufnehmen oder mehrere Tabellen oder mehrere Datenbanken von Tabellen, mit jeder zusätzlicher Dimension eine Ebene weiter. Problem aber bleibt, daß Arrays nun einmal nur über ihre Indizes angesprochen werden können, also in welchem Element meines fünfdimensionalen Arrays war noch gleich die Variable, die ich suche...?

VBA bietet aber noch eine viel praktischere Methode, um Variablen zu sammeln, ein kleines, unscheinbares Objekt, dem man seine Möglichkeiten zu Beginn gar nicht ansieht, das aber zu den mächtigsten gehört: Die Collection.

Die Collection verhält sich wie ein Behälter: Man kann wirklich alles hineinkippen, und das beste ist, der Datentyp ist dabei völlig egal. Das Beispiel oben könnte man für eine Collection folgendermaßen umschreiben. Zunächst braucht es mal eine Collection-Variable:
Code:
    Dim colTest As Collection
Da fällt auf, daß es hier keine Klammern gibt, auch keine Mengendefinition wie im Array-Beispiel. Die Collection ist ein "Behälter", der immer nur genauso groß ist, daß alles reinpaßt. Sie kann 1, 10, 100 oder 1.000.000 Dinge aufnehmen, je nachdem, wieviel Hauptspeicher der Rechner hat. Dabei sind die Elemente in der Collection genauso einfach zugreifbar wie die Elemente eines Arrays: Einfach den Index des Elementes angeben, dann bekommt man das richtige Objekt wieder zurück. Das kann ein String sein, oder ein Long oder was auch immer.

Da eine Collection ein Klassenobjekt ist, genügt die Zeile oben noch nicht, um mit ihr zu arbeiten. Wie bei jeder anderen Klasse muß man aus der Klasse (der "Blaupause") erst ein Objekt erzeugen (das "fertige Produkt"). Das geht einfach mit "New":
Code:
    Set colTest = New Collection
Man sollte diese beiden Zeilen immer voneinander trennen, schon alleine, um die reine Deklaration von der Objekterstellung zu trennen. Man könnte ansonsten auch schreiben "Dim colTest As New Collection".

Da die Collection automatisch mit jedem Element "mitwächst", benötigt man kein umständliches ReDim (bei dem man immer noch auf das "Preserve" achten müßte und die neue Gesamtanzahl Indizes immer explizit angeben müßte), man schreibt einfach "Add":
Code:
    colTest.Add "MeinElement"
Damit ist der String "MeinElement" jetzt automatisch das erste Element in der Collection. Eine Collection beginnt im Gegensatz zum Array immer mit 1 und das kann auch nicht geändert werden. Indizes wie "2 To 14" sind also nicht möglich. Aber die Collection kann ja noch mehr. Sie kann nämlich jedem Element einen Key zuordnen (der allerdings ein String sein muß), und so könnte man dem Element "MeinElement" nun einen Key "2" zuordnen (wichtig: "2", nicht 2, also String). Auf diese Weise könnte man jedem Element also nun doch wieder die Indizes 2 bis 14 zuweisen, nur eben als String - dank der vielfachen Konvertierungsmöglichkeiten in VBA ist das ja kein Problem.

Jetzt kann das Array-Beispiel oben zum Beispiel so in eine Collection übertragen werden:
Code:
Public Sub Demo3_Collection()
    Dim i As Long
    Dim colTest As Collection
   
    Set colTest = New Collection
    colTest.Add "Dies", "0"
    colTest.Add "ist", "1"
    colTest.Add "ein", "2"
    colTest.Add "Beispiel", "3"
    colTest.Add "für", "4"
    colTest.Add "ein", "5"
    colTest.Add "sehr", "6"
    colTest.Add "simples", "7"
    colTest.Add "Array", "8"
    For i = 1 To 9
        Debug.Print colTest(i) & " ";
    Next i
    Debug.Print
    For i = 0 To 8
        Debug.Print colTest(CStr(i)) & " ";
    Next i
End Sub
Die beiden Schleifen unten zeigen zwei Möglichkeiten, die Elemente der Collection auszulesen. Dabei muß man bei der numerischen Methode mit 1 beginnen, also 1 to 9, bei der Methode Zugriff über den selbstdefinierten Schlüssel kann man wieder mit 0 to 8 arbeiten.

Moment...selbstdefiniert...String als Schlüssel - da kommt man doch auf die Idee, daß man seine Elemente einfach benennen könnte (in anderen Programmiersprachen auch "benannte Arrays" genannt). Da eine Collection ein Objekt ist, kann man auch "With" verwenden, um den Code übersichtlicher zu machen:
Code:
Public Sub Demo4_Collection()
    Dim i As Long
    Dim colTest As Collection
   
    Set colTest = New Collection
    With colTest
        .Add "Isaac", "Vorname"
        .Add "Asimov", "Nachname"
        .Add "München", "Ort"
        .Add "Teststraße", "Strasse"
        .Add "1a", "Hausnummer"
    End With
    For i = 1 To colTest.Count
        Debug.Print colTest(i) & " ";
    Next i
    Debug.Print
End Sub
Wie man hier sieht, hat man nun sozusagen eine Tabelle mit einem Datensatz: Jedes Element hat als Key den Feldnamen und als Wert den Feldinhalt. Wenn man also wissen möchte, wo Isaac wohnt, kann man einfach mit "colTest("Ort")" direkt auf das Element zugreifen - oder nach wie vor mit seinem Index 3 (weil als drittes hinzugefügt). Da es in jeder Collection die Eigenschaft "Count" gibt, kann man auch ganz simpel sehen, wieviel in unserem "Behälter" gerade drin ist, hervorragend für übersichtliche Schleifen geeignet, die sich einem gleich beim Lesen erschließen.

Die Collection kann aber noch viel mehr. Wenn die Hausnummer zum Beispiel immer numerisch sein soll, dann hätte man ebenso auch schreiben können:
Code:
        .Add 1,"Hausnummer"
Womit man sieht, daß die Collection wirklich alles schluckt, an beliebiger Position. Da "Add" aber auch noch die optionalen Parameter "Before" und "After" anbietet, kann man ein neues Element auch gezielt an einer bestimmten Position in der Collection einfügen - das macht aber nur Sinn, wenn man über den numerischen Index auf die Elemente zugreifen möchte, aber man kann so eine einfache Sortierung durchführen, indem man über den String-Key das Element bestimmt, bei dem eingefügt werden soll. Grundsätzlich gibt es dafür aber einfachere Methoden - einerseits ein Objekt "Dictionary", das man sich aus VBScript "ausleihen" kann (aber eben eine externe Refernzierung benötigt, während die Collection immer da ist) und eine Art erweiterte Collection mit Sortiermöglichkeit ist, andererseits kann man für solche Operationen besser eine Access-Tabelle verwenden, was dann auch performanter ist.
Die Collection soll ja auch nicht den Sinn einer Tabelle oder von SQL ersetzen, sondern viele neue Möglichkeiten auf der Programmierebene ermöglichen. In der Praxis ist daher "Before" und "After" eher nicht so bedeutend, aber vielleicht findet ja jemand sinnvolle Anwendungsmöglichkeiten.

Doch die Collection ist längst noch nicht am Ende. Ein Array kann mehrdimensional sein - aber das kann eine Collection auch. Bei einem mehrdimensionalen Array (mal 2 Dimensionen angenommen) hat man im Prinzip eine einfache Tabelle: Jedes Element kann durch Angabe von "Zeile" und "Spalte" wiedergefunden werden. Das kann man mit einer Collection ebenfalls! Wie? Ganz einfach: Da eine Collection, wie gesagt, ALLES aufnehmen kann, ist die Verwendung für primitive Datentypen wie String, Long, Double eigentlich eine Verschwendung ihrer Möglichkeiten. ALLES schließt eben auch eine Collection ein. Also kann eine Collection auch eine andere Collection aufnehmen und schon hat man die Entsprechung zu einem zweidimensionalen Array. In einem Array hat man z.B. 10 Elemente in der 1. Dimension, hier als "Zeile" der Tabelle angenommen und 5 Elemente in der 2. Dimension, als "Spalte". Damit gibt es 50 Elemente im Array.
In der Collection erstellt man eine Collection, die 5 Spaltenelemente enthält und legt dann davon 10 Collections an, die man nacheinander in die übergeordnete Collection einfügt - schon kann man mit "colTest(2)(3)" auf das 3. Element (die 3. "Spalte") der 2. Collection (der 2. "Zeile") zugreifen (bei einem Array wäre es "x(2,3)".
Code:
Public Sub Demo5_Collection()
    Dim i As Long
    Dim colTabelle As Collection
    Dim colZeile As Collection
   
    Set colTabelle = New Collection
    Set colZeile = New Collection
    With colZeile
        .Add "Isaac", "Vorname"
        .Add "Asimov", "Nachname"
        .Add "München", "Ort"
        .Add "Teststraße", "Strasse"
        .Add "1a", "Hausnummer"
    End With
    colTabelle.Add colZeile
    Set colZeile = New Collection
    With colZeile
        .Add "Robert A.", "Vorname"
        .Add "Heinlein", "Nachname"
        .Add "Berlin", "Ort"
        .Add "Testplatz", "Strasse"
        .Add 2, "Hausnummer"
    End With
    colTabelle.Add colZeile
    Debug.Print colTabelle(2)(3)
End Sub
Der Grund für diese "komische" Schreibweise ist, daß man mit der Angabe des ersten Indizes (2) die zweite Collection zurückerhält und mit der (3) gibt man dann das 3. Element dieser Collection an - das ist die Objektverkettung. So ergibt "colTabelle(2).Count" die Anzahl Elemente der 2. Collection colZeile. Die Anzahl Elemente in der ersten Collection bekommt man, wenn man "colTabelle.Count" schreibt. Außerdem wird man hier feststellen, daß man für die erste "Count"-Variante keine Hilfe von IntelliSense bekommt. Das liegt daran, daß die Collection eben alles schluckt und IntelliSense nicht weiß, um was für ein Objekt es sich bei der zweiten Collection handelt (könnte ja auch ein String oder was immer sein) und daher einfach gar nichts ausgibt.

Um ein in eine Collection eingefügtes Objekt wieder korrekt aus der Collection herauszuholen, muß man einfach eine passende Objektvariable definieren und das Element dieser zuweisen, also z.B. so:
Code:
    Dim colAuslesen As Collection
   
    Set colAuslesen = colTabelle(2)
    Debug.Print colAuslesen.Count    ' Und hier funktioniert auch wieder IntelliSense
Statt "colAuslesen" könnte man hier auch "colZeile" verwenden, denn das Objekt wird ja nur zum Befüllen der ersten Collection benötigt und danach verworfen.

Ein Zuweisen mit "New" ist hier auch nicht notwendig, denn man will ja keine neue Collection aufmachen (eine neue Instanz der Klasse Collection), sondern einfach nur das schon vorhandene Collection-Objekt wieder aus der übergeordneten Collection herausholen, damit man wieder ordentlich auf alle Elemente zugreifen kann.

Wenn man das Beispiel aber genau betrachtet, kann die Collection in Sachen "mehr Dimensionen" sogar noch mehr als ein Array: Während dieses immer 50 Elemente im Beispiel haben muß, wenn man es mit 5 und 10 dimensioniert, kann jede hinzugefügte Collection in der übergeordneten Collection ohne weiteres auch mehr oder weniger Elemente enthalten. Es wäre also kein Problem, daß Zeile 1 der "Tabelle" nur 3 Elemente, Zeile 2 dann 5 und Zeile 3 18 Elemente enthält. Für eine Collection kein Problem. Ebenso könnte Zeile 4 ein einfacher String sein, Zeile 5 ein Formularobjekt enthalten oder, oder, oder... der Aufbau kann beliebig komplex werden.

Ja, richtig gelesen - Formularobjekt. Da ein Formular auch wie ein Objekt instantiiert werden kann, kann man das erzeugte Formular ebenfalls einer Collection hinzufügen. So kann man ein und dasselbe Formular z.B. 20mal öffnen, und alle 20 Instanzen der Collection hinzufügen. Damit kann man gezielt jede der 20 Instanzen ansprechen - und da die Collection einen String als Key entgegennehmen kann, kann jedes Formular sogar einen eigenen Namen bekommen, wenn man will.

Will man die Formulare auf einen Schlag loswerden, killt man einfach die Collection - schon sind 20 Formulare zum Teufel und verschwinden vom Bildschirm. Das geht einfach mit "Set colTest = Nothing". Jedes Formular erledigt dabei noch alles, was notwendig ist, alle ausstehenden Events, etwa Form Unload.

Noch mehr Möglichkeiten? Kein Problem: Eine Collection kann natürlich auch Recordset-Objekte aufnehmen, so kann man eine Reihe geöffneter Recordsets der Collection hinzufügen und mit Namen versehen und direkt darauf zugreifen. Das Prinzip zum Herausholen funktioniert genauso wie bei dem Beispiel mit der Untercollection oben: Man erstellt für den einfacheren Zugriff eine Recordset-Objektvariable und weist die dem gewünschten Recordset-Objekt der Collection zu:
Code:
    Dim rs As DAO.Recordset
   
    Set rs = colRecordsets("MeinRecordsetname")
Außerdem gibt es noch eine spezielle "For-Next"-Schleife, die schneller ist als die übliche "For i = 1 to 100" Methode: For Each.
Damit kann man sagen "Für jedes Element meiner Collection führe die folgenden Befehle aus". Dabei entfällt das umständliche Zuweisen einer Objektvariablen mit Set wie in den beiden Beispielen oben, man muß nur wissen, welcher Objekttyp in der Collection ist und jedes Element der Collection muß in diesem Fall vom gleichen Typ sein.
Hätte man also eine Collection, die nur Recordset-Objekte enthält, könnte man diese z.B. so alle schließen:
Code:
    Dim rs As DAO.Recordset
   
    For Each rs in colRecordsets
        rs.Close
    Next rs
Eigentlich doch schön einfach und übersichtlich, oder?
In jedem Schleifendurchlauf wird damit automatisch die "Set"-Zeile oben ausgeführt, daher muß natürlich sichergestellt sein, daß die Collection für diese Art Schleife nur Recordset-Objekte enthält - sonst würde eine Fehlermeldung ausgegeben.
Ebenso muß man beim Zugriff auf Collection-Elemente beachten, daß es zu einem Error kommt, wenn man auf ein Element zugreift, das nicht in der Collection ist. Wenn man also nicht weiß, ob das gewünschte Element vorhanden ist, kann man einfach so abfangen:
Code:
    On Error Resume Next
    Set rs = colRecordsets("MeinRecordsetname")
    If Err.Number = 0 Then
        ' Alles OK, rs kann verwendet werden
      Else
        ' Fehlermeldung ausgeben
    End If
Statt "On Error Resume Next" kann man natürlich auch eine Fehlerbehandlungsroutine verwenden, hat aber ein wenig den Nachteil, daß es die Fehlerbehandlung auseinanderreißt und man den Code nicht so ohne weiteres lesen kann.

Mehr? Bitteschön:
Selbstverständlich kann man eine Collection auch als Parameter in einer Sub oder Function übergeben - und nach den vorstehenden Ausführungen ahnt man gerade mal, was das bedeutet. Da man massenweise und unterschiedlichste Dinge in einer Collection ablegen kann, kann man auch die komplexesten Variablenkonstrukte, Objektinstanzen, was auch immer, mit EINEM Parameter an eine Sub übergeben! Nie wieder ellenlange Parameterkonstruktionen.

Hier muß man beachten: Eine normale Variable kann "ByVal" oder "ByRef" übergeben werden - eine Collection kann ebenso als Parameter definiert werden, tatsächlich ignoriert Access aber "ByVal" und erzeugt immer nur "ByRef". Das ist wohl auch gut so, denn wenn man sich eine Megabyte-Collection vorstellt, die mit "ByVal" übergeben würde, würden ja alle enthaltenen Elemente dupliziert werden müssen, das könnte ein ziemlich heftiger Aufwand sein. Wenn man also in der aufgerufenen Prozedur, die die Collection als Parameter bekommt, etwas in der Collection ändert, dann ändert man es auch für die übergeordnete Prozedur.

Und noch ein Highlight der Collection:
Wie gesagt, sie frißt ALLES. Also warum nicht ganz einfach ein eigenes Datenobjekt verwenden? Nein - vergeßt die "Type"-Definitionen. Theoretisch schöne Idee, um ein paar Variablen zu einem Typobjekt zusammenzufassen, wird man mit Type nicht glücklich, da es an allen möglichen Stellen Fehlermeldungen auswirft, man könne den Typ hier nicht verwenden und dort nicht - man könnte es auch gleich entfernen, da mehr oder minder nutzlos.

Das gleiche kann man genauso erreichen, indem man einfach ein neues Klassenmodul schreibt. Das ist nicht so schwer, wie es sich anhört. Im VBA-Editor einfach "Einfügen" - "Neues Klassenmodul" (statt "Modul") verwenden und schon steht das Klassenmodul. Im einfachsten Fall kann man nun einfach ein paar Public-Variablen definieren und schon hat man ein lauffähiges Klassenmodul. Also statt:
Code:
Public Type typMeineDaten
    strX As String
    lngY As Long
End Type
schreibt man einfach in das neue Klassenmodul (mit den natürlich obligatorischen beiden "Option"-Befehlen):
Code:
Option Compare Database
Option Explicit

Public strX As String
Public lngY As Long
Das ist schon alles. Die "Type"-Definition ist damit vollständig ersetzt, das Klassenmodul funktioniert genauso, aber mit dem daraus erstellten Objekt kann man beliebig arbeiten, ohne Fehlermeldungen. Die Klasse benennt man nun in z.B. "clsMeineDaten".

Würde man bei "Type" so schreiben:
Code:
Dim objDaten As typMeineDaten
schreibt man beim Klassenmodul nun:
Code:
Dim objDaten As clsMeineDaten
Kein Unterschied bis hierhin. Nur bei "Type" muß man kein "New" verwenden, beim Klassenmodul schon:
Code:
    Set objDaten = New clsMeineDaten
Das ist aber auch schon das Einzige, was Type interessanter macht als Objekte - also einfach vergessen.

Nun kann das neue Objekt mit Daten befüllt werden:
Code:
    With objMeinObjekt
        .strX = "Test 1"
        .lngY = 1
    End With
Da kommen wir wieder zur Collection zurück: Diese kann nun wieder einfach mit "Add" das neue eigene Datenobjekt entgegennehmen, damit kann die Collection also ganz komplexe eigene Datenstrukturen beinhalten. Schade ist lediglich, daß es keine Möglichkeit gibt, den erstellten Key zu dem Element einer Collection auszulesen, wie das zum Beispiel bei einer TreeView geht (die auch darauf basiert). Aber man kann sich einfach damit behelfen, daß man in eigenen Datenobjekten eben eine zusätzliche Variable für den Key einfügt und diesen dann hier speichert. Ansonsten muß man eben selbst wissen, welche Objekte hinter welchen Keys stehen und welche in der Collection enthalten sind.

Übrigens, nicht wundern: Das "Lokal"- und "Überwachungs"-Fenster aus dem VBA-Editor zeigt nur die ersten 256 Elemente einer Collection an, die anderen danach sind aber trotzdem enthalten. Mit diesen beiden Hilfen kann man bequem durch alle Collections browsen und deren Inhalte ausgeben und damit bekommt man auch komplexe Collections schnell in den Griff.

Alles Neuland? Von wegen. Die meisten haben schon längst mit Collections gearbeitet. Ein paar "prominente" Beispiele: Die "Forms"-Collection beinhaltet alle gerade geladenen Formulare (so sie denn mit DoCmd.OpenForm geöffnet wurden). Die "Reports"-Collection analog für Reporte. Die "Controls"-Collection eines Formulars enthält alle Controls dieses Formulars. Die "Fields"-Collection des Recordsets enthält alle Feldnamen als Key und den Feldinhalt als Element. Die "TempVars"-Collection (ab Access 2007) enthält beliebige, einfache Variablentypen (eine Sonderform der Collection). Die Programmierer von Access haben uns VBA-Programmierern etwas voraus: Sie können mit einer echten objektorientierten Programmiersprache arbeiten und damit Objekte vererben - daher kann man aus einer "simplen" Collection mehr machen.

Naja, wir haben zwar keine Vererbung, aber das heißt nicht, daß wir keine Möglichkeit hätten, etwas Ähnliches selbst zu machen. Man kann nicht nur Objekte in Collections einfügen - man kann natürlich auch Collections in Objekten verwenden. Statt also nur "strX" zu definieren, kann man ebensogut eine Collection in so ein Klassenmodul schreiben, natürlich auch xbeliebig viele. Damit kann man eine Collection auch "erweitern" - indem die Collection Teil eines Objektes wird, das weitere Parameter oder natürlich auch weitere Funktionen/Subs enthält, die etwa nach einem bestimmten Key suchen könnten, so daß man im Hauptprogramm keine extra Fehlerbehandlung implementieren muß. Das übergeordnete Objekt wird so zum "Behälter" für Collections, Variablen, Properties, Functions und Subs - und da jedes Objekt eine Eventfunktion "Class_Initialize" und "Class_Terminate" besitzt, kann man dort praktischerweise auch gleich die Collections instantiieren und am Ende wieder terminieren, so daß sich das Hauptprogramm auch darum nicht kümmern muß. Im einfachen Beispiel sähe das etwa so aus:
Code:
Option Compare Database
Option Explicit

Private clsvar_colTest As Collection
'---------------------------------------------------------------------------------------
' Property    : Test
' Returns     :  - Collection
'---------------------------------------------------------------------------------------
'
Public Property Get Test() As Collection
    Set Test = clsvar_colTest
End Property

Public Property Set Test(colTest As Collection)
    Set clsvar_colTest = colTest
End Property

'---------------------------------------------------------------------------------------
' Property    : ColElement
' Returns     :  - Collection
'---------------------------------------------------------------------------------------
'
Public Property Get ColElement(strName As String) As String
    Dim strReturn As String
    On Error Resume Next
    strReturn = clsvar_colTest(strName)
    If Err.Number = 0 Then
        ColElement = strReturn
      Else
        ColElement = ""
    End If
End Property

Private Sub Class_Initialize()
    Set clsvar_colTest = New Collection
End Sub

Private Sub Class_Terminate()
    Set clsvar_colTest = Nothing
End Sub
Diese einfache Klasse bietet den Direktzugriff auf die Collection über die Eigenschaft "Test" - mit allen Fehlerproblemen, die eine Collection hat - oder den Zugriff über die Eigenschaft "ColElement", die die Fehlerbehandlung selbst übernimmt. Wieder einmal ein Vorteil, den Objekte gegenüber einfachen Variablen haben: Man kann gezielt programmtechnisch steuern, welche Werte zurückgegeben werden und wie auf Fehler reagiert werden soll.

Der Aufruf sähe so aus:
Code:
Public Sub Demo7_Collection()
    Dim objDemo As clsDemo
   
    Set objDemo = New clsDemo
    objDemo.Test.Add "MeineVariable", "MeinKey"
    Debug.Print objDemo.ColElement("MeinKey")
End Sub
Würde man unten jetzt "MeinKey2" eingeben, der nicht existiert, würde die Collection selbst mit einem Fehler reagieren, aber da die Eigenschaft "ColElement" verwendet wird, die den Fehler abfängt, kommt einfach nur ein leerer String zurück.

Fazit:
Wer also noch nie mit eigenen Collections gearbeitet hat und bisher immer nur Arrays verwendet hat, findet hier nun ein weites Feld zum Austoben, womit Anwendungen ein ganzes Stück flexibler werden können. Die Collection sieht am Anfang so simpel aus - Behälter für die Aufnahme beliebiger Objekte - wenn man aber näher hinsieht, ist das wahrscheinlich das mächtigste Instrument in VBA, weswegen Access selbst ja auch reichlich Gebrauch davon macht.

In der angehängten Datenbank befinden sich die Beispiele, es sind keine Tabellen etc. vorhanden, nur die Module "modDemo" und "clsDemo".

Viel Spaß beim Experimentieren und sammeln...

Christian



Sammlungen.zip
 Beschreibung:
Die oben dargestellten Beispiele in einem Modul und einem Klassenmodul

Download
 Dateiname:  Sammlungen.zip
 Dateigröße:  17.63 KB
 Heruntergeladen:  365 mal

Willi Wipp
Moderator


Verfasst am:
30. Aug 2013, 06:32
Rufname:
Wohnort: Raum Wiesbaden


Re: Datensammlung - Arrays und Collections - Re: Datensammlung - Arrays und Collections

Nach oben
       Version: (keine Angabe möglich)

Nachfragen zum Thema bitte hier Datensammlung - Arrays und Collections {Nachgefragt} stellen.
_________________
Eine kurze Rueckmeldung waere nett
SL Willi Wipp

(Anleitung fuer das Anhaengen von Dateien: Klicke links auf [www], Gaeste muessen sich dafuer anmelden)
Neues Thema eröffnen   Neue Antwort erstellen Alle Zeiten sind
GMT + 1 Stunde

Diese Seite Freunden empfehlen

Seite 1 von 1
Gehe zu:  
Du kannst Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.
Du kannst Dateien in diesem Forum nicht posten
Du kannst Dateien in diesem Forum herunterladen

Verwandte Themen
Forum / Themen   Antworten   Autor   Aufrufe   Letzter Beitrag 
Keine neuen Beiträge Access Programmierung / VBA: Datensammlung - Arrays und Collections {Nachgefragt} 12 Stefffano 329 05. Apr 2014, 00:45
Bitsqueezer Datensammlung - Arrays und Collections {Nachgefragt}
Keine neuen Beiträge Access Tabellen & Abfragen: Konvertieren eines Arrays 18 Librasia 278 11. Dez 2013, 12:21
Gast Konvertieren eines Arrays
Keine neuen Beiträge Access Programmierung / VBA: 2 Probleme: 2 Arrays vergleichen, sowie ArrayList leeren 18 bigmig 439 23. Apr 2013, 18:17
MissPh! 2 Probleme: 2 Arrays vergleichen, sowie ArrayList leeren
Keine neuen Beiträge Access Programmierung / VBA: Variable Dimensionierung eines Arrays 9 indscho 277 25. Feb 2013, 16:32
MissPh! Variable Dimensionierung eines Arrays
Keine neuen Beiträge Access Programmierung / VBA: Dynamische Arrays in VBA 3 Marmill 27018 29. Jul 2012, 12:43
steffen0815 Dynamische Arrays in VBA
Keine neuen Beiträge Access Programmierung / VBA: Dynamische Arrays in UDT auf Initialisierung prüfen 21 CrescentEclipse 1062 31. März 2011, 11:03
CrescentEclipse Dynamische Arrays in UDT auf Initialisierung prüfen
Keine neuen Beiträge Access Programmierung / VBA: Diskussion zu Arrays etc. 7 KlausMz 260 27. Dez 2010, 11:56
KlausMz Diskussion zu Arrays etc.
Keine neuen Beiträge Access Programmierung / VBA: vba Sortierung eines Arrays mit 2 Spalten 3 Gast 1646 29. Jul 2009, 13:43
Gast vba Sortierung eines Arrays mit 2 Spalten
Keine neuen Beiträge Access Programmierung / VBA: Arrays vereinen 1 Gast 702 04. Nov 2008, 23:15
Gasth Arrays vereinen
Keine neuen Beiträge Access Programmierung / VBA: arrays in Tabelle einlesen 1 Twix22 651 12. Sep 2008, 10:32
Twix22 arrays in Tabelle einlesen
Keine neuen Beiträge Access Programmierung / VBA: Definition von Arrays in Access 2003 11 Gast01020304 3890 18. Jun 2008, 17:27
Gast01020304 Definition von Arrays in Access 2003
Keine neuen Beiträge Access Programmierung / VBA: Dimension eines Arrays feststellen 6 Darkness 3713 04. Apr 2008, 09:44
Darkness Dimension eines Arrays feststellen
 

----> Diese Seite Freunden empfehlen <------ Impressum - Besuchen Sie auch: HTML CSS