Featured

QTP 10 not Recognizing Oracle Forms Obje

Bidun Meduza shared on our Facebook page a problem and solution that I thought might be useful to you too. Problem He had a situation where QTP 10 was unable to recognize objects of Oracle Forms. Th

Read More
QTP 10 not Recognizing Oracle Forms Objects

New Navigation Menus

In order to ease orientation through our vast knowledge archive, we have added the following navigation menus: First Steps Scripting QTP VBScript Tutorial Knowledge Articles (by levels of expertise) B

Read More
New Navigation Menus

Permalinks

We’ve changed the permalinks format, so if you have been experiencing some trouble with finding materials with the old links, then remove the YYYY/MM/ from the URL and you’d be fine. In ca

Read More
Permalinks

Advanced QTP on Android

A first version of AdvancedQTP for Android can be found here. Now you can take this perfect companion with you to keep updated on what’s new in our site.

Read More
Advanced QTP on Android

New Advanced QTP Features: Layout and FB

As you have most surely noticed, we’ve recently changed the site’s theme in order to enhance the overall user experience. As from today, you can also register and login seamlessly with you

Read More
New Advanced QTP Features: Layout and FB Integration

Complex Dictionary Usage

0
by on September 1, 2008 at 22:21

In this article we are about to see the efficiency of a dictionary when checking or retrieving values from a web-table, For this purpose we have the following table in our AUT.

image

This is the script that will parse the table and will upload the dictionary.

image

After running the script above, the solarExch dictionary loaded with 14 keys

image

Watching Dictionary.Keys array…

image

Each item is an object ( another Dictionary ) that represents a row in the table. Each row has 6 items. each item, is a key.

image

Watching the solarExch values for symbol “TSL”

image

And at last, if we want to check a specific value, we don’t have to remember the indexes, or write them.

we just retrieve the value from the embedded dictionary object

image

, ,

An Improved Dictionary Object

0
by on June 19, 2008 at 10:00

The Scripting.Dictionary object can be an extremely useful tool for storing and retrieving information. We’ve had a whole series of QTips covering it’s basic uses, as well as some advanced articles of using it as a reserved global dictionary, a parameter storage for generic functions (here and here), and more.

However, with all its power, the dictionary object has some inherent shortcomings – you can’t retrieve a value by its index (which can really be annoying when using it in loops), it will throw an error when trying to add an item with a duplicate key, and it lacks merging, importing and exporting abilities.

This article will show a step by step guide for building a new dictionary object, which will be more robust and flexible than the native Scripting.Dictionary. You might want to brush up your VBScript class knowledge before reading on.

Specifically, we’re going to write a wrapper – meaning, we’ll be using an inner scripting.dictionary object, and wrap a more sophisticated mechanism around it. Wrappers are very common in programming – they allow us to expand upon the work of others, and “stand on the shoulders of Giants”, sort of speak.

Wrappers almost never “breaks” the original object they’re wrapping. Meaning that every piece of code that worked with the original dictionary, should ideally work with our new dictionary wrapper. This means that we should keep all the object’s methods and properties names, and only expand with new ones, and new abilities to the existing ones.

So, let’s get this show on the road

Basic Interfaces

First, let’s define our basic class structure, with a private (hidden) variable holding a Scripting.Dictionary object. We’ll also insert initialization and termination event procedures for the object:

<span style="color: #0000ff;">Sub</span> Class_Initialize <span style="color: #008000;">\'Will fire automatically when create a new instance</span>
    <span style="color: #0000ff;">Set</span> oDic = CreateObject(<span style="color: #006080;">"Scripting.Dictionary"</span>)
<span style="color: #0000ff;">End</span> <span style="color: #0000ff;">Sub</span>

<span style="color: #0000ff;">Sub</span> Class_Terminate <span style="color: #008000;">\'Will fire automatically when an instance is destroyed</span>
    <span style="color: #0000ff;">Set</span> oDic = <span style="color: #0000ff;">Nothing</span>
<span style="color: #0000ff;">End</span> Sub

Next, we’ll add some simple public interfaces, which will allow the user to use the new dictionary like the regular native one. For example, we’ll need to add a .Count property to our new dictionary, but since there was nothing wrong with the old dictionary’s .Count property, we could immediately return the answer from our hidden inner dictionary.

<span style="color: #008000;">\'All these properties are read-only</span>
<span style="color: #008000;">\'This is why they only contain a Get block</span>

<span style="color: #0000ff;">Public</span> <span style="color: #0000ff;">Property</span> <span style="color: #0000ff;">Get</span> Count <span style="color: #008000;">\'Returns the number of items in our dictionary</span>
    Count = oDic.Count <span style="color: #008000;">\'The answer is the number of items in the inner dictionary</span>
<span style="color: #0000ff;">End</span> <span style="color: #0000ff;">Property</span>

<span style="color: #0000ff;">Public</span> <span style="color: #0000ff;">Property</span> <span style="color: #0000ff;">Get</span> Keys <span style="color: #008000;">\'Returns the dictionary keys (array)</span>
    Keys = oDic.Keys
<span style="color: #0000ff;">End</span> <span style="color: #0000ff;">Property</span>

<span style="color: #0000ff;">Public</span> <span style="color: #0000ff;">Property</span> <span style="color: #0000ff;">Get</span> Items <span style="color: #008000;">\'Returns the dictionary items (array)</span>
    Items = oDic.Items
<span style="color: #0000ff;">End</span> <span style="color: #0000ff;">Property</span>

