Microsoft Excel

Herbers Excel/VBA-Archiv

Informationen und Beispiele zum Thema MsgBox
BildScreenshot zu MsgBox MsgBox-Seite mit Beispielarbeitsmappe aufrufen

Schreibzugriff auf Array in Dictionary Object-Item | Herbers Excel-Forum


Betrifft: Schreibzugriff auf Array in Dictionary Object-Item von: Martin
Geschrieben am: 18.07.2011 08:21:32

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

  

Betrifft: AW: Schreibzugriff auf Array in Dictionary Object-Item von: Beverly
Geschrieben am: 18.07.2011 08:48:04

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


GrußformelBeverly's Excel - Inn


  

Betrifft: AW: Schreibzugriff auf Array in Dictionary Object-Item von: Martin
Geschrieben am: 18.07.2011 08:59:31

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


  

Betrifft: AW: Schreibzugriff auf Array in Dictionary Object-Item von: Nepumuk
Geschrieben am: 19.07.2011 00:17:43

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


  

Betrifft: AW: Schreibzugriff auf Array in Dictionary Object-Item von: Martin
Geschrieben am: 19.07.2011 08:49:43

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


  

Betrifft: Klasse: Tröste dich, ... von: Rudi Maintaire
Geschrieben am: 19.07.2011 09:03:57

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


  

Betrifft: @Nepumuk: Bitte zeige die Klassenlösung mal von: Martin
Geschrieben am: 19.07.2011 09:19:07

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


  

Betrifft: zum Zeitvertreib ... von: Rudi Maintaire
Geschrieben am: 19.07.2011 22:09:44

Hallo,
.... bis Nepumuk sich wieder meldet, vielleicht das mal studieren:
http://www.office-loesung.de/ftopic171146_0_0_asc.php

Gruß
Rudi


  

Betrifft: AW: zum Zeitvertreib ... von: Nepumuk
Geschrieben am: 19.07.2011 23:03:59

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


  

Betrifft: AW: zum Zeitvertreib ... von: Martin
Geschrieben am: 20.07.2011 08:11:07

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


  

Betrifft: AW: Schreibzugriff auf Array in Dictionary Object-Item von: bst
Geschrieben am: 18.07.2011 09:20:47

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


  

Betrifft: AW: Schreibzugriff auf Array in Dictionary Object-Item von: Martin
Geschrieben am: 18.07.2011 09:47:05

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


  

Betrifft: AW: Schreibzugriff auf Array in Dictionary Object-Item von: Rudi Maintaire
Geschrieben am: 18.07.2011 10:41:09

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