Anzeige
Anzeige
HERBERS
Excel-Forum (Archiv)
20+ Jahre Excel-Kompetenz: Von Anwendern, für Anwender
Inhaltsverzeichnis

Schreibzugriff auf Array in Dictionary Object-Item

Forumthread: Schreibzugriff auf Array in Dictionary Object-Item

Schreibzugriff auf Array in Dictionary Object-Item
Martin
Hallo liebe Excelfreunde,
es ist möglich im Dictionary Object auch Arrays als Items abzulegen:

Dim MyDic As Object
Set MyDic = CreateObject("Scripting.Dictionary")
MyDic.Add "Obst", Array("Äpfel", "Birnen", "Kirschen", "Weintrauben", "Johannisbeeren")

Die einzelnen Array-Werte können auch einfach abgerufen werden:

MsgBox MyDic.Item("Obst")(4) 'Liefert Johannisbeeren

Eine direkte Änderung der Array-Werte ist mir jedoch nicht gelungen:
    MyDic.Item("Obst")(4) = "Blaubeeren" 'Ersetzen der "Johannesbeeren" durch "Blaubeeren"
MsgBox MyDic.Item("Obst")(4) 'Liefert weiterhin Johannisbeeren
...der Code wird zwar ohne Fehlermeldung durchlaufen, bewirkt aber keine Änderung.
Es ist natürlich möglich das Array-Item des Dictionary Objects in ein neues Array auszulesen, dieses zu ändern und das alte Item zu überschreiben. Aber ist dieser Umweg wirklich notwendig? Kann mir jemand sagen ob/wie ich direkt im Dictionary Object einzelne Array-Werte ändern kann?
Viele Grüße
Martin
Anzeige
AW: Schreibzugriff auf Array in Dictionary Object-Item
18.07.2011 08:48:04
Beverly
Hi Martin,
vielleicht eine Möglichkeit:
Sub ArrDic()
Dim dicObjekt As Object
Dim Obst, Gemüse
Set dicObjekt = CreateObject("Scripting.Dictionary")
dicObjekt.Add "Obst", Array("Birnen", "Äpfel", "Kirschen", "Bananen")
dicObjekt.Add "Gemüse", Array("Tomaten", "Kohlrabi", "Kartoffeln", "Gurken")
MsgBox dicObjekt("Gemüse")(3)
dicObjekt.Remove ("Gemüse")
dicObjekt.Add "Gemüse", Array("Tomaten", "Kohlrabi", "Kartoffeln", "Zwiebeln")
MsgBox dicObjekt("Gemüse")(3)
End Sub