<span style="color: #0000ff;">Public</span> <span style="color: #0000ff;">Property</span> <span style="color: #0000ff;">Get</span> Exists(Key) <span style="color: #008000;">\'Returns a True/False if the Key exists</span>
    Exists = oDic.Exists(Key)
<span style="color: #0000ff;">End</span> Property

As you can see, since these interfaces don’t require any additional tweaking and manipulations, they’re very direct and simple. The next interfaces won’t be so straightforward.

Modified Interfaces

We’ll begin with the .Remove method. The original dictionary object throws an error when trying to remove an item in a key which doesn’t exist. We’ll perform a simple patch – only remove the item if the key exists:

<span style="color: #0000ff;">Public</span> <span style="color: #0000ff;">Sub</span> Remove(Key)
    <span style="color: #0000ff;">If</span> oDic.Exists(Key) <span style="color: #0000ff;">Then</span> oDic.Remove(Key)
<span style="color: #0000ff;">End</span> Sub

Let’s continue with something a bit trickier – the .Add method, which adds a new item to our dictionary. The original method had an annoying “feature” – when adding an item with a key that already exists, the  script threw an error, instead of simply overriding the current item in that key. In our new method, we’ll do just that:

<span style="color: #0000ff;">Public</span> <span style="color: #0000ff;">Sub</span> Add(Key, Value)
    <span style="color: #0000ff;">If</span> oDic.Exists(Key) <span style="color: #0000ff;">Then</span>
        <span style="color: #008000;">\'We cannot simply add the item, we have to replace it</span>
        oDic.Item(Key) = Value
    <span style="color: #0000ff;">Else</span>
        <span style="color: #008000;">\'Here we can add the key as usual</span>
        oDic.Add Key, Value
    <span style="color: #0000ff;">End</span> <span style="color: #0000ff;">If</span>
<span style="color: #0000ff;">End</span> Sub

But wait, things aren’t so simple. Dictionaries can contain objects as items (even other dictionaries!), but in VBScript, assigning an object to a variable requires using the special keyword Set. So if the Value we’re trying to add in an object, we’ll have to execute Set oDic.Item(Key) = Value, not simply oDic.Item(Key) = Value. This will quickly turn into an impossible If structure, so let’s present a simpler alternative – if the value exists, we’ll remove it, and then add it as usual.

<span style="color: #0000ff;">Public</span> <span style="color: #0000ff;">Sub</span> Add(Key, Value)
    <span style="color: #0000ff;">Call</span> <span style="color: #0000ff;">Me</span>.Remove(Key)
    oDic.Add Key, Value
<span style="color: #0000ff;">End</span> Sub

Let’s take a second to see what we’ve done here. We want to remove the item only if the key already exists in our dictionary. But we’ve just created a .Remove method which does just that! So instead of recoding the algorithm, we reuse the code we’ve already written, and call our new and improved .Remove method. Once that’s taken care of, we can add the new key and value as usual.

And now the crown jewel: the .Item method. It will be quite complicated, we’ll have to distinguish between an “real” key, and a numeric key, as well as between returning a regular item and returning an object. First, let’s deal with the key issue:

<span style="color: #0000ff;">Public</span> <span style="color: #0000ff;">Function</span> Item(Key)
    <span style="color: #0000ff;">Dim</span> arrKeys <span style="color: #008000;">\'Will hold the inner dictionary keys</span>
    <span style="color: #0000ff;">Dim</span> sRealKey

    arrKeys = oDic.Keys

    <span style="color: #0000ff;">If</span> IsNumeric(Key) <span style="color: #0000ff;">Then</span>
        sRealKey = arrKeys(Key) <span style="color: #008000;">\'We have to translate the number to the corresponding key</span>
    <span style="color: #0000ff;">Else</span>
        sReakKey = Key <span style="color: #008000;">\'We can use the key as it is</span>
    <span style="color: #0000ff;">End</span> <span style="color: #0000ff;">If</span>

    Item = oDic.Item(sRealKey)

<span style="color: #0000ff;">End</span> Function

Notice that we’re ignoring a possible exception – what if we have a key named “1”? Our code will interpret it as a numeric index and not an actual key. We could build a workaround, but let’s keep things simple. We’ll let this one slide by and say we don’t allow any such keys.

Now let’s deal with the second problem – we got the key, what’s left is returning the value. Here’ we encounter the same problem we have in the .Add method – a simple item and an object item require different handling (the object item requires using the Set keyword). Unlike the .Add method, we’ll have to tackle this head-on:

<span style="color: #0000ff;">Public</span> <span style="color: #0000ff;">Function</span> Item(Key) <span style="color: #008000;">\'Returns an item, either by a key or an index</span>
    <span style="color: #0000ff;">Dim</span> arrKeys <span style="color: #008000;">\'Will hold the inner dictionary keys</span>
    <span style="color: #0000ff;">Dim</span> sRealKey <span style="color: #008000;">\'The actual key which holds the needed value</span>

    arrKeys = oDic.Keys

    <span style="color: #0000ff;">If</span> IsNumeric(Key) <span style="color: #0000ff;">Then</span>
        sRealKey = arrKeys(Key) <span style="color: #008000;">\'We have to translate the number to the corresponding key</span>
    <span style="color: #0000ff;">Else</span>
        sReakKey = Key <span style="color: #008000;">\'We can use the key as it is</span>
    <span style="color: #0000ff;">End</span> <span style="color: #0000ff;">If</span>

    <span style="color: #008000;">\'If the relevant item is an object, we\'ll have to use the Set keyword to retun it</span>
    <span style="color: #0000ff;">If</span> IsObject(oDic.Item(sRealKey)) <span style="color: #0000ff;">Then</span>
        <span style="color: #0000ff;">Set</span> Item = oDic.Item(sRealKey)
    <span style="color: #0000ff;">Else</span>
        Item = oDic.Item(sRealKey)
    <span style="color: #0000ff;">End</span> <span style="color: #0000ff;">If</span>

