Creating a complex structure with Scripting Dictionary - VBScript
I am trying to understand some code so that i can make modifications to it. I am fairly new at vbscript so any help is appreciated .
I am looking at a Dictionary object that looks like it is behaving like a table with different rows controlled by a key. I am not sure what is happening. commands like
list.add
list.count+1
, ListElement
are a little over my league right now. The code is able to output data for 1 use with simple statement
Sub DumpList ( list )
' This function dumps all the people in the office and their information
' in the application window. The list is usually sorted by Name.
Dim e, le
For Each e In list ' output listelements...
Set le = list(e)
LogOutput 0, "line: " & (le.num, 3) & " : " & le.Name _
& " " & le.PHNumber1 & " 开发者_如何转开发" & le.PHNumber2 _
& " " & le.Email1 & " " & le.Email2 _
& " " & le.DeskNo.1 & " " & le.OFficeCode _
& " " & le.wirecolour & " " & le.wirecross
Next
End Sub
I am not sure how it is working for me to make any changes to it.
Thanks again
The task: Maintain a collection of persons.
First attempt at a solution: Use a dictionary with numerical indices=keys, based on dic.Count
As sanwar pointed out, a dictionary stores key-value pairs. To put (info about) persons in a dictionary, we need a person class from which we can create person objects/instances to hold the multiple information elements.
Minimal/POC code for a Person class:
Dim g_nPersonId : g_nPersonId = -1
Class cPerson
Private m_nId
Private m_sName
Private m_dtBirth
Private m_dWage
Public Function init( sName, dtBirth, dWage )
Set init = Me
g_nPersonId = g_nPersonId + 1
m_nId = g_nPersonId
Name = sName
Birth = dtBirth
Wage = dWage
End Function
Public Property Let Name( sName ) : m_sName = sName : End Property
Public Property Let Birth( dtBirth ) : m_dtBirth = dtBirth : End Property
Public Property Let Wage( dWage ) : m_dWage = dWage : End Property
Public Property Get Id() : Id = m_nId : End Property
Public Property Get Name() : Name = m_sName : End Property
Public Property Get Birth() : m_dtBirth = m_dtBirth : End Property
Public Property Get Wage() : m_dWage = m_dWage : End Property
Public Function Data()
Data = Array( m_nId, m_sName, m_dtBirth, m_dWage )
End Function
End Class ' cPerson
[The class cPerson defines/blue prints persons, each having an id, a name, a dob, and a salary. You create persons by calling the init function passing suitable values for name, doc, and wage members; the id will augmented automagically (by using a global counter instead of proper class level data as possible in more capable OO languages).]
and a demo script to prove we can create and display persons:
Dim oAdam : Set oAdam = New cPerson.init( "Adam", #1/5/2001#, 1234.56 )
Dim oEve : Set oEve = New cPerson.init( "Eve" , #1/6/2001#, 6543.21 )
Dim oPerson
For Each oPerson In Array( oAdam, oEve )
WScript.Echo Join( oPerson.Data(), " - " )
Next
output:
0 - Adam - 1/5/2001 - 1234.56
1 - Eve - 1/6/2001 - 6543.21
Now lets put them in a dictionary with numerical keys (a VBScript special feature, other languages have string-key-only dictionaries) based on the .Count property. The .Count property of an empty dictionary is 0, by adding the first element (a person object holding all info we need) to the dictionary its .Count increments to 1 (ready for the next addition). You easily can see that .Add .Count + 1 is a waste of time/effort:
Dim dicPersons : Set dicPersons = CreateObject( "Scripting.Dictionary" )
Dim aPersons : aPersons = Array( _
Array( "Adam", #1/5/2001#, 1234.56 ) _
, Array( "Eve" , #1/6/2001#, 6543.21 ) _
)
Dim aPerson
For Each aPerson In aPersons
dicPersons.Add dicPersons.Count, New cPerson.init( aPerson( 0 ), aPerson( 1 ), aPerson( 2 ) )
Next
Dim nPerson
WScript.Echo "Adam & Eve"
For Each nPerson In dicPersons
WScript.Echo nPerson, ":", Join( dicPersons( nPerson ).Data(), " - " )
Next
dicPersons.Remove 0 ' how do we know the key of Adam?
WScript.Echo "Adam zaped"
For Each nPerson In dicPersons
WScript.Echo nPerson, ":", Join( dicPersons( nPerson ).Data(), " - " )
Next
WScript.Echo "Trying to add Caine"
On Error Resume Next
dicPersons.Add dicPersons.Count, New cPerson.init( "Caine", Date(), 0.33 )
WScript.Echo Err.Description
On Error GoTo 0
The output
Adam & Eve
0 : 0 - Adam - 1/5/2001 - 1234.56
1 : 1 - Eve - 1/6/2001 - 6543.21
Adam zaped
1 : 1 - Eve - 1/6/2001 - 6543.21
Trying to add Caine
This key is already associated with an element of this collection
shows why dictionaries with numerical indices based on .Count are no solution for the task: Maintain a collection of persons.
In this case the variable list
holds a Scripting.Dictionary
.
When you use the VBScript For Each
construct on Scripting.Dictionary
each key in the dictionary is returned. So in this case the For Each
will loop place each key in the variable e
on each iteration.
The Line:-
Set le = list(e)
is now using the key for this loop to lookup the value in the dictionary associated with the key. In this case the value is an object that has properties.
Hence a dictionary can be used to quickly and directly lookup a "row" in a "table" using its key. Also as the code you've posted demonstrates you can enumerate each key and lookup each value to "scan" the whole "table".
精彩评论