Anzeige
AW: Schreibzugriff auf Array in Dictionary Object-Item
18.07.2011 08:59:31
Martin
Hallo Beverly,
vielen lieben Dank für deinen Vorschlag. Im Grunde ähnelt dein Vorschlag auch der von mir genannten Alternative:
Sub Dic()
Dim MyDic As Object
Set MyDic = CreateObject("Scripting.Dictionary")
MyDic.Add "Obst", Array("Äpfel", "Birnen", "Kirschen", "Weintrauben", "Johannisbeeren")
Debug.Print MyDic.Item("Obst")(4) 'Liefert Johannisbeeren
Dim ArrTmp As Variant
ArrTmp = MyDic.Item("Obst")
ArrTmp(4) = "Blaubeeren"
MyDic.Item("Obst") = ArrTmp
Debug.Print MyDic.Item("Obst")(4) 'Liefert nun Blaubeeren
End Sub
... nur dass du den Key ganz löscht und neu schreibst. Es interessiert mich aber, ob es eine Möglichkeit gibt einzelne Array-Werte direkt (also ohne Umweg) im Dictionary Object ändern zu können. Scheinbar nicht, aber vielleicht mache ich auch etwas falsch?!
Viele liebe Grüße
Martin
Anzeige
AW: Schreibzugriff auf Array in Dictionary Object-Item
19.07.2011 00:17:43
Nepumuk
Hallo Martin,
hast die sie noch alle :-))
Anstatt dir eine eigene Klasse zu schreiben die alles so macht wie du willst, versuchst du eine zu vergewaltigen die für so etwas gar nicht entwickelt wurde. Ist ja wie einen Ferrari vor einen Pflug zu spannen.
Jetzt aber hopp, bei VBA gut muss so eine Klasse wie aus der Pistole geschossen kommen
Gruß
Nepumuk
Anzeige
AW: Schreibzugriff auf Array in Dictionary Object-Item
19.07.2011 08:49:43
Martin
Hallo Nepumuk,
dann habe ich mein Level vermutlich zu hoch gewählt: Als "VBA bescheiden" schätze ich mich eigentlich auch nicht ein und Klassenprogrammierung hätte ich als "VBA-Profi" eingestuft. Ich muss zugeben, dass ich mich mit Klassen nicht auskenne, aber es gerne lernen würde. (Ich wusste nicht einmal, dass man das überhaupt mit Klassen regeln kann.) Da mir aufgefallen ist, dass Arrays im Gegensatz zum 'Dictionary Object' sehr langsam sind (zumindest das Erweitern mit "Redim Preserve") und ich auch den Zugriff über den Schüssel (ohne mit einer Schleife alle Einträge durchlaufen lassen zu müssen) als sehr angenehm empfinde, hatte ich mich für das 'Dictionary Object ' entschieden.
Nach deiner Antwort wäre ich dir sehr dankbar, wenn du mir demonstrieren würdest wie ich das über eine Klasse löse.
Viele Grüße
Martin
Anzeige
Klasse: Tröste dich, ...
19.07.2011 09:03:57
Rudi
Hallo,
... ich kann das auch nicht (oder nur sehr eingeschränkt)
Nepumuk ist eben Handwerker und ich nur Bastler.
zumindest das Erweitern mit "Redim Preserve")
dann stelle entweder vorher die Größe fest oder dimensioniere es zu groß und dann nur 1x Redim Preserve.
Gruß
Rudi
Anzeige
@Nepumuk: Bitte zeige die Klassenlösung mal
19.07.2011 09:19:07
Martin
Hallo Rudi,
danke für die Antwort. Eigentlich hätte ich selbst auf die Idee kommen müssen die Anzahl der Array-Werte über eine Long-Variable mitzuzählen und am Ende die Array-Größe mit "Redim Preserve" über diese Variable entsprechend zu reduzieren. Gut, damit habe ich eine mögliche Alternative.
Nepumuk hat mich aber mit seiner Klassen-Lösung neugierig gemacht. Ich lasse die Frage offen in der Hoffnung, dass Nepumuk uns das mal vorstellt.
Viele Grüße
Martin
Anzeige
AW: zum Zeitvertreib ...
19.07.2011 23:03:59
Nepumuk
Hallo Jungs,
hat ein bisschen gedauert bis ich Zeit hatte. Also, hier etwas zum Spielen. Man könnte aus der Item-Methode noch die Default-Methode machen, dann würden die Ausdücke kürzer. Oder eine Enumerator einbauen, dann könnte man die Warengruppen und deren Artikel mit For Each durchlaufen.
' **********************************************************************
' Modul: Modul1 Typ: Allgemeines Modul
' **********************************************************************

Option Explicit


Public Sub test()
    
    Dim objWarengruppe As cls_Warengruppe
    Set objWarengruppe = New cls_Warengruppe
    
    Call objWarengruppe.Add("Obst", "Ananas", "Birne", "Banane", "Kirsche")
    
    MsgBox objWarengruppe.Item("Obst").Item(1).Artikel
    
    objWarengruppe.Item("Obst").Item("Ananas").Artikel = "Apfel"
    
    MsgBox objWarengruppe.Item("Obst").Item(1).Artikel
    
    Call objWarengruppe.Item("Obst").Add("Kiwi")
    
    MsgBox objWarengruppe.Item("Obst").Item(objWarengruppe.Item("Obst").Count).Artikel
    
    Call objWarengruppe.Add("Gemüse", "Korotte", "Gurke", "Rettich", "Rotkohl")
    
    MsgBox objWarengruppe.Item("Obst").Item(1).Artikel & "-" & _
        objWarengruppe.Item("Obst").Item(5).Artikel & "-" & _
        objWarengruppe.Item("Gemüse").Item(4).Artikel
    
    MsgBox objWarengruppe.Item("Gemüse").Count
    
    MsgBox objWarengruppe.Item("Gemüse").Item(2).Artikel
    
    Call objWarengruppe.Item("Gemüse").Delete("Gurke")
    
    MsgBox objWarengruppe.Item("Gemüse").Item(2).Artikel
    
    MsgBox objWarengruppe.Item("Gemüse").Count
    
    Set objWarengruppe = Nothing
    
End Sub