<span style="color: #0000ff;">End</span> Function

New Interfaces

The .Item method was the last of the original dictionary’s interfaces. After we’ve dealt with them, we can now create some new interfaces, adding new functionality and power to our dictionary.

The first new interface we’ll implement is .Key. It will return the key at a certain index. Simple, and very useful:

<span style="color: #0000ff;">Public</span> Funciton Key(iIndex)
    <span style="color: #0000ff;">Dim</span> arrKeys

    <span style="color: #0000ff;">If</span> iIndex > <span style="color: #0000ff;">Me</span>.Count -1 <span style="color: #0000ff;">Then</span> <span style="color: #0000ff;">Exit</span> <span style="color: #0000ff;">Function</span> <span style="color: #008000;">\'There is no such key</span>

    arrKeys = <span style="color: #0000ff;">Me</span>.Keys
    Key = arrKeys(iIndex)
<span style="color: #0000ff;">End</span> Function

Now we can implement another new interface – Clone. It will return a copy of the current dictionary. Perfect for sending it to outer functions with just minor adjustments to some of the items:

<span style="color: #0000ff;">Public</span> <span style="color: #0000ff;">Function</span> Clone
    <span style="color: #0000ff;">Dim</span> oResult
    <span style="color: #0000ff;">Dim</span> i

    <span style="color: #0000ff;">Set</span> oResult = <span style="color: #0000ff;">New</span> NewDictionary

    <span style="color: #0000ff;">For</span> i = 0 <span style="color: #0000ff;">to</span> <span style="color: #0000ff;">Me</span>.Count - 1
        oResult.Add <span style="color: #0000ff;">Me</span>.Key(i), <span style="color: #0000ff;">Me</span>.Item(i)
    <span style="color: #0000ff;">Next</span>

    <span style="color: #0000ff;">Set</span> Clone = oResult
<span style="color: #0000ff;">End</span> Function

And now – what for me is quite a killer feature – merge. We’ll take another new dictionary object, and merge its data into our own. Our dictionary’s data takes precedence, so we’ll only import new values. Notice how these features become very easy to implement once you have the improved .Item and new .Key methods.

<span style="color: #0000ff;">Public</span> <span style="color: #0000ff;">Sub</span> Merge(oOutsideDictionary)
    <span style="color: #0000ff;">Dim</span> i

    <span style="color: #0000ff;">For</span> i = 0 <span style="color: #0000ff;">to</span> oOutsideDictionary.Count - 1
        <span style="color: #0000ff;">If</span> <span style="color: #0000ff;">Not</span> <span style="color: #0000ff;">Me</span>.Exists(oOutsideDictionary.Key(i)) <span style="color: #0000ff;">Then</span> _
            <span style="color: #0000ff;">Me</span>.Add oOutsideDictionary.Key(i), oOutsideDictionary.Item(i)
    <span style="color: #0000ff;">Next</span>
<span style="color: #0000ff;">End</span> Sub

And, last but not least, we’ll add a .Import and .Export methods, which will transfer the dictionary’s data from and to an external file. Dictionary’s are often used to carry important information, which we might like to save for the next test run. Since the object itself will be destroyed once QTP stops, we need to same the information in an external resource – a text file. The data will be saved in this format: Key>Value|Key>Value|… . Of course that this only applies to simple data-types – objects will not be saved.

<span style="color: #0000ff;">Sub</span> Export(sFileName)
    <span style="color: #0000ff;">Dim</span> i
    <span style="color: #0000ff;">Dim</span> oFSO
    <span style="color: #0000ff;">Dim</span> oFile
    <span style="color: #0000ff;">Dim</span> sData

    <span style="color: #0000ff;">On</span> <span style="color: #0000ff;">Error</span> <span style="color: #0000ff;">Resume</span> <span style="color: #0000ff;">Next</span> <span style="color: #008000;">\'Protects from object items</span>

    <span style="color: #0000ff;">For</span> i = 0 <span style="color: #0000ff;">to</span> <span style="color: #0000ff;">Me</span>.Count - 1
        sData = sData & <span style="color: #006080;">"|"</span> & <span style="color: #0000ff;">Me</span>.Key(i) & <span style="color: #006080;">">"</span> & <span style="color: #0000ff;">Me</span>.Item(i)
    <span style="color: #0000ff;">Next</span>

    sData = Mid(sData,2) <span style="color: #008000;">\'Get rid of the first, unneeded \'|\'</span>

    <span style="color: #0000ff;">Set</span> oFSO = CreateObject(<span style="color: #006080;">"Scripting.FileSystemObject"</span>)
    <span style="color: #0000ff;">Set</span> oFile = oFSO.CreateTextFile(sFileName, <span style="color: #0000ff;">True</span>)

    <span style="color: #0000ff;">Call</span> oFile.Write(sData)

    oFile.Close

    <span style="color: #0000ff;">Set</span> oFile = <span style="color: #0000ff;">Nothing</span>
    <span style="color: #0000ff;">Set</span> oFSO = <span style="color: #0000ff;">Nothing</span>

    <span style="color: #0000ff;">On</span> <span style="color: #0000ff;">Error</span> <span style="color: #0000ff;">Goto</span> 0
