2016-06-08 15 views
2

Ich versuche zu entscheiden, ob Excel VBA Collection oder Dictionary für mein Projekt zu verwenden. Aus verschiedenen Gründen lehne ich mich dem Wörterbuch zu, aber ich lese, dass bei Verwendung einer For.. Each-Schleife zum Abrufen von Wörterbuchelementen oder beim Lesen von Elementen aus dem Wörterbuch Items() -Array die Reihenfolge des Abrufs möglicherweise nicht der Reihenfolge entspricht, in der Elemente hinzugefügt wurden. Dies wäre ein ernsthaftes Problem für meine Anwendung, daher habe ich viele Testfälle ausprobiert, um zu beweisen, dass diese Fehlordnung tatsächlich auftritt. Bisher war es mir nicht möglich, ein Szenario zu erstellen, in dem dies geschieht, einschließlich des Hinzufügens und Entfernens von Elementen in zufälliger Reihenfolge.Beweisen Sie, dass Excel VBA Scripting.Dictionary nicht die Reihenfolge der Artikeleinfügung erhalten

Kann jemand ein Beispiel angeben, das beweist, dass die Abrufreihenfolge nicht der Reihenfolge der Einfügung für das Excel VBA Scripting.Dictionary entspricht?

+0

Wo liest du das? Ich würde mit der übermäßigen Anzahl von Posts online darüber nachdenken, wie man ein Wörterbuch oder eine Sammlung sortiert, dass die Sortierreihenfolge beibehalten wird, ansonsten sollte man sich darum kümmern, sie zu sortieren. Es scheint auch unvernünftig, dass die Reihenfolge durch irgendeine mysteriöse Aktivität geändert wird, die auf dem Wörterbuchobjekt passiert. – JNevill

+0

Danke für Ihre Antwort, aber ich sortiere keine Artikel. Ich möchte einfach wissen, dass, wenn ich die Elemente 1, 2, 3, 4 (in dieser Reihenfolge) hinzufüge, dann lese die Elemente in einem For .. Jede Schleife, ich bekomme nicht 1, 4, 3, 2. – JohnM

+0

Das ist mein Punkt aber. Wenn so viele Leute sich die Mühe gemacht haben, Dictionary-Sortierlogik zu schreiben, dann macht es Sinn, dass eine Wörterbuchreihenfolge beibehalten wird. Sonst wäre die Sortierlogik sinnlos. Ich bin bei dir. Ich glaube nicht, dass ein Wörterbuch seine Artikel beliebig nachbestellen kann. – JNevill

Antwort

2

Niemand kann ein Beispiel für ein Scripting.Dictionary Objekt bereitstellen, das Schlüssel/Elemente in einer anderen Reihenfolge zurückgibt, als sie hinzugefügt wurden, weil ein Scripting.Dictionary dies nicht tut. Noch nie. Wenn Sie die folgenden Schlüssel-/Elementpaare in einer progressiven Reihenfolge hinzufügen, werden sie auf diese Weise zurückgegeben.

Sie könnten sich auf die Kurzschreibmethode zum Hinzufügen von Schlüsseln beziehen, ohne zu überprüfen, ob sie existieren. Wenn Sie versuchen, .Add einen Schlüssel, der Fehler 457 vorhanden ist, wird ausgelöst. Wenn Sie jedoch einfach Keys und Items in das Wörterbuch schreiben, wird ein neuer Schlüssel und ein neues Element erstellt, wenn der Schlüssel nicht existiert, aber wenn der Schlüssel vorhanden ist, bleibt der Schlüssel gleich und das Element wird überschrieben.

key item 
1 A 
2 B 
3 C 
4 D 
2 E 

'enumerate by key 
Dim dict As Object 
Set dict = CreateObject("Scripting.Dictionary") 

dict.Item(1) = "A" 
dict.Item(2) = "B" 
dict.Item(3) = "C" 
dict.Item(4) = "D" 
dict.Item(2) = "E"  'the second entry's item is overwritten 

Dim k As Variant 
For Each k In dict.Keys 
    Debug.Print k & " - " & dict.Item(k) 
Next k 

Die Überschreibverfahren ist ein wenig schneller als die Überprüfung, ob ein Schlüssel .Exists aber das Verhalten verstanden werden sollte. Ich habe das Überschreiben verwendet, um absichtlich das letzte Element für einen beliebigen Schlüssel in einer Liste mit doppelten Schlüsseln abzurufen, aber das war ein Sonderfall. Beachten Sie, dass die .Key nicht außerhalb der ursprünglichen Reihenfolge ist; Es hat nur seine .Item mit der späteren ersetzt.

Wenn Sie die Microsoft Scripting Runtime-Referenzbibliothek hinzugefügt haben, können Sie Early Binding in Ihrer Variablendeklaration verwenden. Dies hat den Vorteil, dass ein etwas schnelleres Wörterbuchobjekt erstellt und andere Methoden der indizierten Enumeration verfügbar gemacht werden.

Dim dict As New Scripting.Dictionary 

'enumerate by index position (zero-based index) 
Dim i As Long 
For i = 0 To dict.Count - 1 
    Debug.Print dict.Keys(i) & " - " & dict.Items(i) 
Next i 

'enumerate as elements of an array 
Dim a As Long 
For a = LBound(dict.Keys) To UBound(dict.Keys) 
    Debug.Print dict.Keys(a) & " - " & dict.Items(a) 
Next a 

FWIW, habe ich diese indizierte Aufzählung unzuverlässig, wenn das Wörterbuch der .Count eine signierte ganze Zahl (32.767) übersteigt.

Schließlich können Schlüssel/Element-Paare einzeln oder alle gleichzeitig entfernt werden.

dict.Remove 2        'remove by key 

dict.Remove dict.Keys(0)     'remove first key/item by index position 
dict.Remove dict.Keys(UBound(dict.Keys)) 'remove last key/item by index position 

dict.RemoveAll        'remove all 
+0

Vielen Dank für Ihre Informationen - Ich bin gespannt, was Sie mit der "indizierten Enumeration unzuverlässig, wenn das Wörterbuch .Count eine vorzeichenbehaftete ganze Zahl (32.767)" bedeutet? – JohnM

+0

Ich habe die Wörterbuchdokumentation neu geschrieben und 'unzuverlässige Ergebnisse' mit einer großen Anzahl von Wörterbuchschlüsseln entdeckt. Bis ich die Tests unter einer größeren Anzahl von Bedingungen abgeschlossen habe, kann ich das Problem nicht genau bestimmen, daher habe ich den Begriff "unzuverlässig" verwendet. – Jeeped

+0

Können Sie einen Fall angeben, den Sie für unzuverlässig hielten? – JohnM

Verwandte Themen