' **********************************************************************
' Modul: cls_Warengruppe Typ: Klassenmodul
' **********************************************************************

Option Explicit

Private mobjWarengruppe As Collection
Private mstrWarengruppe As String

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

Private Sub Class_Terminate()
    Set mobjWarengruppe = Nothing
End Sub

Friend Sub Add(strWarengruppe As String, ParamArray vntArtikel() As Variant)
    Dim lngIndex As Long
    Dim objArtikel As cls_Artikel
    Set objArtikel = New cls_Artikel
    For lngIndex = LBound(vntArtikel) To UBound(vntArtikel)
        Call objArtikel.Add(CStr(vntArtikel(lngIndex)))
    Next
    mobjWarengruppe.Add objArtikel, strWarengruppe
    Set objArtikel = Nothing
End Sub

Friend Function Item(vntIndex As Variant) As cls_Artikel
    Set Item = mobjWarengruppe(vntIndex)
End Function

' **********************************************************************
' Modul: cls_Artikel Typ: Klassenmodul
' **********************************************************************

Option Explicit

Private mobjArtikel As Collection
Private mstrArtikel As String

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

Private Sub Class_Terminate()
    Set mobjArtikel = Nothing
End Sub

Public Property Get Artikel() As String
    Artikel = mstrArtikel
End Property

Public Property Let Artikel(ByVal strArtikel As String)
    mstrArtikel = strArtikel
End Property

Public Sub Add(strArtikel As String)
    Dim objArtikel As cls_Artikel
    Set objArtikel = New cls_Artikel
    objArtikel.Artikel = strArtikel
    mobjArtikel.Add objArtikel, strArtikel
    Set objArtikel = Nothing
End Sub

Public Function Item(vntIndex As Variant) As cls_Artikel
    Set Item = mobjArtikel.Item(vntIndex)
End Function

Public Function Count() As Long
    Count = mobjArtikel.Count
End Function

Public Sub Delete(vntIndex As Variant)
    Call mobjArtikel.Remove(vntIndex)
End Sub

Gruß
Nepumuk
Anzeige
AW: zum Zeitvertreib ...
20.07.2011 08:11:07
Martin
Hallo Rudi, hallo Nepumuk,
vielen Dank für Eure Antworten. Ich habe mich gestern nach Informationen zur Thematik Klassen (Grundwissen) umgesehen. Ich muss zugeben, dass es mir zur Zeit noch sehr schwer fällt Nepumuks Klassencode und den Code aus der Beispieldatei von Rudis Link nachzuvollziehen, weil ich noch ein blutiger Anfänger bin und ganz am Anfang stehe. In jedem Fall hat Nepumuk mein Interesse an Klassen geweckt, jetzt muss ich mich in Ruhe damit auseinandersetzen. Nochmals vielen Dank euch beiden!
Viele Grüße
Martin
Anzeige
AW: Schreibzugriff auf Array in Dictionary Object-Item
18.07.2011 09:20:47
bst
Morgen,
ist mir auch schon aufgefallen.
Ich vermute einfach mal dass der Zugriff auf myDic("Obst") eine Kopie des Arrays erzeugt und diese zurück liefert. Damit dürfte nur der Umweg über das Auslesen/Zurückschreiben des gesamten Arrays möglich sein.
cu, Bernd
AW: Schreibzugriff auf Array in Dictionary Object-Item
18.07.2011 09:47:05
Martin
Hallo Bernd,
schade, dann mache ich scheinbar doch nichts falsch. Ich hatte schon die ähnliche Vermutung, dass ein Item im Dictionary Object nur vollständig gesetzt werden kann. Ich finde es ungüstig, dass ein versuchter Schreibzugriff
MyDic.Item("Obst")(4) = "Blaubeeren"
zu keiner Fehlermeldung (etwa "Kein Schreibzugriff Datentyp Variant") führt. Ich lasse die Frage mal offen, vielleicht hat doch noch jemand eine Lösung.
Viele Grüße
Martin
Anzeige
AW: Schreibzugriff auf Array in Dictionary Object-Item
18.07.2011 10:41:09
Rudi
Hallo,
Es ist natürlich möglich das Array-Item des Dictionary Objects in ein neues Array auszulesen, dieses zu ändern und das alte Item zu überschreiben.
Das mach ich auch so. Eine andere Möglichkeit habe ich noch nicht gefunden.
Gruß
Rudi
;
Anzeige

Infobox / Tutorial