<span style="color: #0000ff;">End</span> <span style="color: #0000ff;">Sub</span>

<span style="color: #0000ff;">Sub</span> Import(sFileName)
    <span style="color: #0000ff;">Dim</span> i
    <span style="color: #0000ff;">Dim</span> oFSO
    <span style="color: #0000ff;">Dim</span> oFile
    <span style="color: #0000ff;">Dim</span> sData
    <span style="color: #0000ff;">Dim</span> arrData, arrSingleField

    <span style="color: #0000ff;">On</span> <span style="color: #0000ff;">Error</span> Sesume <span style="color: #0000ff;">Next</span> <span style="color: #008000;">\'Protects from wrong file names</span>

    <span style="color: #0000ff;">Set</span> oFSO = CreateObject(<span style="color: #006080;">"Scripting.FileSystemObject"</span>)
    <span style="color: #0000ff;">Set</span> oFile = oFSO.OpenTextFile(sFileName, 1, <span style="color: #0000ff;">True</span>)

    sData = oFile.ReadAll

    oFile.Close

    <span style="color: #0000ff;">Set</span> oFile = <span style="color: #0000ff;">Nothing</span>
    <span style="color: #0000ff;">Set</span> oFSO = <span style="color: #0000ff;">Nothing</span>

    arrData = Split(sData, <span style="color: #006080;">"|"</span>)

    <span style="color: #0000ff;">For</span> i = 0 <span style="color: #0000ff;">to</span> uBound(arrData)
        arrSingleField = Split(arrData(i), <span style="color: #006080;">">"</span>)
        <span style="color: #0000ff;">Me</span>.Add arrSingleField(0), arrSingleField(1)
    <span style="color: #0000ff;">Next</span>

    <span style="color: #0000ff;">On</span> <span style="color: #0000ff;">Error</span> <span style="color: #0000ff;">Goto</span> 0
<span style="color: #0000ff;">End</span> Sub

We can add more methods and properties, but even now we have quite a buffed up dictionary, which can make our lived much easier.

Bringing it all together

Here’s the entire code, with extra comments:

