2017-01-10 3 views
0

Ich hatte Probleme mit komplizierterem Code und ich verstand Wörterbücher noch nicht vollständig, also baute ich ein wirklich einfaches, einfaches Testblatt, um herauszufinden, wie sie funktionieren. Nur drei Einträge, die "first", "do" und "alpha" lesen, über den Spalten a-c (Ziel war es schließlich sicherzustellen, dass ich verschachtelte Wörterbücher verstanden habe, obwohl diese Frage nicht auf diese Frage eingeht).Warum können Wörterbuchschlüssel nicht zu Zellen gemacht werden?

Der Code war:

Sub testing() 

Dim dict As New Scripting.Dictionary 

dict.Add Key:=Cells(1, 1), Item:=Cells(1, 2) 
MsgBox dict(Cells(1, 1)) 

End Sub 

Dies funktionierte nicht. Aber als ich eine Variable temp = Cells(1, 1) hinzugefügt und diese anstelle von Cells(1, 1) verwendet habe, wo immer es auftauchte, funktionierte es.

Warum kann der Schlüssel keine Zelle sein? Kann jemand mir helfen, zu verstehen, was der Unterschied zwischen

dict.Add Key:=Cells(1, 1), Item:=(1, 2) 

und

temp = Cells(1, 1) 

dict.Add Key:=temp, Item:=(1, 2) 

ist? Der Gegenstand kann eine Zelle sein, nur nicht der Schlüssel?

+1

Setzen Sie '.value' am Ende der beiden Zellen (1,1) –

+0

ja, Wörterbuch ist sehr entgegenkommend beim Speichern der Daten. Ohne 'Wert' speichert es das Bereichsobjekt. – cyboashu

+0

Oh! Ich hatte von dieser Funktion noch nichts gehört. Also gibt '.value' eine Zeichenfolge von dem zurück, was in der Sache '' value' 'angehängt ist? –

Antwort

0

Sie können Objekte verwenden, da beide Schlüssel und Werte (einschließlich der durch .Cells zurückBereiche), wie dieser Code demonstriert:

Public Sub Example() 
    Dim dict As New Scripting.Dictionary 
    dict.Add Sheet1.Cells(1, 1), Sheet1.Cells(1, 1) 
    dict.Add Sheet1.Cells(1, 2), Sheet1.Cells(1, 1) 

    Dim x As Variant 
    For Each x In dict.Keys 
     Debug.Print TypeName(x) 'Prints Range 
    Next 

    For Each x In dict.Items 
     Debug.Print TypeName(x) 'Prints Range 
    Next 
End Sub 

In der Tat, Ihr Code oben „funktioniert“ - du bist nur nicht sehen, was Sie in Ihrem MsgBox erwarten. Auf dieser Codezeile ...

MsgBox dict(Cells(1, 1)) 

... der erste Parameter MsgBox ist ein Variant, aber es muss letztlich in der Lage sein, ein String anzuzeigen. Wenn es ein Objekt als Parameter empfängt, ruft es seinen Standardmember auf (.Value in diesem Fall). Das heißt, Ihr Code entspricht:

MsgBox dict(Cells(1, 1).Value) 

Für Ihr zweites Beispiel mit temp, ich gehe davon aus, dass es entweder nicht deklariert (und implizit Variant) oder ein anderer stark typisierte Wert. In diesem Fall wird die Zuordnung Aufruf implizit das Standardelement von Cells(1, 1), so dass Ihre Zuordnung zu äquivalent ist:

Dim temp As Variant 
temp = Cells(1, 1).Value 
dict.Add temp, Cells(1, 2) '<--- temp is whatever the type of Cells(1, 1).Value is. 

Wenn Temp als Range deklariert wird (oder Object), funktioniert es genau das gleiche wie in Sub Example() oben:

Dim temp As Range 
Set temp = Cells(1, 1) 
dict.Add temp, Cells(1, 2) '<--- temp is a Range. 

beachten Sie, dass einzigartige Zell Werte als Objekte einzigartige Zelle unterschiedlich sind:

Public Sub Example2() 
    Dim dict As New Scripting.Dictionary 
    Cells(1, 1).Value = "Foo" 
    Cells(1, 2).Value = "Foo" 

    'This is fine - the keys are unique cell references: 
    dict.Add Cells(1, 1), Empty 
    dict.Add Cells(1, 2), Empty '<-- No runtime error 

    Set dict = New Scripting.Dictionary 

    'This is an error - the keys are identical values: 
    dict.Add Cells(1, 1).Value, Empty 
    dict.Add Cells(1, 2).Value, Empty '<-- Runtime error 457, key already exists. 
End Sub 
+0

Also wenn ich das richtig verstehe - weil ich den Schlüssel als einen Datentyp beim Speichern im Dictionary (Zelle) verwendet habe, aber standardmäßig einen anderen Datentyp hat, wenn msgbox aufgerufen wird (Variante), wird er nicht angezeigt, weil obwohl der Text identisch ist, ist der Datentyp anders? Und deshalb war die Verwendung von temp eine Art unbeabsichtigte Brücke darüber, indem es unwissentlich im Wörterbuch als ein anderer Datentyp gespeichert wurde, zufälligerweise die gleiche msgbox standardmäßig? –

+0

@GrahamPerry - Nein. Es ist der gleiche Typ ('Range'). Sie können nicht 'MsgBox' ein Objekt, so dass es seinen Standardmember -' .Value' aufruft. Das Zuweisen von 'temp' hat genau das Gleiche bewirkt, weil Sie' Set' nicht davor verwendet haben. Zuweisungen zu 'Variant's ohne das' Set'-Schlüsselwort sind Wertzuweisungen, keine Referenzzuweisungen. – Comintern

+0

Ich bin ... mehr verwirrt, denke ich. 'Cells (1, 1)' ist ein Bereichsobjekt. temp ist eine (n nicht deklarierte) Variante, also setzt sie sich implizit gleich 'Cells (1, 1) .Value '. Und der Bereich ist ein Objekt (?), Also versucht msgbox das zu beheben, indem er '.value' hinzufügt, was zu 'Cells (1, 1) .Value' führt. Ich meine, das ist eindeutig nicht der Fall, denn sonst würde es funktionieren, denn das ist das gleiche Ergebnis, aber ... –

Verwandte Themen