{"id":55000640,"date":"2008-12-01T00:00:00","date_gmt":"2021-02-11T21:23:59","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=640"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Arrays_Collections_und_Dictionarys","status":"publish","type":"post","link":"https:\/\/access-im-unternehmen.de\/Arrays_Collections_und_Dictionarys\/","title":{"rendered":"Arrays, Collections und Dictionarys"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg05.met.vgwort.de\/na\/a17f2f39796f4e0c89e4d4a57aaede41\" width=\"1\" height=\"1\" alt=\"\"><\/p>\n<p><b>Unter Access bietet sich das Speichern von Daten in Tabellen an. Die legen Sie in der Datenbankdatei an und greifen &uuml;ber gebundene Formulare, Berichte und Steuerelemente darauf zu. Unter VBA geschieht dies fast genauso bequem mithilfe von DAO- oder ADO-Recordsets. Manche Konstellationen schlie&szlig;en die Verwendung von gebundenen Recordsets aus und Sie m&uuml;ssen auf andere Strukturen zum tempor&auml;ren Speichern Ihrer Daten zur&uuml;ckgreifen. Dieser Beitrag stellt die verschiedenen M&ouml;glichkeiten und ihre Vor- und Nachteile vor.<\/b><\/p>\n<p>Wollen Sie nur eine einzige Information wie etwa den Namen einer Person so festhalten, dass Sie jederzeit schnell darauf zugreifen k&ouml;nnen, reicht eine simple String-Variable aus:<\/p>\n<pre>Dim strName As String\r\nstrName = &quot;Sascha Trowitzsch&quot;<\/pre>\n<p>Sobald Sie mehrere Daten zu einer Einheit zusammenfassen m&ouml;chten, helfen die Standarddatentypen nicht mehr weiter. Hier k&ouml;nnen Sie benutzerdefinierte Strukturen mit einem festen Aufbau verwenden, deren Definition etwa so aussieht:<\/p>\n<pre>Type TPerson\r\nVorname As String\r\nNachname As String\r\nGeburtsdatum As Date\r\nEnd Type<\/pre>\n<p>Um diese Struktur einzusetzen, deklarieren Sie eine Variable auf Basis der Struktur und f&uuml;llen deren Element wie in den folgenden Beispielanweisungen:<\/p>\n<pre>Dim Autor As TPerson\r\nAutor.Vorname = &quot;Sascha&quot;\r\nAutor.Nachname = &quot;Trowitzsch&quot;\r\nAutor.Geburtsdatum = &quot;11.1.1918&quot;<\/pre>\n<p>Damit sto&szlig;en Sie sp&auml;testens dann an Ihre Grenzen, wenn Sie mehrere gleichartige Daten in einer Liste zusammenfassen wollen &#8211; im Beispiel etwa eine Gruppe von Personen. Dann ben&ouml;tigen Sie ein Datenfeld, wobei einem als Erstes das Array einf&auml;llt. Tats&auml;chlich gibt es unter Access und VBA aber noch einige M&ouml;glichkeiten mehr:<\/p>\n<ul>\n<li class=\"aufz-hlung\">Arrays<\/li>\n<li class=\"aufz-hlung\">Collections<\/li>\n<li class=\"aufz-hlung\">Dictionarys<\/li>\n<li class=\"aufz-hlung\">TempVars (nur Access 2007)<\/li>\n<li class=\"aufz-hlung\">ADODB-Recordsets<\/li>\n<li class=\"aufz-hlung\">API-SafeArrays<\/li>\n<\/ul>\n<p>Die ersten f&uuml;nf Varianten stellen wir in den folgenden Abschnitten vor, die sechste w&uuml;rde leider den Rahmen dieses Beitrags sprengen.<\/p>\n<p><b>ADODB-Recordsets<\/b><\/p>\n<p>Wenn man an ADO-Recordsets denkt, zieht man direkt Parallelen zu ihrem DAO-Pendant und damit zur Bindung an Tabellen. Im Gegensatz zu DAO ben&ouml;tigt ein ADO-Recordset jedoch nicht zwingend einen Bezug zu einer physischen Datenherkunft und kann als reiner Datencontainer im Speicher dienen. Solche Recordsets, in denen die Eigenschaft <b>Connection <\/b>nicht gesetzt ist, nennt man auch ungebundene Recordsets (es gibt auch noch die <b>Disconnected Recordsets<\/b>, die zun&auml;chst mit Daten etwa aus einer Tabelle gef&uuml;llt und dann von dieser getrennt werden &#8211; mehr dazu im Beitrag <b>Disconnected Recordsets<\/b>, Shortlink 437).<\/p>\n<p>Listing 1 zeigt beispielhaft, wie Sie solch ein ungebundenes Recordset anlegen und f&uuml;llen.<\/p>\n<p class=\"kastentabelleheader\">Listing 1: Disconnected ADODB-Recordset als Variablenspeicher<\/p>\n<pre>Sub ADODBCollection()\r\n    Dim rst As ADODB.Recordset\r\n    Set rst = New ADODB.Recordset\r\n    rst.CursorLocation = adUseClient\r\n    rst.Fields.Append &quot;Nachname&quot;, adBSTR\r\n    rst.Fields.Append &quot;Vorname&quot;, adBSTR\r\n    rst.Fields.Append &quot;Geburtsdatum&quot;, adDate\r\n    rst.Open , , adOpenKeyset\r\n    rst.AddNew\r\n    rst!Nachname = &quot;Trowitzsch&quot;\r\n    rst!Vorname = &quot;Sascha&quot;\r\n    rst!Geburtsdatum = &quot;11.1.1918&quot;\r\n    rst.MoveFirst\r\n    rst.Find &quot;Nachname=&apos;Trowitzsch&apos;&quot;\r\n    If Not rst.EOF Then\r\n        Debug.Print rst(0), rst(1), rst(2)\r\n    End If\r\n    rst.Close\r\n    End Sub<\/pre>\n<p>Wichtig ist hier die <b>Open<\/b>-Methode des Recordsets, die den <b>Connection<\/b>-Parameter ausl&auml;sst, wodurch das Recordset keinerlei Bezug zu einer Tabelle der Datenbank selbst hat. Bei einem <b>Disconnected Recordset <\/b>bindet man das Recordset zun&auml;chst an eine Tabelle und deaktiviert anschlie&szlig;end die Verbindung:<\/p>\n<pre>Set rst.Connection = Nothing<\/pre>\n<p>Danach hat man wieder ein rein speicherbasiertes Recordset, in dem Sie Daten &auml;ndern k&ouml;nnen, ohne dass sich dies auf die Daten aus der Herkunftstabelle niederschl&auml;gt.<\/p>\n<p>Das gro&szlig;e Plus von ADODB ist seine hohe Flexibilit&auml;t. Das Recordset l&auml;sst verschiedenste Operationen zu, wobei gerade die Suchm&ouml;glichkeiten einen wesentlichen Vorteil gegen&uuml;ber den weiter unten vorgestellten Arrays und Collections ausmachen. Das hat jedoch seinen Preis: Der Verwaltungsaufwand f&uuml;r das Objekt und seine Schnittstelle ist hoch, was zulasten der Performance geht. Wer Millionen Berechnungen auf Basis der Elemente dieses Datencontainers ausf&uuml;hren m&ouml;chte, wird am ADODB-Recordset keine rechte Freude haben.<\/p>\n<p>Zum Einsatz kommen ungebundene Recordsets als reiner Variablenspeicher daher vor allem, wenn kompliziertere Operationen ausgef&uuml;hrt werden sollen, die sich mit Arrays und Collections nur durch hohen Programmieraufwand realisieren lie&szlig;en.<\/p>\n<p><b>TempVars<\/b><\/p>\n<p>Mit Access 2007 hat Microsoft einen neuen Typ von Auflistungsvariablen eingef&uuml;hrt: die <b>TempVars<\/b>. Es handelt sich dabei um ein eindimensionales Array, das allerdings eher einer Collection &auml;hnelt, weil Sie dessen Elemente &uuml;ber einen Key ansprechen k&ouml;nnen. Speichern k&ouml;nnen Sie in <b>TempVars <\/b>jedoch nur Standarddatentypen, aber keine Objekte, Arrays oder benutzerdefinierte Typen.<\/p>\n<p><b>TempVars <\/b>m&uuml;ssen Sie nicht extra als Variable deklarieren, weil Access die Auflistung von vornherein als Eigenschaft des <b>Application<\/b>-Objekts mitbringt. Neue Elemente f&uuml;gen Sie etwa so hinzu:<\/p>\n<pre>TempVars.Add &quot;Nachname&quot;, &quot;Trowitzsch&quot;\r\nTempVars.Add &quot;Vorname&quot;, &quot;Sascha&quot;&quot;\r\nTempVars.Add &quot;Geburtsdatum&quot;, CDate(&quot;1.11.1918&quot;)\r\nTempVars(&quot;Vorname&quot;) = &quot;Alexander&quot; &apos;Inhalt &auml;ndern\r\nDebug.Print TempVars(&quot;Vorname&quot;)<\/pre>\n<p>Das ist eine komfortable M&ouml;glichkeit, Daten schnell und ohne gro&szlig;en Aufwand in einem Datenfeld zu speichern. <b>TempVars <\/b>haben zudem eine ganz besondere Eigenschaft: Sie gehen nicht verloren. W&auml;hrend globale Variablen beim Auftreten eines nicht behandelten Fehlers unter VBA grunds&auml;tzlich zerst&ouml;rt werden, bleiben <b>TempVars <\/b>erhalten. Sie sind damit sichere Datenspeicher und wickeln ihre Gesch&auml;fte zudem recht flott ab. Die Performance der Auflistung beim Zugriff auf die enthaltenen Elemente ist sehr gut.<\/p>\n<p>Andererseits sind die Features nicht gerade atemberaubend. Ein Knackpunkt etwa ist die fehlende M&ouml;glichkeit, neue <b>TempVars<\/b>-Variablen anzulegen. Man ist auf die eine eingebaute und flache Liste angewiesen. Damit eignen sich <b>TempVars <\/b>in erster Linie zum Speichern anwendungsbezogener Daten, in denen Sie beispielsweise einzelne Einstellungen unterbringen m&ouml;chten.<\/p>\n<p><b>Arrays<\/b><\/p>\n<p>Der klassische Variablentyp zur Speicherung mehrerer Elemente ist das Array. Es kann beliebige Datentypen aufnehmen, also auch Objekte und benutzerdefinierte Typen und arbeitet wegen seines einfachen Aufbaus au&szlig;erordentlich schnell.<\/p>\n<p>Das Beispiel aus Listing 2 speichert mehrere der in einem fr&uuml;heren Beispiel angelegten Type-Strukturen in Form einer Personenliste. <\/p>\n<p class=\"kastentabelleheader\">Listing 3: Variablen setzen mit DAO<\/p>\n<pre>Sub SetVarDAO(ByVal strVarName As String, Wert As Variant)\r\n    With rstVars\r\n    .FindFirst &quot;VarName=&apos;&quot; &amp; strVarName &amp; &quot;&apos;&quot;\r\n    If .NoMatch Then\r\n        .AddNew\r\n        !VarName = strVarName\r\n    Else\r\n        .Edit\r\n    End If\r\n    !VarWert = CStr(Wert)\r\n    .Update\r\n    End With\r\n    End Sub<\/pre>\n<p>Einige Besonderheiten sind im Umgang mit Arrays zu beachten:<\/p>\n<ul>\n<li class=\"aufz-hlung\">Die Zahl der enthaltenen Elemente k&ouml;nnen Sie zwar schon bei der Deklaration der Variable voreinstellen (statisches Array), g&uuml;nstiger ist jedoch die Deklaration als dynamisches Array ohne Angabe der Dimensionen. Diese k&ouml;nnen Sie jederzeit &auml;ndern, was bedeutet, dass Sie beispielsweise nachtr&auml;glich neue Elemente hinzuf&uuml;gen k&ouml;nnen. Anfangs initialisieren Sie das dynamische Array daher mit einem einzigen Element: <b> ReDim arrPerson(0)<\/b><\/li>\n<li class=\"aufz-hlung\">Wenn Sie neue Elemente in ein dynamisches Array aufnehmen, m&uuml;ssen Sie es zuvor neu dimensionieren. Damit bei diesem Vorgang nicht alle bereits gespeicherten Elemente verloren gehen, f&uuml;gen Sie das Schl&uuml;sselwort <b>Preserve <\/b>ein: <b> ReDim Preserve arrPerson(1)<\/b><\/li>\n<li class=\"aufz-hlung\">Der Zugriff auf Elemente des Arrays geschieht immer &uuml;ber ihre Ordinalzahl, also den Index des Elements. Sie k&ouml;nnen ein Element nicht wie bei <b>Collection<\/b>&#8211; und <b>Dictionary<\/b>-Auflistungen &uuml;ber einen Schl&uuml;ssel ansprechen. Damit entf&auml;llt auch eine gezielte Suche nach Elementen, sodass Sie Suchmechanismen selbst programmieren m&uuml;ssen.<\/li>\n<li class=\"aufz-hlung\">Die Elemente eines Arrays k&ouml;nnen Sie &uuml;ber die Direktive <b>Erase <\/b>leeren. Das ist gerade beim Speichern von Objekten im Array wichtig, weil <b>Erase <\/b>dann alle Objektbez&uuml;ge auf <b>Nothing<\/b> setzt. Somit bestehen keine Referenzen auf die Ursprungsobjekte mehr, die dazu f&uuml;hren k&ouml;nnten, dass diese im Speicher verbleiben.<\/li>\n<\/ul>\n<p>Die Zahl der Elemente fragen Sie mit der Funktion <b>UBound <\/b>ab:<\/p>\n<pre>Debug.Print UBound(arrPerson) + 1<\/pre>\n<p>Da <b>UBound <\/b>den Index des letzten Elements zur&uuml;ckgibt, das Array normal aber nullbasiert ist, ergibt sich die Anzahl aus dem h&ouml;chstem Index plus eins. Ist das Array noch gar nicht dimensioniert worden, liefert der Aufruf von <b>UBound<\/b> nicht etwa den Wert <b>0<\/b>, sondern l&ouml;st einen Fehler aus.<\/p>\n<p>Arrays k&ouml;nnen auch andere Arrays als Elemente aufnehmen. Dadurch ist, vor allem im Zusammenspiel mit benutzerdefinierten Typen, der Aufbau von Strukturen m&ouml;glich. So einfach und schnell solche Gebilde auch sind, ein Manko haftet ihnen doch an: Um ein Element im Array zu finden, m&uuml;ssen Sie leider alle Elemente in einer Schleife durchlaufen und mit einer Suchvariablen vergleichen. Der Zeitaufwand f&uuml;r die Suche steigt damit linear mit der Anzahl der Elemente.<\/p>\n<p>Nehmen wir an, Sie h&auml;tten im Array des Beispiels aus Listing 2 genau 100 Personen gespeichert. Um nun den Vornamen der Person <b>M&uuml;ller<\/b> zu erfahren, m&uuml;ssen Sie alle Nachnamen-Elemente des Arrays mit diesem Suchbegriff vergleichen, um schlie&szlig;lich nach dem hundertsten Durchlauf Gleichheit festzustellen. &Uuml;ber den nun ermittelten Index des gefundenen Elements erhalten Sie den Vornamen:<\/p>\n<pre>strFind = &quot;M&uuml;ller&quot;\r\nFor i = 0 To UBound(arrPerson)\r\n    If arrPerson(i).Nachname = strFind Then\r\n        Debug.Print arrPerson(i).Vorname\r\n        Exit For\r\n    End If\r\nNext i<\/pre>\n<p>Unter Performance-Gesichtspunkten ist also die Verwendung von Arrays kontraindiziert, wenn gezielt Elemente bearbeitet werden sollen.<\/p>\n<p><b>Collections<\/b><\/p>\n<p>Collections brauchen Sie im Gegensatz zu Arrays nicht zu dimensionieren. Sie erleichtern die Suche nach Elementen &uuml;ber ihren Schl&uuml;ssel (<b>Key<\/b>). Man spricht deshalb bei Collections und ihren Derivaten auch von assoziativen Arrays. Eine <b>Collection<\/b>-Variable ist schnell angelegt und gef&uuml;llt:<\/p>\n<pre>Sub PersonenCollection()\r\n    Dim colPersonen As VBA.Collection\r\n    Set colPersonen = New VBA.Collection\r\n    With colPersonen\r\n    .Add &quot;Minhorst&quot;, &quot;Nachname&quot;\r\n    .Add &quot;Andr&eacute;&quot;, &quot;Vorname&quot;\r\n    .Add CDate(&quot;26.05.1929&quot;), &quot;Geburtsdatum&quot;\r\n    Debug.Print &quot;Anzahl Elemente:&quot; &amp; .Count\r\n    Debug.Print !Nachname\r\n    End With\r\n    Debug.Print colPersonen(2)\r\n    Set colPersonen = Nothing\r\n    End Sub<\/pre>\n<p>Weitere Bemerkungen zum <b>Collection<\/b>-Objekt:<\/p>\n<ul>\n<li class=\"aufz-hlung\">Eine Collection instanzieren Sie per <b>New<\/b>-Anweisung. Vermeiden Sie, das bereits bei Deklaration der Variablen zu tun, weil damit immer unklar ist, in welchem Zustand sie sich befindet. Gel&ouml;scht wird die Instanz mit Setzen auf <b>Nothing<\/b>.<\/li>\n<li class=\"aufz-hlung\">Elemente f&uuml;gen Sie mit der <b>Add<\/b>-Methode hinzu, wobei Sie einen Schl&uuml;ssel zur sp&auml;teren Identifizierung hinzugeben k&ouml;nnen. Ohne den Schl&uuml;ssel ist der Zugriff dann nur noch &uuml;ber den Index, also die Position des Elements im Array, m&ouml;glich.<\/li>\n<li class=\"aufz-hlung\">Ein Element k&ouml;nnen Sie auch zwischen bestehenden Elementen einf&uuml;gen. Sie m&uuml;ssen dazu die optionalen Parameter <b>before <\/b>und <b>after <\/b>angeben. Erl&auml;uterungen finden Sie in der Visual Basic-Hilfe.<\/li>\n<li class=\"aufz-hlung\">Ein Element k&ouml;nnen Sie &uuml;ber drei Syntaxarten direkt abfragen: <b>Collection(&quot;Schl&uuml;ssel&quot;)<\/b>, <b>Collection!Schl&uuml;ssel <\/b>oder <b>Collection(Index)<\/b><\/li>\n<li class=\"aufz-hlung\">Der Zugriff auf die Elemente &uuml;ber den Ordinalindex beginnt im Unterschied zu Arrays mit dem Index <b>1 <\/b>und nicht mit <b>0<\/b>. Das erste Element im Beispiel ist <b>colPersonen(1)<\/b>.<\/li>\n<li class=\"aufz-hlung\">Ein einmal hinzugef&uuml;gtes Element k&ouml;nnen Sie nicht mehr ver&auml;ndern.<\/li>\n<\/ul>\n<p><!--30percent--><\/p>\n<p>Der letzte Punkt ist deutlich auf der Minusseite zu verbuchen. In einem Array k&ouml;nnen Sie jederzeit ein bestehendes Element mit einem neuen Wert &uuml;berschreiben, in einer Collection geht das nicht. Der Workaround sieht so aus: L&ouml;schen Sie das bestehende Element und f&uuml;gen Sie es mit gleichem Schl&uuml;ssel wieder an gleicher Position hinzu:<\/p>\n<pre>.Remove &quot;Vorname&quot;\r\n.Add &quot;Krischna&quot;, &quot;Vorname&quot;, , &quot;Nachname&quot;<\/pre>\n<p><b>Nachname<\/b> ist hier der Parameter <b>after<\/b>, also der Schl&uuml;ssel des Elements, hinter dem der neue Wert platziert werden soll. Das ist etwas umst&auml;ndlich und kostet wieder einiges an Performance, weil das L&ouml;schen und Einf&uuml;gen intern einige Speicherverschiebungen voraussetzt. Bemerkbar d&uuml;rfte sich das allerdings kaum machen, weil Collections sowohl beim Lesen wie Schreiben ohnehin sehr schnell sind.<\/p>\n<p>Die Tatsache, dass Collections auch Objekte als Elemente aufnehmen k&ouml;nnen (und somit auch andere Collections), macht sie f&uuml;r Verschachtelungen und Objektmodelle interessant. Eine Eigenschaft wurde noch verschwiegen: Collections sind enumerationsf&auml;hig, was bedeutet, dass sie ihre Elemente mit <b>For Each<\/b>-Schleifen durchlaufen k&ouml;nnen:<\/p>\n<pre>Dim itm As Variant\r\nFor Each itm In colPersonen\r\n    Debug.Print itm, TypeName(itm)\r\nNext itm<\/pre>\n<p>Das ist zweifellos praktischer als das Hantieren mit <b>UBound <\/b>und Schleifenz&auml;hlern, wie es Arrays notwendig machen.<\/p>\n<p><b>Dictionarys<\/b><\/p>\n<p>In Access-Kreisen offensichtlich selten benutzt wird das <b>Dictionary<\/b>-Objekt. Das ist nicht verwunderlich, weil es nicht aus den unmittelbar in Access eingesetzten Standardbibliotheken kommt, sondern aus der Library <b>Microsoft Scripting Runtime<\/b>. Mit zus&auml;tzlichen Referenzen soll man ja in VBA-Projekten im Interesse von Kompatibilit&auml;t und Stabilit&auml;t nicht wuchern, doch dieser Verweis ist ziemlich unverd&auml;chtig, findet sich die Datei <b>scrrun.dll <\/b>schlie&szlig;lich in jedem Windows-System wieder. Fr&uuml;her wurde sie aus Sicherheitsgr&uuml;nden von Administratoren gerne mal deaktiviert, doch heute sollte das pass&eacute; sein, weil viele Windows-Funktionen auf dieser Bibliothek aufbauen.<\/p>\n<p>Wenn Sie keinen Verweis auf die Bibliothek setzen m&ouml;chten, dann erhalten Sie das <b>Dictionary<\/b>-Objekt auch &uuml;ber Late Binding:<\/p>\n<pre>Dim objDictionary as Object\r\nSet objDictionary = CreateObject(&quot;Scripting.&micro;\r\nDictionary&quot;)<\/pre>\n<p>Wie immer bei Late Binding m&uuml;ssen Sie dann aber kleinere Performance-Einbu&szlig;en hinnehmen, die dem Marshalling der Objekte geschuldet sind, und k&ouml;nnen im VBA-Editor nicht die Dienste von IntelliSense in Anspruch nehmen.<\/p>\n<p>Ein <b>Dictionary<\/b>-Objekt ist eigentlich auch eine Collection, hat jedoch mehr Eigenschaften und Methoden, wodurch es flexibler und einfacher zu bedienen ist.<\/p>\n<p>Der Code zum Instanzieren und F&uuml;llen des <b>Dictionary<\/b>-Objekts ist fast identisch mit dem f&uuml;r Collections. Der folgende Beispielcode verwendet zur Abwechslung mal Late Binding:<\/p>\n<pre>Sub PersonenDictionary()\r\n    Dim dictPersonen As Object\r\n    Set dictPersonen = CreateObject(&quot;Scripting.&micro;\r\n    Dictionary&quot;)\r\n    With dictPersonen\r\n    !Nachname = &quot;Trowitzsch&quot;\r\n    !Vorname = &quot;Sascha&quot;\r\n    !Geburtsdatum = CDate(&quot;11.1.1918&quot;)\r\n    Debug.Print &quot;Anzahl Elemente:&quot; &amp; .Count\r\n    Debug.Print !Nachname\r\n    .Add &quot;Nachname&quot;, &quot;Minhorst&quot; &apos;Fehler!\r\n    End With\r\n    Set dictPersonen = Nothing\r\n    End Sub<\/pre>\n<p>Es f&auml;llt auf, dass f&uuml;r das Hinzuf&uuml;gen von Elementen keine <b>Add<\/b>-Methode zum Einsatz kommt, sondern lediglich eine direkte Zuweisung des Werts &uuml;ber einen Schl&uuml;ssel. Das schreit nach Erl&auml;uterung, wobei die folgende &Uuml;bersicht als Erweiterung dessen gilt, was Sie bereits zu Collections lesen konnten:<\/p>\n<ul>\n<li class=\"aufz-hlung\">Elemente eines <b>Dictionary<\/b>-Objekts sind immer mit einem obligatorischen Schl&uuml;ssel verkn&uuml;pft. Ein Zugriff &uuml;ber einen Index, wie bei Collections, ist nicht direkt m&ouml;glich. Der Grund hierf&uuml;r ist, dass Sie als Schl&uuml;ssel nicht nur Zeichenketten verwenden k&ouml;nnen, sondern beliebige Datentypen und sogar Objekte (Ausnahme: Arrays). Infolgedessen wei&szlig; ein <b>Dictionary<\/b>-Objekt bei Angabe einer Ordinalzahl nicht, ob es sich hierbei um einen Index oder einen Key handelt.<\/li>\n<li class=\"aufz-hlung\">Neue Elemente k&ouml;nnen Sie durch einfache Zuweisung eines Schl&uuml;ssel-Wert-Paares anlegen.<\/li>\n<li class=\"aufz-hlung\">Es gibt dennoch eine Methode <b>Add<\/b>, die immer dann fehlschl&auml;gt, wenn ein Schl&uuml;ssel bereits im <b>Dictionary<\/b>-Objekt vorhanden ist.<\/li>\n<li class=\"aufz-hlung\">Elemente k&ouml;nnen Sie im Gegensatz zu denen von Collections ver&auml;ndern. Der Wert wird unter Angabe des Schl&uuml;ssels neu gesetzt, zum Beispiel:<\/li>\n<\/ul>\n<p class=\"quellcodefliesstext-miteinzug\">dictPersonen!Nachname = &quot;Minhorst&quot;<\/p>\n<ul>\n<li class=\"aufz-hlung\">Aus der Kombination der bisherigen Ausf&uuml;hrungen folgt eine Eigent&uuml;mlichkeit von Dictionarys, der besonderes Augenmerk zu widmen ist. Versuchen Sie, auf ein Element zuzugreifen, das noch nicht existiert, also dessen Schl&uuml;ssel noch nicht in der <b>Keys<\/b>-Auflistung zu finden ist, dann legt das Objekt einfach ein neues Element mit diesem <b>Key <\/b>an und weist ihm den Wert <b>Empty <\/b>zu. Die folgende Anweisung zum Abfragen des nicht existierenden Elements <b>Adresse<\/b> gibt demnach weder den Wert <b>Null <\/b>zur&uuml;ck, noch ereignet sich ein Fehler:<\/li>\n<\/ul>\n<p class=\"quellcodefliesstext-miteinzug\">Debug.Print dictPersonen!Adresse<\/p>\n<p class=\"text-miteinzug\">Stattdessen legt die Anweisung ein neues Element mit leerem Inhalt an.<\/p>\n<ul>\n<li class=\"aufz-hlung\">Um solche Probleme zu vermeiden, sieht das Dictionary die Funktion <b>Exists <\/b>vor, mit der Sie das Vorhandensein eines Elements abfragen k&ouml;nnen:<\/li>\n<\/ul>\n<p class=\"quellcodefliesstext-miteinzug\">If dictPersonen.Exists(&quot;Adresse&quot;) Then _<\/p>\n<p class=\"quellcodefliesstext-miteinzug\"> Debug.Print dictPersonen!Adresse<\/p>\n<ul>\n<li class=\"aufz-hlung\">Nicht nur den Wert eines Elements k&ouml;nnen Sie &auml;ndern, sondern auch dessen Schl&uuml;ssel. Das mag Stirnrunzeln hervorrufen, denn wozu sollte man den <b>Key <\/b>&auml;ndern &#8211; schlie&szlig;lich &auml;n-dert man die ID eines Datensatzes auch nicht, nachdem er einmal angelegt wurde. Sinn bekommt das Ganze aber etwa in Anbetracht der Tatsache, dass man die Elemente eines Dictionarys nicht wie mit einer Abfrage sortieren kann, ohne sie zu vertauschen. Sieht man f&uuml;r ein Dictionary numerische Schl&uuml;ssel vor, dann kann man nach Sortierung nach Wert der Elemente einfach die Schl&uuml;ssel in aufsteigender Reihenfolge neu vergeben und hat nun in Zukunft eine sortierte Liste vor sich.<\/li>\n<\/ul>\n<p>Den Schl&uuml;ssel eines Elements &auml;ndern Sie so:<\/p>\n<pre>arrPersonen.Key(&quot;Nachname&quot;) = &quot;Vorname&quot;<\/pre>\n<p>Als Schl&uuml;ssel f&uuml;r <b>Dictionary<\/b>-Elemente k&ouml;nnen Sie auch Objekte angeben. Betrachten Sie folgendes Beispiel:<\/p>\n<pre>Dim dict As New Dictionary\r\ndict.Add CurrentDb, &quot;Test 1&quot;\r\ndict.Add CurrentDb, &quot;Test 2&quot;\r\ndict.Add dict, &quot;Test 3&quot;\r\nDebug.Print dict(CurrentDb)\r\nDebug.Print dict(dict)<\/pre>\n<p>Die Anweisungen verwenden drei verschiedene Objekte als Schl&uuml;ssel: Zweimal den Verweis auf die aktuelle Datenbank und einmal wird als Kuriosum das Dictionary selbst als Schl&uuml;sselobjekt eingesetzt. Tats&auml;chlich gibt nur die letzte Zeile etwas aus, n&auml;mlich &#8222;Test 3&#8220;.<\/p>\n<p>Das erste <b>Debug.Print <\/b>zeigt nur einen leeren Wert. Die Ursache ist, dass <b>CurrentDb <\/b>immer eine neue Kopie der aktuellen Datenbank zur&uuml;ckgibt, nicht einen Verweis auf das eigentliche Datenbankobjekt, den man mit <b>DBEngine(0)(0) <\/b>erhielte. Also ist das dritte <b>CurrentDb <\/b>ein falscher Schl&uuml;ssel, der nicht nur nichts zur&uuml;ckgibt, sondern zu allem &Uuml;berfluss auch noch automatisch ein neues Element anlegt, wie bereits weiter oben ausgef&uuml;hrt.<\/p>\n<p>Also sind die ersten zwei Elemente nun verschwunden Nicht wirklich, denn es gibt noch eine andere Methode, um auf deren Wert zuzugreifen:<\/p>\n<pre>Debug.Print dict.Items(2)\r\nTest 2<\/pre>\n<p>Das zeigt, dass man &uuml;ber Umwege doch einen Index f&uuml;r den Zugriff verwenden kann. Wo aber ist der Schl&uuml;ssel (<b>CurrentDb<\/b>) geblieben Auch der ist noch vorhanden:<\/p>\n<pre>Debug.Print Typename(dict.Keys(2)) &apos; &gt;&quot;Database&quot; !<\/pre>\n<p>Also f&uuml;hrt auch diese etwas schr&auml;ge Konstruktion zum Erfolg:<\/p>\n<pre>Debug.Print dict(dict.Keys(2))\r\nTest 2<\/pre>\n<p>Eigentlich ist ein <b>Dictionary<\/b>-Element ein Container f&uuml;r zwei verkn&uuml;pfte Datenobjekte, auf die Sie sp&auml;ter separat zugreifen k&ouml;nnen. Die Bedeutung des Begriffs <b>Assoziative Liste <\/b>ist hier perfekt umgesetzt.<\/p>\n<p>Lassen wir es bei diesen Beispielen bewenden, die nur demonstrieren sollen, wie komplex der Umgang mit Dictionarys sein kann und dass Objektmodelle mit ihnen noch einfacher zu realisieren sind als mit Collections.<\/p>\n<p>In der Beispieldatenbank finden sich im Modul <b>mdlDictionarySpecials <\/b>noch ausf&uuml;hrlichere Prozeduren, die verschiedene weitere M&ouml;glichkeiten zeigen.<\/p>\n<p><b>Performance im richtigen Leben<\/b><\/p>\n<p>Sch&ouml;n und gut, werden Sie sich sagen, aber was fange ich nun mit den hier vorgestellten Elementen in meinen Anwendungen an<\/p>\n<p>Nun, Ihre Fantasie m&ouml;chten wir nicht infrage stellen und lediglich anregen, sich beim n&auml;chsten Mal, wenn Ihnen die Verwendung von Arrays f&uuml;r einen Zweck vorschwebt, an diesen Beitrag zu erinnern und &uuml;ber Alternativen nachzudenken.<\/p>\n<p>Ein ausf&uuml;hrliches Beispiel ist in der Demodatenbank enthalten und zeigt, wie man Daten einer Tabelle, die immer wieder in der Anwendung ben&ouml;tigt werden, ohne direkten Tabellenzugriff schnell auslesen und setzen kann.<\/p>\n<p>Das k&ouml;nnen etwa Daten sein, die Werte f&uuml;r beliebige Einstellungen der Anwendung enthalten &#8211; quasi Systemvariablen &#8211; und daher nennt sich die zugrunde liegende Tabelle auch <b>tblVariablen<\/b>. <\/p>\n<p>H&auml;ufig realisiert man so etwas &uuml;ber ein globales Recordset, das st&auml;ndig offen ist und auf dessen Datens&auml;tze &uuml;ber <b>Find<\/b>-Methoden zugegriffen wird. Auch in der Demodatenbank gibt es diese Technik, aber eben auch alternative Methoden.<\/p>\n<p>Die Aufgabe besteht darin, die Werte aus der Tabelle <b>tblVariablen <\/b>st&auml;ndig schnell und ressourcensparend bereit zu halten.<\/p>\n<p>Ihr Aufbau ist einfach:<\/p>\n<ul>\n<li class=\"aufz-hlung\"><b>ID <\/b>(<b>Autowert<\/b>)<\/li>\n<li class=\"aufz-hlung\"><b>VarName <\/b>(<b>Text<\/b>)<\/li>\n<li class=\"aufz-hlung\"><b>VarWert <\/b>(<b>Text<\/b>)<\/li>\n<\/ul>\n<p>Ein Datensatz zur Speicherung einer Variablen f&uuml;r die horizontale Position eines Formulars sieht etwa so aus:<\/p>\n<pre>1 | &quot;frmPersonen.X&quot; | &quot;330&quot;<\/pre>\n<p>In vielen F&auml;llen wird so ein einzelner Wert &uuml;ber die Funktion <b>DLookup <\/b>ermittelt:<\/p>\n<pre>Function GetVarLookup(ByVal strVarName As String)\r\n    GetVarLookup = DLookup(&quot;VarWert&quot;, _\r\n    &quot;tblVariablen&quot;, _\r\n    &quot;VarName=&apos;&quot; &amp; strVarName &amp; &quot;&apos;&quot;)\r\nEnd Function\r\nDebug.Print GetVarLookup(&quot;frmPersonen.X&quot;)<\/pre>\n<p>F&uuml;r sporadische Zugriffe mag diese Funktion v&ouml;llig in Ordnung sein, f&uuml;r h&auml;ufige ist sie es aber nicht, wie Performance-Tests sp&auml;ter zeigen werden.<\/p>\n<p>Die Beispieldatenbank enth&auml;lt mehrere Module, die alle gleichartig aufgebaut sind und auch alle die gleichen Aufgaben erf&uuml;llen, aber mit unterschiedlichen Techniken arbeiten. Die Hauptaufgaben sind:<\/p>\n<ul>\n<li class=\"aufz-hlung\">Datens&auml;tze aus der Tabelle auslesen: <b>InitVars<\/b><\/li>\n<li class=\"aufz-hlung\">Variablen hinzuf&uuml;gen oder bearbeiten: <b>SetVar (Variablenname, Wert)<\/b><\/li>\n<li class=\"aufz-hlung\">Variablen auslesen: <b>GetVar(Variablenname)<\/b><\/li>\n<\/ul>\n<p>Das Auslesen der Tabelle geschieht in allen Modulen zun&auml;chst &uuml;ber ein DAO-Recordset. Danach jedoch teilen sich die Wege und die Werte werden in Arrays (<b>mdlArray<\/b>), Collections (<b>mdlCollections<\/b>) oder Dictionarys (<b>mdlDictionary<\/b>) &uuml;berf&uuml;hrt, &uuml;ber die sie anschlie&szlig;end ausgelesen oder neu gesetzt werden k&ouml;nnen.<\/p>\n<p>Das Modul <b>mdlDAO <\/b>stellt mehr oder weniger den Prototyp dar. Es gibt dort ein modulweit g&uuml;ltiges Recordset <b>rstVars<\/b>, das mit dieser Zeile aufgef&uuml;llt wird:<\/p>\n<pre>Set rstVars = CurrentDb.OpenRecordset (&quot;SELECT &micro;\r\nVarName, VarWert FROM tblVariablen&quot;, &micro;\r\ndbOpenDynaset)<\/pre>\n<p>Das Lesen von Variablen geschieht &uuml;ber die Funktion <b>GetVarDAO<\/b>:<\/p>\n<pre>Function GetVarDAO(ByVal strVarName As String) _\r\n    As Variant\r\n    With rstVars\r\n    .FindFirst &quot;VarName=&apos;&quot; &amp; strVarName &amp; &quot;&apos;&quot;\r\n    If .NoMatch Then\r\n        GetVarDAO = Null\r\n    Else\r\n        GetVarDAO = !VarWert\r\n    End If\r\n    End With\r\nEnd Function<\/pre>\n<p>Wer unter DAO oft mit der <b>Recordset<\/b>-Methode <b>FindFirst<\/b> arbeitet, der wei&szlig;, dass diese Methode nicht besonders performant ist. Weitaus schneller ist die auf den Prim&auml;rindex arbeitende Methode <b>Seek<\/b>, die aber bei verkn&uuml;pften Tabellen leider ausscheidet.<\/p>\n<p>Die Prozedur <b>SetVar <\/b>f&uuml;gt Variablen hinzu oder setzt diese neu. Die DAO-Variante sieht wie in Listing 3 aus.<\/p>\n<p class=\"kastentabelleheader\">Listing 5: Variablen einer Collection bearbeiten <\/p>\n<pre>Sub SetVarCol(ByVal strVarName As String, Wert As Variant)\r\n    On Error Resume Next\r\n    colVars.Add Wert, strVarName\r\n    If Err.Number = 457 Then &apos;Schl&uuml;ssel bereits vorhanden\r\n    colVars.Remove strVarName\r\n    colVars.Add Wert, strVarName\r\nEnd If\r\nEnd Sub\r\nFunction GetVarCol(ByVal strVarName As String) As Variant\r\nGetVarCol = colVars(strVarName)\r\nEnd Function<\/pre>\n<p>Die restlichen Prozeduren besch&auml;ftigen sich mit dem L&ouml;schen von Werten oder dem Abbau von Objekten und sollen hier nicht im Detail beschrieben werden.<\/p>\n<p>Das Modul <b>mdlArrays <\/b>zeigt, genau wie die entsprechenden Module mit den <b>Collection<\/b>&#8211; und <b>Dictionary<\/b>-Beispielen, eine Abweichung: Nach dem &Ouml;ffnen des Recordsets wird &uuml;ber die Prozedur <b>FillArray <\/b>dessen Inhalt in das modulweit g&uuml;ltige Array <b>arrVars <\/b>&uuml;berf&uuml;hrt. Die analogen Prozeduren f&uuml;r die anderen Module lauten <b>FillCollection<\/b>, <b>FillDictionary <\/b>und f&uuml;llen die Objektvariablen <b>colVars<\/b> und <b>dictVars<\/b>. Die Funktionen zum Auslesen und Setzen der Variablen laufen ab da nur noch &uuml;ber diese Auflistungsobjekte ohne Bezug zur Tabelle <b>tblVariablen<\/b>.<\/p>\n<p>Nebenbei: Prozeduren, die den Inhalt der Variablen abschlie&szlig;end wieder in der Quelltabelle speichern, m&uuml;ssten Sie selbst nachtragen &#8211; sie fehlen in der Beispieldatenbank.<\/p>\n<p>Beispielhaft zeigen die Listings 4 bis 6 die einzelnen Funktionen zum Auslesen und Setzen der Variablen. Schon am Umfang der Prozeduren ist zu erkennen, welche Methoden sich f&uuml;r die gestellte Aufgabe besser oder weniger eignen.<\/p>\n<p>Was nun noch ansteht, ist ein Stress-Test dieser Module und eine Messung der Performance der L&ouml;sungen. Die daf&uuml;r ben&ouml;tigten Aufrufprozeduren sind f&uuml;r Sie im Modul <b>mdlTest<\/b> zusammengefasst. Werfen Sie dort einfach die Sub-Funktion <b>TabelleFuellenUndPerformanceTesten <\/b>an und warten Sie auf das Ergebnis im VBA-Direktfenster. Der Ablauf des Tests im Schnelldurchlauf:<\/p>\n<ul>\n<li class=\"aufz-hlung\">Tabelle <b>tblVariablen <\/b>mit 1.000 k&uuml;nstlichen Werten f&uuml;llen<\/li>\n<li class=\"aufz-hlung\">Auflistungsvariablen in den einzelnen Modulen initialisieren<\/li>\n<li class=\"aufz-hlung\">F&uuml;r jede Methode jeweils 10.000 Variablenwerte auslesen<\/li>\n<li class=\"aufz-hlung\">F&uuml;r jede Methode jeweils 5.000 Werte setzen, wobei davon 1.000 neu angelegt und 4.000 bearbeitet werden<\/li>\n<li class=\"aufz-hlung\">F&uuml;r jede Methode die ben&ouml;tigte Zeit messen<\/li>\n<\/ul>\n<p>Tab. 1 zeigt das mit einem aktuellen Rechner ermittelte Ergebnis und spricht B&auml;nde.<\/p>\n<p>Fast schon schockierend: Die <b>Dictionary<\/b>-Methode ist etwa um den Faktor 250 schneller als <b>DLookup <\/b>&#8211; ein weiterer Beweis f&uuml;r die Unzul&auml;nglichkeit dieser Funktion. <\/p>\n<p>Gut ist es aber auch nicht um DAO-Recordset-Methoden bestellt. Die beiden SQL-Eintr&auml;ge kommen &uuml;brigens durch weitere Methoden zustande, dem Setzen und Lesen von Datens&auml;tzen &uuml;ber zusammengesetzte SQL-Strings, wie hier:<\/p>\n<pre> DBEngine(0)(0).OpenRecordset(&quot;SELECT VarWert &micro;\r\nFROM tblVariablen &quot; &amp; &quot;WHERE VarName=&micro;\r\n&apos;Nachname&apos;&quot;, dbOpenSnapshot)(0)<\/pre>\n<p>Auch das ist keine empfehlenswerte L&ouml;sung, wobei man ihr zugutehalten muss, dass sie in anderen Zusammenh&auml;ngen wegen der flexibleren Such- und Filterm&ouml;glichkeiten ein Mittel der Wahl ist.<\/p>\n<p>Die Array-Methoden schneiden sogar schlechter ab als der DAO-Zugriff.<\/p>\n<p>Das allerdings nicht etwa deshalb, weil Arrays langsam w&auml;ren, sondern weil der gezielte Zugriff auf ihre Elemente nur durch Schleifenkonstrukte m&ouml;glich ist.<\/p>\n<p>Als Spitzenreiter bleiben die <b>Collection<\/b>&#8211; und <b>Dictionary<\/b>-L&ouml;sungen, die in einer ganz eigenen Liga spielen. Die Messungen befinden sich hier schon fast au&szlig;erhalb der Toleranzen. Man muss sich vor Augen f&uuml;hren, dass sich in einem <b>Dictionary<\/b>-Element gezielt locker 300.000 Elemente pro Sekunde setzen lassen.<\/p>\n<p><b>Fazit<\/b><\/p>\n<p>Werfen Sie Ihre Arrays &uuml;ber Bord und vor allen Dingen Ihre DLookups, wenn nicht triftige Gr&uuml;nde dagegen sprechen.<\/p>\n<p>Leichter und performanter als mit Collections und Dictionarys werden Sie tabellenunabh&auml;ngige Datenlisten kaum bearbeiten k&ouml;nnen.<\/p>\n<p>Und letztlich spricht wegen der Flexibilit&auml;t von Dictionarys, etwa der datentyptoleranten Schl&uuml;ssel, auch wieder nichts f&uuml;r Collections.<\/p>\n<table>\n<tbody>\n<tr>\n<td>\n<p class=\"kastentabelleheader\">Listing 2: Array mit Elementen eines benutzerdefinierten Datentyps<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<pre>Type Person\r\nNachname As String\r\nVorname As String\r\nGeburtsdatum As Date\r\nEnd Type\r\nSub PersonenArray()\r\n    Dim arrPerson() As Person\r\n    ReDim arrPerson(0)\r\n    arrPerson(0).Vorname = &quot;Sascha&quot;\r\n    arrPerson(0).Nachname = &quot;Trowitzsch&quot;\r\n    arrPerson(0).Geburtsdatum = &quot;11.1.1918&quot;\r\n    ...\r\n    ReDim Preserve arrPerson(100)\r\n    arrPerson(100).Vorname = &quot;Walter&quot;\r\n    arrPerson(100).Nachname = &quot;Ulbricht&quot;\r\n    arrPerson(100).Geburtsdatum = &quot;31.12.1899&quot;\r\n    Debug.Print arrPerson(100).Nachname\r\n    Erase arrPerson\r\n    End Sub<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<table>\n<tbody>\n<tr>\n<td>\n<p class=\"kastenheader\">Wohin mit den Anwendungseinstellungen<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>Anwendungseinstellungen m&uuml;ssen im Prinzip nat&uuml;rlich nicht in verkn&uuml;pften Tabellen eines Backends gespeichert werden, denn schlie&szlig;lich handelt es sich hier ja um lokale Einstellungen. Die Sache hat aber einen Haken: Sobald Sie ein Update Ihrer Anwendung (Frontends) an die Benutzer weitergeben, werden deren Einstellungen alle verloren gehen beziehungsweise durch Ihre ersetzt.<\/p>\n<p>Deshalb ist es g&uuml;nstiger, solche Variablentabellen nicht im Frontend unterzubringen, sondern im Backend. Im Unterschied zu unserer Demo ist dann allerdings ein weiteres indiziertes Feld <b>Username <\/b>oder &auml;hnlich in die Variablentabelle aufzunehmen, damit die Einstellungen eines Benutzers entsprechend gefiltert werden k&ouml;nnen.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p class=\"kastentabelleheader\">Listing 4: Variablen eines Arrays bearbeiten<\/p>\n<pre>Sub SetVarArr(ByVal strVarName As String, Wert As Variant)\r\n    Dim i As Long\r\n    Dim n As Long\r\n    n = UBound(arrVars, 2)\r\n    For i = 0 To n\r\n        If arrVars(0, i) = strVarName Then\r\n            arrVars(1, i) = Wert\r\n            Exit For\r\n        End If\r\n    Next i\r\n    ReDim Preserve arrVars(1, i)\r\n    arrVars(0, i) = strVarName\r\n    arrVars(1, i) = Wert\r\n    End Sub\r\nFunction GetVarArr(ByVal strVarName As String) As Variant\r\n    Dim i As Long\r\n    Dim n As Long\r\n    n = UBound(arrVars, 2)\r\n    For i = 0 To n\r\n        If arrVars(0, i) = strVarName Then\r\n            GetVarArr = arrVars(1, i)\r\n            Exit For\r\n        End If\r\n    Next i\r\nEnd Function<\/pre>\n<p class=\"kastentabelleheader\">Listing 6: Variablen eines Dictionary bearbeiten <\/p>\n<pre>Sub SetVarDict(ByVal strVarName As String, Wert As Variant)\r\n    dictVars(strVarName) = Wert\r\n    End Sub\r\nFunction GetVarDict(ByVal strVarName As String) As Variant\r\n    GetVarDict = dictVars(strVarName)\r\nEnd Function<\/pre>\n<h3>Downloads zu diesem Beitrag<\/h3>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>collections.mdb<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/CDCA22DF-DB66-4C3B-BEF7-EF4E1B47DB56\/aiu_640.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Unter Access bietet sich das Speichern von Daten in Tabellen an. Die legen Sie in der Datenbankdatei an und greifen &uuml;ber gebundene Formulare, Berichte und Steuerelemente darauf zu. Unter VBA geschieht dies fast genauso bequem mithilfe von DAO- oder ADO-Recordsets. Manche Konstellationen schlie&szlig;en die Verwendung von gebundenen Recordsets aus und Sie m&uuml;ssen auf andere Strukturen zum tempor&auml;ren Speichern Ihrer Daten zur&uuml;ckgreifen. Dieser Beitrag stellt die verschiedenen M&ouml;glichkeiten und ihre Vor- und Nachteile vor.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[662008,66062008,44000025],"tags":[],"class_list":["post-55000640","post","type-post","status-publish","format-standard","hentry","category-662008","category-66062008","category-VBA_und_Programmiertechniken"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.9 (Yoast SEO v27.3) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Arrays, Collections und Dictionarys - Access im Unternehmen<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/access-im-unternehmen.de\/Arrays_Collections_und_Dictionarys\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Arrays, Collections und Dictionarys\" \/>\n<meta property=\"og:description\" content=\"Unter Access bietet sich das Speichern von Daten in Tabellen an. Die legen Sie in der Datenbankdatei an und greifen &uuml;ber gebundene Formulare, Berichte und Steuerelemente darauf zu. Unter VBA geschieht dies fast genauso bequem mithilfe von DAO- oder ADO-Recordsets. Manche Konstellationen schlie&szlig;en die Verwendung von gebundenen Recordsets aus und Sie m&uuml;ssen auf andere Strukturen zum tempor&auml;ren Speichern Ihrer Daten zur&uuml;ckgreifen. Dieser Beitrag stellt die verschiedenen M&ouml;glichkeiten und ihre Vor- und Nachteile vor.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/access-im-unternehmen.de\/Arrays_Collections_und_Dictionarys\/\" \/>\n<meta property=\"og:site_name\" content=\"Access im Unternehmen\" \/>\n<meta property=\"article:published_time\" content=\"2021-02-11T21:23:59+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/vg05.met.vgwort.de\/na\/a17f2f39796f4e0c89e4d4a57aaede41\" \/>\n<meta name=\"author\" content=\"Andr\u00e9 Minhorst\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Verfasst von\" \/>\n\t<meta name=\"twitter:data1\" content=\"Andr\u00e9 Minhorst\" \/>\n\t<meta name=\"twitter:label2\" content=\"Gesch\u00e4tzte Lesezeit\" \/>\n\t<meta name=\"twitter:data2\" content=\"23\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Arrays_Collections_und_Dictionarys\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Arrays_Collections_und_Dictionarys\\\/\"},\"author\":{\"name\":\"Andr\u00e9 Minhorst\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\"},\"headline\":\"Arrays, Collections und Dictionarys\",\"datePublished\":\"2021-02-11T21:23:59+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Arrays_Collections_und_Dictionarys\\\/\"},\"wordCount\":3832,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Arrays_Collections_und_Dictionarys\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg05.met.vgwort.de\\\/na\\\/a17f2f39796f4e0c89e4d4a57aaede41\",\"articleSection\":[\"2008\",\"6\\\/2008\",\"VBA und Programmiertechniken\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Arrays_Collections_und_Dictionarys\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Arrays_Collections_und_Dictionarys\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Arrays_Collections_und_Dictionarys\\\/\",\"name\":\"Arrays, Collections und Dictionarys - Access im Unternehmen\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Arrays_Collections_und_Dictionarys\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Arrays_Collections_und_Dictionarys\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg05.met.vgwort.de\\\/na\\\/a17f2f39796f4e0c89e4d4a57aaede41\",\"datePublished\":\"2021-02-11T21:23:59+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Arrays_Collections_und_Dictionarys\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Arrays_Collections_und_Dictionarys\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Arrays_Collections_und_Dictionarys\\\/#primaryimage\",\"url\":\"http:\\\/\\\/vg05.met.vgwort.de\\\/na\\\/a17f2f39796f4e0c89e4d4a57aaede41\",\"contentUrl\":\"http:\\\/\\\/vg05.met.vgwort.de\\\/na\\\/a17f2f39796f4e0c89e4d4a57aaede41\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Arrays_Collections_und_Dictionarys\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Arrays, Collections und Dictionarys\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\",\"name\":\"Access im Unternehmen\",\"description\":\"Das Magazin f\u00fcr Datenbankentwickler auf Basis von Microsoft Access\",\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/access-im-unternehmen.de\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"de\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\",\"name\":\"Andr\u00e9 Minhorst Verlag\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/wp-content\\\/uploads\\\/2019\\\/09\\\/aiu_wp.png\",\"contentUrl\":\"https:\\\/\\\/access-im-unternehmen.de\\\/wp-content\\\/uploads\\\/2019\\\/09\\\/aiu_wp.png\",\"width\":370,\"height\":111,\"caption\":\"Andr\u00e9 Minhorst Verlag\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\",\"name\":\"Andr\u00e9 Minhorst\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"caption\":\"Andr\u00e9 Minhorst\"}}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Arrays, Collections und Dictionarys - Access im Unternehmen","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/access-im-unternehmen.de\/Arrays_Collections_und_Dictionarys\/","og_locale":"de_DE","og_type":"article","og_title":"Arrays, Collections und Dictionarys","og_description":"Unter Access bietet sich das Speichern von Daten in Tabellen an. Die legen Sie in der Datenbankdatei an und greifen &uuml;ber gebundene Formulare, Berichte und Steuerelemente darauf zu. Unter VBA geschieht dies fast genauso bequem mithilfe von DAO- oder ADO-Recordsets. Manche Konstellationen schlie&szlig;en die Verwendung von gebundenen Recordsets aus und Sie m&uuml;ssen auf andere Strukturen zum tempor&auml;ren Speichern Ihrer Daten zur&uuml;ckgreifen. Dieser Beitrag stellt die verschiedenen M&ouml;glichkeiten und ihre Vor- und Nachteile vor.","og_url":"https:\/\/access-im-unternehmen.de\/Arrays_Collections_und_Dictionarys\/","og_site_name":"Access im Unternehmen","article_published_time":"2021-02-11T21:23:59+00:00","og_image":[{"url":"http:\/\/vg05.met.vgwort.de\/na\/a17f2f39796f4e0c89e4d4a57aaede41","type":"","width":"","height":""}],"author":"Andr\u00e9 Minhorst","twitter_card":"summary_large_image","twitter_misc":{"Verfasst von":"Andr\u00e9 Minhorst","Gesch\u00e4tzte Lesezeit":"23\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/access-im-unternehmen.de\/Arrays_Collections_und_Dictionarys\/#article","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/Arrays_Collections_und_Dictionarys\/"},"author":{"name":"Andr\u00e9 Minhorst","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f"},"headline":"Arrays, Collections und Dictionarys","datePublished":"2021-02-11T21:23:59+00:00","mainEntityOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Arrays_Collections_und_Dictionarys\/"},"wordCount":3832,"commentCount":0,"publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Arrays_Collections_und_Dictionarys\/#primaryimage"},"thumbnailUrl":"http:\/\/vg05.met.vgwort.de\/na\/a17f2f39796f4e0c89e4d4a57aaede41","articleSection":["2008","6\/2008","VBA und Programmiertechniken"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/access-im-unternehmen.de\/Arrays_Collections_und_Dictionarys\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/access-im-unternehmen.de\/Arrays_Collections_und_Dictionarys\/","url":"https:\/\/access-im-unternehmen.de\/Arrays_Collections_und_Dictionarys\/","name":"Arrays, Collections und Dictionarys - Access im Unternehmen","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Arrays_Collections_und_Dictionarys\/#primaryimage"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Arrays_Collections_und_Dictionarys\/#primaryimage"},"thumbnailUrl":"http:\/\/vg05.met.vgwort.de\/na\/a17f2f39796f4e0c89e4d4a57aaede41","datePublished":"2021-02-11T21:23:59+00:00","breadcrumb":{"@id":"https:\/\/access-im-unternehmen.de\/Arrays_Collections_und_Dictionarys\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/access-im-unternehmen.de\/Arrays_Collections_und_Dictionarys\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/Arrays_Collections_und_Dictionarys\/#primaryimage","url":"http:\/\/vg05.met.vgwort.de\/na\/a17f2f39796f4e0c89e4d4a57aaede41","contentUrl":"http:\/\/vg05.met.vgwort.de\/na\/a17f2f39796f4e0c89e4d4a57aaede41"},{"@type":"BreadcrumbList","@id":"https:\/\/access-im-unternehmen.de\/Arrays_Collections_und_Dictionarys\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/access-im-unternehmen.de\/"},{"@type":"ListItem","position":2,"name":"Arrays, Collections und Dictionarys"}]},{"@type":"WebSite","@id":"https:\/\/access-im-unternehmen.de\/#website","url":"https:\/\/access-im-unternehmen.de\/","name":"Access im Unternehmen","description":"Das Magazin f\u00fcr Datenbankentwickler auf Basis von Microsoft Access","publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/access-im-unternehmen.de\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"de"},{"@type":"Organization","@id":"https:\/\/access-im-unternehmen.de\/#organization","name":"Andr\u00e9 Minhorst Verlag","url":"https:\/\/access-im-unternehmen.de\/","logo":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/logo\/image\/","url":"https:\/\/access-im-unternehmen.de\/wp-content\/uploads\/2019\/09\/aiu_wp.png","contentUrl":"https:\/\/access-im-unternehmen.de\/wp-content\/uploads\/2019\/09\/aiu_wp.png","width":370,"height":111,"caption":"Andr\u00e9 Minhorst Verlag"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f","name":"Andr\u00e9 Minhorst","image":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","caption":"Andr\u00e9 Minhorst"}}]}},"_links":{"self":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55000640","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/comments?post=55000640"}],"version-history":[{"count":0,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55000640\/revisions"}],"wp:attachment":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/media?parent=55000640"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/categories?post=55000640"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/tags?post=55000640"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}