<span style="color: #0000ff;">Class</span> NewDictionary
    <span style="color: #0000ff;">Private</span> oDic <span style="color: #008000;">\'Will hold the hidden inner dictionary</span>

    <span style="color: #008000;">\'****** Class LifeCycle ****** </span>
    <span style="color: #0000ff;">Sub</span> Class_Initialize <span style="color: #008000;">\'Will fire automatically when create a new instance</span>
        <span style="color: #0000ff;">Set</span> oDic = CreateObject(<span style="color: #006080;">"Scripting.Dictionary"</span>)
    <span style="color: #0000ff;">End</span> <span style="color: #0000ff;">Sub</span>

    <span style="color: #0000ff;">Sub</span> Class_Terminate <span style="color: #008000;">\'Will fire automatically when an instance is destroyed</span>
        <span style="color: #0000ff;">Set</span> oDic = <span style="color: #0000ff;">Nothing</span>
    <span style="color: #0000ff;">End</span> <span style="color: #0000ff;">Sub</span>

    <span style="color: #008000;">\'****** Basic properties ****** </span>
    <span style="color: #008000;">\'All these properties are read-only</span>
    <span style="color: #008000;">\'This is why they only contain a Get block</span>

    <span style="color: #0000ff;">Public</span> <span style="color: #0000ff;">Property</span> <span style="color: #0000ff;">Get</span> Count <span style="color: #008000;">\'Returns the number of items in our dictionary</span>
        Count = oDic.Count <span style="color: #008000;">\'The answer is the number of items in the inner dictionary</span>
    <span style="color: #0000ff;">End</span> <span style="color: #0000ff;">Property</span>

    <span style="color: #0000ff;">Public</span> <span style="color: #0000ff;">Property</span> <span style="color: #0000ff;">Get</span> Keys <span style="color: #008000;">\'Returns the dictionary keys (array)</span>
        Keys = oDic.Keys
    <span style="color: #0000ff;">End</span> <span style="color: #0000ff;">Property</span>

    <span style="color: #0000ff;">Public</span> <span style="color: #0000ff;">Property</span> <span style="color: #0000ff;">Get</span> Items <span style="color: #008000;">\'Returns the dictionary items (array)</span>
        Items = oDic.Items
    <span style="color: #0000ff;">End</span> <span style="color: #0000ff;">Property</span>

    <span style="color: #0000ff;">Public</span> <span style="color: #0000ff;">Property</span> <span style="color: #0000ff;">Get</span> Exists(Key) <span style="color: #008000;">\'Returns a True/False if the Key exists</span>
        Exists = oDic.Exists(Key)
    <span style="color: #0000ff;">End</span> <span style="color: #0000ff;">Property</span>

    <span style="color: #008000;">\'****** Improved Methods ****** </span>

    <span style="color: #0000ff;">Public</span> <span style="color: #0000ff;">Sub</span> Remove(Key) <span style="color: #008000;">\'Removes the key from the dictionary (it it existed)</span>
        <span style="color: #0000ff;">If</span> oDic.Exists(Key) <span style="color: #0000ff;">Then</span> oDic.Remove(Key)
    <span style="color: #0000ff;">End</span> <span style="color: #0000ff;">Sub</span>

    <span style="color: #0000ff;">Public</span> <span style="color: #0000ff;">Sub</span> Add(Key, Value) <span style="color: #008000;">\'Adds a new value to the dictionary. Overwrites existing values</span>
        <span style="color: #0000ff;">Call</span> <span style="color: #0000ff;">Me</span>.Remove(Key)
        oDic.Add Key, Value
    <span style="color: #0000ff;">End</span> <span style="color: #0000ff;">Sub</span>


    <span style="color: #0000ff;">Public</span> <span style="color: #0000ff;">Function</span> Item(Key) <span style="color: #008000;">\'Returns an item, either by a key or an index</span>
        <span style="color: #0000ff;">Dim</span> arrKeys <span style="color: #008000;">\'Will hold the inner dictionary keys</span>
        <span style="color: #0000ff;">Dim</span> sRealKey <span style="color: #008000;">\'The actual key which holds the needed value</span>

        arrKeys = oDic.Keys

        <span style="color: #0000ff;">If</span> IsNumeric(Key) <span style="color: #0000ff;">Then</span>
            sRealKey = arrKeys(Key) <span style="color: #008000;">\'We have to translate the number to the corresponding key</span>
        <span style="color: #0000ff;">Else</span>
            sReakKey = Key <span style="color: #008000;">\'We can use the key as it is</span>
        <span style="color: #0000ff;">End</span> <span style="color: #0000ff;">If</span>

        <span style="color: #008000;">\'If the relevant item is an object, we\'ll have to use the Set keyword to retun it</span>
        <span style="color: #0000ff;">If</span> IsObject(oDic.Item(sRealKey)) <span style="color: #0000ff;">Then</span>
            <span style="color: #0000ff;">Set</span> Item = oDic.Item(sRealKey)
        <span style="color: #0000ff;">Else</span>
            Item = oDic.Item(sRealKey)
        <span style="color: #0000ff;">End</span> <span style="color: #0000ff;">If</span>

    <span style="color: #0000ff;">End</span> <span style="color: #0000ff;">Function</span>

    <span style="color: #008000;">\'****** New Methods ****** </span>

    <span style="color: #0000ff;">Public</span> <span style="color: #0000ff;">Function</span> Key(iIndex) <span style="color: #008000;">\'Returns the key at a given index</span>
        <span style="color: #0000ff;">Dim</span> arrKeys

        <span style="color: #0000ff;">If</span> iIndex > <span style="color: #0000ff;">Me</span>.Count -1 <span style="color: #0000ff;">Then</span> <span style="color: #0000ff;">Exit</span> <span style="color: #0000ff;">Function</span> <span style="color: #008000;">\'There is no such key</span>

        arrKeys = <span style="color: #0000ff;">Me</span>.Keys
        Key = arrKeys(iIndex)
    <span style="color: #0000ff;">End</span> <span style="color: #0000ff;">Function</span>

    <span style="color: #0000ff;">Public</span> <span style="color: #0000ff;">Function</span> Clone <span style="color: #008000;">\'Returns a copy of the dictionary</span>
        <span style="color: #0000ff;">Dim</span> i
        <span style="color: #0000ff;">Dim</span> oResult

        <span style="color: #0000ff;">Set</span> oResult = <span style="color: #0000ff;">New</span> NewDictionary

        <span style="color: #0000ff;">For</span> i = 0 <span style="color: #0000ff;">to</span> <span style="color: #0000ff;">Me</span>.Keys - 1
            oResult.Add <span style="color: #0000ff;">Me</span>.Key(i), <span style="color: #0000ff;">Me</span>.Item(i)
        <span style="color: #0000ff;">Next</span>

        <span style="color: #0000ff;">Set</span> Clone = oResult
    <span style="color: #0000ff;">End</span> <span style="color: #0000ff;">Function</span>

    <span style="color: #0000ff;">Public</span> <span style="color: #0000ff;">Sub</span> Merge(oOutsideDictionary) <span style="color: #008000;">\'Merges the dictionary with another one</span>
        <span style="color: #0000ff;">Dim</span> i

        <span style="color: #0000ff;">For</span> i = 0 <span style="color: #0000ff;">to</span> oOutsideDictionary.Count - 1
            <span style="color: #008000;">\'Add the value, but don\'t overwrite</span>
            <span style="color: #0000ff;">If</span> <span style="color: #0000ff;">Not</span> <span style="color: #0000ff;">Me</span>.Exists(oOutsideDictionary.Key(i)) <span style="color: #0000ff;">Then</span> _
                <span style="color: #0000ff;">Me</span>.Add oOutsideDictionary.Key(i), oOutsideDictionary.Item(i)
        <span style="color: #0000ff;">Next</span>
    <span style="color: #0000ff;">End</span> <span style="color: #0000ff;">Sub</span>

    <span style="color: #0000ff;">Sub</span> Export(sFileName) <span style="color: #008000;">\'Exports the dictionary to a text file</span>
        <span style="color: #0000ff;">Dim</span> i
        <span style="color: #0000ff;">Dim</span> oFSO
        <span style="color: #0000ff;">Dim</span> oFile
        <span style="color: #0000ff;">Dim</span> sData

       <span style="color: #0000ff;">On</span> <span style="color: #0000ff;">Error</span> <span style="color: #0000ff;">Resume</span> <span style="color: #0000ff;">Next</span> <span style="color: #008000;">\'Protects from object items</span>

        <span style="color: #008000;">\'First, create a string holding the dictionary data</span>
        <span style="color: #0000ff;">For</span> i = 0 <span style="color: #0000ff;">to</span> <span style="color: #0000ff;">Me</span>.Count - 1
            sData = sData & <span style="color: #006080;">"|"</span> & <span style="color: #0000ff;">Me</span>.Key(i) & <span style="color: #006080;">">"</span> & <span style="color: #0000ff;">Me</span>.Item(i)
        <span style="color: #0000ff;">Next</span>

        sData = Mid(sData,2) <span style="color: #008000;">\'Get rid of the first, unneeded \'|\'</span>

        <span style="color: #008000;">\'Now, write the string to an external file</span>
        <span style="color: #0000ff;">Set</span> oFSO = CreateObject(<span style="color: #006080;">"Scripting.FileSystemObject"</span>)
        <span style="color: #0000ff;">Set</span> oFile = oFSO.CreateTextFile(sFileName, <span style="color: #0000ff;">True</span>)

        <span style="color: #0000ff;">Call</span> oFile.Write(sData)

        oFile.Close

        <span style="color: #0000ff;">Set</span> oFile = <span style="color: #0000ff;">Nothing</span>
        <span style="color: #0000ff;">Set</span> oFSO = <span style="color: #0000ff;">Nothing</span>

        <span style="color: #0000ff;">On</span> <span style="color: #0000ff;">Error</span> <span style="color: #0000ff;">Goto</span> 0
    <span style="color: #0000ff;">End</span> <span style="color: #0000ff;">Sub</span>

    <span style="color: #0000ff;">Sub</span> Import(sFileName) <span style="color: #008000;">\'Builds the dictionary from an external file</span>
        <span style="color: #0000ff;">Dim</span> i
        <span style="color: #0000ff;">Dim</span> oFSO
        <span style="color: #0000ff;">Dim</span> oFile
        <span style="color: #0000ff;">Dim</span> sData
        <span style="color: #0000ff;">Dim</span> arrData, arrSingleField

        <span style="color: #0000ff;">On</span> <span style="color: #0000ff;">Error</span> <span style="color: #0000ff;">Resume</span> <span style="color: #0000ff;">Next</span> <span style="color: #008000;">\'Protects from wrong file names</span>

        <span style="color: #0000ff;">Set</span> oFSO = CreateObject(<span style="color: #006080;">"Scripting.FileSystemObject"</span>)
        <span style="color: #0000ff;">Set</span> oFile = oFSO.OpenTextFile(sFileName, 1, <span style="color: #0000ff;">True</span>)

        sData = oFile.ReadAll

        oFile.Close

        <span style="color: #0000ff;">Set</span> oFile = <span style="color: #0000ff;">Nothing</span>
        <span style="color: #0000ff;">Set</span> oFSO = <span style="color: #0000ff;">Nothing</span>

        <span style="color: #008000;">\'Split the data string to its separate key>item pairs</span>
        arrData = Split(sData, <span style="color: #006080;">"|"</span>)

        <span style="color: #0000ff;">For</span> i = 0 <span style="color: #0000ff;">to</span> uBound(arrData)
            <span style="color: #008000;">\'Split each pair</span>
            arrSingleField = Split(arrData(i), <span style="color: #006080;">">"</span>)

            <span style="color: #008000;">\'Add the value to the dictionary</span>
            <span style="color: #0000ff;">Me</span>.Add arrSingleField(0), arrSingleField(1)
        <span style="color: #0000ff;">Next</span>

        <span style="color: #0000ff;">On</span> <span style="color: #0000ff;">Error</span> <span style="color: #0000ff;">Goto</span> 0
    <span style="color: #0000ff;">End</span> <span style="color: #0000ff;">Sub</span>