Schreibzugriff auf Array in Dictionary Object-Item


Schritt-für-Schritt-Anleitung

  1. Erstellen des Dictionary-Objekts: Du kannst ein Dictionary-Objekt in VBA mit der Funktion CreateObject("Scripting.Dictionary") erstellen. Dies ermöglicht eine einfache Handhabung von Schlüssel-Wert-Paaren.

    Dim MyDic As Object
    Set MyDic = CreateObject("Scripting.Dictionary")
  2. Hinzufügen von Arrays als Items: Du kannst Arrays als Items in deinem Dictionary speichern. Zum Beispiel:

    MyDic.Add "Obst", Array("Äpfel", "Birnen", "Kirschen", "Weintrauben", "Johannisbeeren")
  3. Zugriff auf Array-Werte: Um auf die Werte eines Arrays im Dictionary zuzugreifen, verwende den Schlüssel und den Index:

    MsgBox MyDic.Item("Obst")(4) ' Liefert Johannisbeeren
  4. Ändern von Array-Werten: Leider ist es nicht möglich, Array-Werte direkt zu ändern. Du musst das gesamte Array auslesen, ändern und dann wieder in das Dictionary zurückschreiben.


Häufige Fehler und Lösungen

  • Fehler beim Zugriff auf Array-Werte: Wenn du versuchst, einen Wert direkt zu ändern, wie in diesem Beispiel:

    MyDic.Item("Obst")(4) = "Blaubeeren"

    Du erhältst keine Fehlermeldung, aber der Wert wird nicht geändert. Dies liegt daran, dass MyDic.Item("Obst") eine Kopie des Arrays zurückgibt.

  • Lösung: Um den Wert zu ändern, musst du das Array in eine Variable kopieren, den Wert ändern und dann das Array zurück ins Dictionary schreiben:

    Dim ArrTmp As Variant
    ArrTmp = MyDic.Item("Obst")
    ArrTmp(4) = "Blaubeeren"
    MyDic.Item("Obst") = ArrTmp

Alternative Methoden

  • Verwendung von Klassen: Eine alternative Methode ist die Verwendung von Klassen. Du kannst eine benutzerdefinierte Klasse erstellen, um Array-Werte zu verwalten. Dies ermöglicht dir eine flexiblere Handhabung ohne die Einschränkungen des Dictionary Objects.

  • Ein Beispiel für eine Klassenimplementierung:

    Public Sub test()
       Dim objWarengruppe As cls_Warengruppe
       Set objWarengruppe = New cls_Warengruppe
       ' Weitere Implementierungen hier...
    End Sub

Praktische Beispiele

  • Beispiel zur Verwendung des Dictionary:

    Dim dicObjekt As Object
    Set dicObjekt = CreateObject("Scripting.Dictionary")
    dicObjekt.Add "Obst", Array("Birnen", "Äpfel", "Kirschen", "Bananen")
    MsgBox dicObjekt("Obst")(1) ' Liefert Äpfel
  • Löschen und Hinzufügen von Werten:

    dicObjekt.Remove ("Obst")
    dicObjekt.Add "Obst", Array("Ananas", "Mango")
    MsgBox dicObjekt("Obst")(0) ' Liefert Ananas

Tipps für Profis

  • Vermeide unnötige Kopien: Da der Zugriff auf ein Array im Dictionary eine Kopie erstellt, sei vorsichtig, um unnötige Speicherverwendungen zu vermeiden.

  • Nutze die Keys-Methode: Du kannst die Methode Keys verwenden, um alle Schlüssel im Dictionary zu erhalten und diese in ein Array zu konvertieren:

    Dim keysArray As Variant
    keysArray = MyDic.Keys

FAQ: Häufige Fragen

1. Kann ich ein Array direkt im Dictionary ändern?
Nein, du kannst ein Array nicht direkt im Dictionary ändern. Du musst es zuerst auslesen, ändern und dann wieder ins Dictionary schreiben.

2. Wie kann ich ein Dictionary in Excel VBA erstellen?
Du kannst ein Dictionary in Excel VBA mit CreateObject("Scripting.Dictionary") erstellen. Dies ist der Standardweg, um ein Dictionary-Objekt in VBA zu initialisieren.

3. Gibt es eine Möglichkeit, mehrere Arrays in einem Dictionary zu speichern?
Ja, du kannst mehrere Arrays als Items im Dictionary speichern, indem du verschiedene Schlüssel verwendest.

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige