VB and VBA Users Source Code: Overview of the scripting dictionary object
[
Home
|
Contents
|
Search
|
Reply
| Previous | Next ]
VB/VBA Source Code
Overview of the scripting dictionary object
By:
Peter Mackay
Email (spam proof):
Email the originator of this post
Date:
Wednesday, May 14, 2003
Hits:
7505
Category:
Visual Basic General
Article:
The Dictionary object (require a reference to scrrun.dll) Visual Basic has two main method for storing collection: 1. The array type (COM type SAFEARRAY) 2. VBA.Collection collection type. The array has the benefit of quick access to individual items, but suffers from slow addition and remove operations because the entire array has to be reallocated and the contents copied. The Collection type boasts a much speedier dynamic addition and removal, but suffers from a number of limitations. The Scripting runtime module, give you a third option call the Dictionary object. This is similiar to a collection offering fast iteration and add/remove operations. Infact the Dictionary object works in much the same way as a collection, but has a richer interface and a couple of key changes. Among the welcomed improvements of the Dictionary over the Collection type are: 1. You can use any value for keys, including numbers. Only requirement is that the key value can be contained in a variant. 2. The Dictionary object's Item member is a read-write property, not a method. 3. The Dictionary object has an Exists method to allow you to check if a key has already been used. A collection (in this context; the Collection and Dictionary types) is like a bag of things: each object in the bag has a tag that identifies the object. In collection syntax the Item is the object and the key represents the tag. A real-world example could be an encyclopedia or a list of order entries (items) with each order entry identified by an order ID (key). With the Dictionary type you can store any Variant-compatible datatype. You can also use any Variant-compatible type for a key. Use a Dictionary when you can't know at design-time how many items you need to store. The members of the Dictionary object are: Method (m) / Property (p) HelpString Add (m) Add a new key and item to the dictionary CompareMode (p) Set or get the string comparison method Count (p) (read-only) Get the number of items in the dictionary Exists (m) Determine if a given key is in the dictionary Item (default) (p) Set or get the item for a given key Items (m) Get an array containing all items in the dictionary Key (p) (write-only) Change a key to a different key Keys (m) Get an array containing all keys in the dictionary Remove (p) Remove a given key from the dictionary RemoveAll (m) Remove all information from the dictionary Adding items Use the Add method for adding items. The code below instantiates a new Dictionary object and adds the names of three cartoon characters using a String key for the first, an Integer key for the second and a Single key for the last item: Dim Dict As Dictionary Set Dict = New Dictionary Dict.Add "MyKey", "Goofy" Dict.Add 1, "Donald Duck" Dict.Add 0.223332, "Uncle Scrooge" You can add as many copies of the same item as you like, but you cannot use the same key more than once, or you'll get a run-time error. You can also add items with the Item property, the default member, like this: Dict("MyKey") = "Goofy" Dict(1) = "Donald Duck" Dict(0.223332) = "Uncle Scrooge" The result of this code is the same as for the example using the Add method. In contrast to the Add method, the Item Let property will not raise an error if you try to add an item with a key that is already present in the collection. The Item Let property works like this: If the key is not found, the item/key pair is added, otherwise, the item found at key is replaced with the new item assigned. Removing items You can remove individual items from the dictionary with the Remove method. You specify which item to remove with the Key parameter. An error is raised if no such key is found in the Dictionary. You can empty the Dictionary completely by using the RemoveAll method. Retrieving items Individual items are retrieved from the dictionary with the Item Get property: Dim ReturnItem As Variant Dict("key1") = 1 Dict("key2") = Form1 ReturnItem = Dict("key1") Set ReturnItem = Dict("key2") The above example adds two items to the 'Dict' dictionary object; a number and a reference to Form1, using string keys. The same items are then retrieved into the Variant ReturnItem variable. Note that you have to use the Set keyword when you retrieve an object reference and store it in a variable. You might also need to retrieve all items from the dictionary in one go. If so, use the Items method. The method copies all items to a 0-based variant array of variants. More on this under "Iterating items". The Key property The Key property is a rarity: it is write-only. That is probably because it doesn't make a lot of sense to make it read-write, because you'd have to specify the key value as a parameter, only to get the same value returned. The purpose of the Key property Let is to allow you to change the key used for an item without affecting the item. This is yet another improvement over the VBA.Collection, where, to achieve the same result, you'd have to first remove the item and then add it back again with the new key. The syntax for the Key property is: Dict.Key(OldKey) = NewKey Iterating items Because you can use numbers for keys, you cannot use a For...To...Next loop to iterate through the collection. This is different from the VBA.Collection, where the item method parameter would be evaluated as a key when you passed a string, but as an index value if you passed an integer. Now that you can use numbers for keys there is no way the Dictionary class could know whether to interpret a numeric parameter as a key or as an index. There are three ways to iterate through all or parts of the dictionary: The For...Each...Next method: Dim itm As Variant For Each itm In Dict Debug.Print itm Next The code loops through the entire collection and outputs the item values to the immediate window. One disadvantage of this syntax is that it always starts with the first item in the collection and then goes through the whole collection, unless you exit the loop prematurely with an Exit For statement. Using the Keys method: You can use the Keys method to retrieve an array copy of all keys in the dictionary and then use the Item property to retrieve individual items inside a For...To...Next loop: Dim keys As Variant keys = Dict.keys Dim counter As Integer For counter = 3 To 6 Debug.Print Dict(keys(counter)) Next The code prints items with index values 3 to 6. Using the Items method: If you don't care about the actual key values you might as well go straight for the items. You can use the Items method to retrieve an array copy of all items in the dictionary and then use the Item property to retrieve individual items inside a For...To...Next loop: Dim itms As Variant itms = Dict.Items Dim counter As Integer For counter = 3 To 6 Debug.Print itms(counter) Next Choosing which iteration method to use depends entirely on what you want to do and what information is needed to do so. If you're going to examine all items, use the first method. If you need to examine the key values, use the second method. Otherwise, use the third method. The Exists method The Exists method is a very valuable "innovation" in the Dictionary object. Use it to check if a given key is already in use in the dictionary. With the VBA.Collection the absence of an equivalent method let to awkward code because attempts to add a an item using a pre-existing key would generate a runtime error. It still does (and it should), but now at least, you can check first with the Exists method. The CompareMode property Although the CompareMode property is read-write, it is read-only once you've added items to the dictionary. You'll get a runtime error if you attempt to set the property while the dictionary is in use. The CompareMode property determines how the Dictionary class performs comparisons on String keys: If the CompareMode is TextCompare (1) the comparison is case-insensitive, while it is case-sensitive if the CompareMode is BinaryCompare (0). Since the dictionary is an un-ordered collection you might wonder why the Dictionary needs to perform string comparisons. The Dictionary does not do sorting on keys, but needs to compare keys to determine if it should raise an error or not when you use the Add method. An example: Dict.CompareMode = TextCompare Dict.Add "Greeting", "Hello" Dict.Add "greeting", "Goodbye" The last line generates a runtime error 457, but wouldn't if the CompareMode were BinaryCompare. Remember that adding items with the Item property will not generate errors in any case - see under 'Adding items'. General use The Dictionary class is not very friendly when it comes to error handling. I've noted two examples of this: The information you get back when an error is raised is not always very informative. For example if you try to Remove an item specifying a key unknown to the dictionary, what you get back is: "Run-time error 32811 - Method 'Remove' of object 'IDictionary' failed". This is hardly what you'd call "rich error information". Attempting to retrieve an item with the Item Get property, specifying a key unknown to the dictionary key does not even generate an error. Instead, you're just returned an empty variant. I regard this as a bug. Unlike the built-in array, the Dictionary collection is not type-specific; you can toss any variable at a Dictionary object as long as it can be contained in a Variant. Therefore, to use the Dictionary in an object model you'll probably want to use it as base class for your own specific type-safe collection class. For example if you're developing an e-mail application you might need a collection of objects of the class CMailMessage. Make your own CMailMessages class in which you mimic the interface of the Dictionary class, delegating to a private Dictionary object.
Terms and Conditions
Support this site
Download a trial version of the Excel Workbook Rebuilder