<span style="color: #0000ff;">End</span> Class

You can also download a clean version of the code:

Dictionary.VBS

, , , ,

A Pitfall for Beginners when Working with a Dictionary

0
by on April 23, 2008 at 11:00

Introduction

First and foremost I wish to thank two of my team members, Yasmin Helled and Eyas Kopty, who actually brought this issue to my attention. This post actually replaces an earlier post in which I prematurely and erroneously declared the issue as being a bug. My apologies to you, my loyal readers, for falling with such pitfall. I hope this short article will enable you avoid another one, even more substantial – one that can impact the way your code behaves.

 

Discussion

Yasmin had showed me a piece of code similar to the following (I simplified it a bit for illustration purposes):

<span style="color: #0000ff">If</span> <span style="color: #0000ff">Not</span> (objDic.Exists(<span style="color: #006080">"MyKey"</span>) <span style="color: #0000ff">Or</span> IsNumeric(objDic(<span style="color: #006080">"MyKey"</span>))) <span style="color: #0000ff">Then</span>
    MsgBox <span style="color: #006080">"Key Not Found"</span>
<span style="color: #0000ff">Else</span>
    MsgBox <span style="color: #006080">"Key Found: "</span> & objDic(<span style="color: #006080">"MyKey"</span>)
<span style="color: #0000ff">End</span> If

The key, needless to say, was not previously added, but the condition consistently entered the Else clause, printing an Empty value in the MsgBox. This sounded weird to Yasmin, who had forgotten that VBScript always checks ALL conditional clauses, so that even though the first part of the condition already returned true, the second part is also checked. This resulted in runtime problems, since the key thus added contained an empty value!

To overcome this problem, the above code was replaced with the following:

<span style="color: #008000">\'Declare variables</span>
<span style="color: #0000ff">Dim</span> objDic, strKey

<span style="color: #008000">\'Create instance of Dictionary</span>
<span style="color: #0000ff">Set</span> objDic = CreateObject(<span style="color: #006080">"Scripting.Dictionary"</span>)

<span style="color: #008000">\'Assign value to required key</span>
strKey = <span style="color: #006080">"MyKey"</span>

<span style="color: #0000ff">If</span> <span style="color: #0000ff">Not</span> (objDic.Exists(strKey)) <span style="color: #0000ff">Then</span>                 <span style="color: #008000">\'Check if the key exists</span>
    MsgBox <span style="color: #006080">"Key "</span> & strKey & <span style="color: #006080">" was not found."</span>
<span style="color: #0000ff">ElseIf</span> <span style="color: #0000ff">Not</span> IsNumeric(objDic(strKey)) <span style="color: #0000ff">Then</span>           <span style="color: #008000">\'The key exists so check if it\'s numeric</span>
    MsgBox <span style="color: #006080">"Value is not numeric: "</span>  & objDic(strKey)
<span style="color: #0000ff">Else</span>                                                <span style="color: #008000">\'Report that the validation succeeded</span>
    MsgBox <span style="color: #006080">"Key "</span> & strKey & <span style="color: #006080">" was found and the value is "</span> & objDic(strKey)
<span style="color: #0000ff">End</span> <span style="color: #0000ff">If</span>

So that functional independence between key existence and value type validation is achieved.

 

Conclusion

 

When addressing a non-existing key in a Dictionary object, the add method is invoked by default. The problem is that the Windows Script Host does not inform during runtime that there is a missing key. Moreover, the automatically assigned Empty value may cause trouble to our subsequent code execution. I hope that bringing up this issue will benefit programmers and enable them to avoid such a pitfall.

 

*Note: This revised post replaces a previous post titled "Amazing Bug in the Dictionary Object!"

, ,

Add Elements to a Dictionary

0
by on April 1, 2008 at 22:55

Demonstration script that adds three key-item pairs to a Script Runtime Dictionary. Script must be run on the local computer.

<span style="color: #0000ff;">Set</span> oDictionary = CreateObject(<span style="color: #006080;">"Scripting.Dictionary"</span>)

oDictionary.Add <span style="color: #006080;">"Printer 1"</span>, <span style="color: #006080;">"Printing"</span>
oDictionary.Add <span style="color: #006080;">"Printer 2"</span>, <span style="color: #006080;">"Offline"</span>
oDictionary.Add <span style="color: #006080;">"Printer 3"</span>, <span style="color: #006080;">"Printing"</span>

,

Delete All Elements from a Dictionary

0
by on April 1, 2008 at 22:53

Demonstration script that deletes all the key-item pairs from a Script Runtime Dictionary. Script must be run on the local computer

<span style="color: #0000ff;">Set</span> oDictionary = CreateObject(<span style="color: #006080;">"Scripting.Dictionary"</span>)

oDictionary.Add <span style="color: #006080;">"Printer 1"</span>, <span style="color: #006080;">"Printing"</span>
oDictionary.Add <span style="color: #006080;">"Printer 2"</span>, <span style="color: #006080;">"Offline"</span>
oDictionary.Add <span style="color: #006080;">"Printer 3"</span>, <span style="color: #006080;">"Printing"</span>
keysCol = oDictionary.Keys

Print <span style="color: #006080;">"First run: "</span>
<span style="color: #0000ff;">For</span> <span style="color: #0000ff;">Each</span> KeyStr <span style="color: #0000ff;">in</span> keysCol
    Print KeyStr
<span style="color: #0000ff;">Next</span>

oDictionary.RemoveAll
keysCol = oDictionary.Keys

Print  <span style="color: #006080;">"Second run: "</span>
<span style="color: #0000ff;">For</span> <span style="color: #0000ff;">Each</span> KeyStr <span style="color: #0000ff;">in</span> keysCol
    Print KeyStr
<span style="color: #0000ff;">Next</span>

,

Delete One Element from a Dictionary

0
by on April 1, 2008 at 22:52

Demonstration script that deletes a specific key-item pair from a Script Runtime Dictionary. Script must be run on the local computer.

<span style="color: #0000ff;">Set</span> oDictionary = CreateObject(<span style="color: #006080;">"Scripting.Dictionary"</span>)

oDictionary.Add <span style="color: #006080;">"Printer 1"</span>, <span style="color: #006080;">"Printing"</span>
oDictionary.Add <span style="color: #006080;">"Printer 2"</span>, <span style="color: #006080;">"Offline"</span>
oDictionary.Add <span style="color: #006080;">"Printer 3"</span>, <span style="color: #006080;">"Printing"</span>

keysCol = oDictionary.Keys

Print  <span style="color: #006080;">"First run: "</span>
<span style="color: #0000ff;">For</span> <span style="color: #0000ff;">Each</span> keyStr <span style="color: #0000ff;">in</span> keysCol
    Print keyStr
<span style="color: #0000ff;">Next</span>

oDictionary.Remove(<span style="color: #006080;">"Printer 2"</span>)
keysCol= oDictionary.Keys

Print <span style="color: #006080;">"Second run: "</span>
<span style="color: #0000ff;">For</span> <span style="color: #0000ff;">Each</span> keyStrin keysCol
    Print keyStr
<span style="color: #0000ff;">Next</span>

,

List the Number of Items in a Dictionary

0
by on April 1, 2008 at 22:49

Demonstration script that counts the number of key-item pairs in a Script Runtime Dictionary. Script must be run on the local computer.

<span style="color: #0000ff;">Set</span> oDictionary = CreateObject(<span style="color: #006080;">"Scripting.Dictionary"</span>)

oDictionary.Add <span style="color: #006080;">"Printer 1"</span>, <span style="color: #006080;">"Printing"</span>
oDictionary.Add <span style="color: #006080;">"Printer 2"</span>, <span style="color: #006080;">"Offline"</span>
oDictionary.Add <span style="color: #006080;">"Printer 3"</span>, <span style="color: #006080;">"Printing"</span>
Print objDictionary.Count

,

Dictionary of Employees

0
by on April 1, 2008 at 22:46

Demonstration script that combines the usage of classes and dictionary object. Script must be run on the local computer.

<span style="color: #0000ff;">Class</span> Employee
    <span style="color: #0000ff;">Private</span> fname,lname,m_id,m_city,m_country

    <span style="color: #0000ff;">Public</span> <span style="color: #0000ff;">Property</span> <span style="color: #0000ff;">Get</span> FirstName()
        FirstName = fname
    <span style="color: #0000ff;">End</span> <span style="color: #0000ff;">Property</span>
    <span style="color: #0000ff;">Public</span> <span style="color: #0000ff;">Property</span> <span style="color: #0000ff;">Let</span> FirstName( value )
        fname = value
    <span style="color: #0000ff;">End</span> <span style="color: #0000ff;">Property</span>
    <span style="color: #0000ff;">Public</span> <span style="color: #0000ff;">Property</span> <span style="color: #0000ff;">Get</span> LastName()
        LastName = lname
    <span style="color: #0000ff;">End</span> <span style="color: #0000ff;">Property</span>
    <span style="color: #0000ff;">Public</span> <span style="color: #0000ff;">Property</span> <span style="color: #0000ff;">Let</span> LastName( value )
        lname = value
    <span style="color: #0000ff;">End</span> <span style="color: #0000ff;">Property</span>
    <span style="color: #0000ff;">Public</span> <span style="color: #0000ff;">Property</span> <span style="color: #0000ff;">Get</span> Id()
        Id = m_id
    <span style="color: #0000ff;">End</span> <span style="color: #0000ff;">Property</span>
    <span style="color: #0000ff;">Public</span> <span style="color: #0000ff;">Property</span> <span style="color: #0000ff;">Let</span> Id( value )
        m_id = value
    <span style="color: #0000ff;">End</span> <span style="color: #0000ff;">Property</span>
     <span style="color: #0000ff;">Public</span> <span style="color: #0000ff;">Property</span> <span style="color: #0000ff;">Get</span> City()
        City = m_city
    <span style="color: #0000ff;">End</span> <span style="color: #0000ff;">Property</span>
    <span style="color: #0000ff;">Public</span> <span style="color: #0000ff;">Property</span> <span style="color: #0000ff;">Let</span> City( value )
        m_city = value
    <span style="color: #0000ff;">End</span> <span style="color: #0000ff;">Property</span>
     <span style="color: #0000ff;">Public</span> <span style="color: #0000ff;">Property</span> <span style="color: #0000ff;">Get</span> Country()
        Country = m_country
    <span style="color: #0000ff;">End</span> <span style="color: #0000ff;">Property</span>
    <span style="color: #0000ff;">Public</span> <span style="color: #0000ff;">Property</span> <span style="color: #0000ff;">Let</span> Country( value )
        m_country = value
    <span style="color: #0000ff;">End</span> <span style="color: #0000ff;">Property</span>
<span style="color: #0000ff;">End</span> <span style="color: #0000ff;">Class</span>

<span style="color: #0000ff;">Set</span> listEmployee = CreateObject( <span style="color: #006080;">"Scripting.Dictionary"</span> )
listEmployee.Add <span style="color: #006080;">"1"</span>, <span style="color: #0000ff;">New</span> Employee
listEmployee( <span style="color: #006080;">"1"</span> ).Id = <span style="color: #006080;">"3425789734"</span>
listEmployee( <span style="color: #006080;">"1"</span> ).FirstName = <span style="color: #006080;">"Dani"</span>
listEmployee( <span style="color: #006080;">"1"</span> ).LastName = <span style="color: #006080;">"Vainstein"</span>
listEmployee( <span style="color: #006080;">"1"</span> ).City = <span style="color: #006080;">"Petaj Tikva"</span>
listEmployee( <span style="color: #006080;">"1"</span> ).Country = <span style="color: #006080;">"Israel"</span>
listEmployee.Add <span style="color: #006080;">"2"</span>, <span style="color: #0000ff;">New</span> Employee
listEmployee( <span style="color: #006080;">"2"</span> ).Id = <span style="color: #006080;">"456875677"</span>
listEmployee( <span style="color: #006080;">"2"</span> ).FirstName = <span style="color: #006080;">"Sara"</span>
listEmployee( <span style="color: #006080;">"2"</span> ).LastName = <span style="color: #006080;">"Vainstein"</span>
listEmployee( <span style="color: #006080;">"2"</span> ).City = <span style="color: #006080;">"BatYam"</span>
listEmployee( <span style="color: #006080;">"2"</span> ).Country = <span style="color: #006080;">"Israel"</span>
<span style="color: #008000;">\' ** Printing</span>
<span style="color: #0000ff;">For</span> nEmp = 1 <span style="color: #0000ff;">To</span> listEmployee.Count
    Print <span style="color: #006080;">"Employee No: "</span> & nEmp
    Print listEmployee( <span style="color: #0000ff;">Cstr</span>( nEmp ) ).FirstName
    Print listEmployee( <span style="color: #0000ff;">Cstr</span>( nEmp ) ).LastName
    Print listEmployee( <span style="color: #0000ff;">Cstr</span>( nEmp ) ).Country
Next

, ,