Trim and Dictionary can not work together - excel

I have code like this, but:
If I use myDic.add Trim(cells(4,5)), key --> I get an error.
If I use myDic.add cells(4,5), key --> no error.
Dim MyDictionary As Scripting.Dictionary
Set MyDictionary = New Scripting.Dictionary
Do While Len(Temp.Cells(num, 1))) > 0
"myDic.add Trim(cells(4,5)), key" 'Error Here
Loop
Is that we cannot use Trim when we use Add ? Thanks

You can use Trim (or typed function Trim$) with dict.add. There are a number of other errors with your code:
Get rid of the " around
"myDic.add Trim(cells(4,5)), key"
i.e.
myDic.add Trim(cells(4,5)), key
Also, you add key first with dictionaries, though I don't know what you mean by key here. Where is it defined and do you mean key for the value you wish to add to the dictionary?
And, you don't increment the cell it is always cells(4,5) . If this was a key they must be unique.
Traditionally I would expect something like
dict.add key, Trim$(ws.cells(i,5))
where key is unique and defined, ws is a variable holding the parent sheet name, i (or maybe num?) is an Long type variable to allow you to change the value being added, assuming you want to add a cell value in a loop to a dictionary.

Related

Dict key getting overwritten when created in a loop

I'm trying to create individual dictionary entries while looping through some input data. Part of the data is used for the key, while a different part is used as the value associated with that key. I'm running into a problem (due to Python's "everything is an object, and you reference that object" operations method) with this as ever iteration through my loop alters the key set in previous iterations, thus overwriting the previously set value, instead of creating a new dict key and setting it with its own value.
popcount = {}
for oneline of datafile:
if oneline[:3] == "POP":
dat1, dat2, dat3, dat4, dat5, dat6 = online.split(":")
datid = str.join(":", [dat2, dat3])
if datid in popcount:
popcount[datid] += int(dat4)
else:
popcount = { datid : int(dat4) }
This iterates over seven lines of data (datafile is a list containing that information) and should create four separate keys for datid, each with their own value. However, what ends up happening is that only the last value for datid exist in the dictionary when the code is run. That happens to be the one that has duplicates, and they get summed properly (so, at least i know that part of the code works, but the other key entries just are ... gone.
The data is read from a file, is colon (:) separated, and treated like a string even when its numeric (thus the int() call in the if datid in popcount).
What am I missing/doing wrong here? So far I haven't been able to find anything that helps me out on this one (though you folks have answered a lot of other Python questions i've run into, even if you didn't know it). I know why its failing; or, i think i do -- it is because when I update the value of datid the key gets pointed to the new datid value object even though I don't want it to, correct? I just don't know how to fix or work around this behavior. To be honest, its the one thing I dislike about working in Python (hopefully once I grok it, I'll like it better; until then...).
Simply change your last line
popcount = { datid : int(dat4) } # This does not do what you want
This creates a new dict and assignes it to popcount, throwing away your previous data.
What you want to do is add an entry to your dict instead:
popcount[datid] = int(dat4)

Dictionary lookup fails

I am writing an Excel VBA program that validates a school course schedule. A key component is a global dictionary object that keeps track of the course number (the key) and the number of times that course is scheduled (the item). I have successfully created and loaded the dictionary. I'm trying to lookup the value associated with the course key, but have been unable to do so using the one-line examples I've found at this site. I'd like to use this line of code:
intCourseCnt = gdicCourses("BAAC 100")
or
intCourseCnt = gdicCourses.Item("BAAC 100")
but neither work (actually, the "BAAC 100" part is a string variable, but it won't even work if I hardcode a course in.) Instead, I have to use the kludgy loop code below to lookup the course count:
Private Function Check_Course_Dup_Helper(strCourse As String) As Boolean
Dim k As Variant
Check_Course_Dup_Helper = False
' Read thru dictionary. Look to see if only 1 occurrence then jump out.
For Each k In gdicCourses.Keys
If k = strCourse Then
If gdicCourses.Item(k) = 1 Then
Check_Course_Dup_Helper = True
Exit Function
End If
Exit Function
End If
Next
End Function
Is there a way to rewrite this so that I can lookup of the item value without the loop?
Thank you.
Thanks for the prompt replies. Answers below:
David, the gdicCourses("BAAC 100") code value while the program is running is "empty" which makes the receiving variable equal to 0. The result is the same if I use strCourse variable. Also, the dictionary populating code is shown below. I do not believe it is a problem because I can correctly access the values elsewhere in the program where For-Each-Next loops that use a range variable are employed. Whitespace and non-printable characters are not present.
My guess is that I need to use a range to reference the position in the dictionary rather than a string. I've tried pretty much every combination of this that I can think of, but the value is still "empty".
Set gdicCourses = New Scripting.Dictionary
For Each c In Worksheets("Tables").Range("combined_courses").Cells
If Not (gdicCourses.Exists(c)) Then
gdicCourses.Add c, (Application.WorksheetFunction.CountIF(Range("MWF_Table_Full"), c
(Application.WorksheetFunction.CountIf(Range("TTh_Table_Full"), c)))
End If
Next

Ampscript BuildRowsetFromString() fails on single item

I've been tasked with an ExactTarget task, which uses Ampscript. Trying to learn on the go here. See code snippet below:
%%[
Var #testString, #testOutput
Set #testString = Qwerty
Set #testOutput = BuildRowsetFromString(#testString,"~")
]%%
TestOutput:%%= v(#testOutput) =%%
The code works if the testString contains a ~, but when there is no ~ character in the string, the ouput is blank. Is this correct by design? Do I need to add a conditional to check for the presence of the ~ character?
That's the expected behavior. The BuildRowsetFromString() function alone isn't going to return any value when displayed, you're going to need to use Row() and Field() in order to pull the value out.
Using your example:
%%[
Var #testString, #testOutput
Set #testString = "Qwerty"
Set #testOutput = BuildRowsetFromString(#testString,"~")
]%%
RowCount: %%=RowCount(#testOutput)=%%
TestOutput: %%=v(#testOutput)=%%
The RowCount() function returns a value of 1, essentially saying it knows there's at least one 'row' in there. To display that one value, you'll need to wrap that value with Field() and Row():
TestOutput: %%=Field(Row(#testOutput,1),1)=%%
If you want to display other values in the string, say you were passing "Qwerty~Second~Third", you'll need to either change the number at the Row() function or perform a loop.
References
Using Loops
BuildRowsetFromString() Function

How to call a value of a variable whose name is passed as text to another variable?

I need to call a value of a variable as another variable. E.g.
I assign the FirstVariable = "One"
and then I asssign the Name as Text to
SecondVaribale = "FirstVariable" (Note here it is the "TEXT")
So now can I call or assign the SecondVariable to return the value as One in any ways?
Means this should return One:
Range("A1").Value = SecondVariable
is that possible?
Because I have about 40 such variables to be done in around 4 - 6 instances which I want to drive through a mapping sheet in Excel.
The easy way out is assigning the variables manually which would require manual intervention in future which I want to avoid.
You can create your own custom Dictionary or Collection in VBA for Excel 2007. Then you can "name" your variables, and use another string variable to indirectly access those "named variables". Choice of using Dictionary or Collection is how easy you need it to change the value of a "named variable".
A Dictionary allows you to add, read, change, and remove key/value pairs. A Collection only allows add, read, and remove; you have to use a subroutine to change a key/value pair. A Collection lets you use a numeric index (like an array) to access the key/value pairs; a Dictionary does not have an array-like feature. A pretty thorough comparison is at http://www.experts-exchange.com/Software/Office_Productivity/Office_Suites/MS_Office/A_3391-Using-the-Dictionary-Class-in-VBA.html
So to adapt your example, and to also show a change in value of a "named variable", here is some example code:
Public Function test() As String
' Dictionary example
Dim myDictionary, SecondVariable As String
Set myDictionary = CreateObject("scripting.dictionary")
myDictionary.Add "FirstVariable", "Four"
myDictionary.Add "AnotherVariable", "Two"
SecondVariable = "FirstVariable"
' note that "FirstVariable" must be already defined in the Dictionary else an error will occur; from your example this seemed to be the case
' if this was not the case then will need a more complex line using: If myDictionary.exists(SecondVariable) Then ... Else ...
myDictionary.Item(SecondVariable) = "One"
test = myDictionary.Item(SecondVariable) 'function returns "One"; the current value of "FirstVariable" in the Dictionary
End Function
Public Function test2() As String
' Collection example
Dim myCollection As New Collection, SecondVariable As String
myCollection.Add "Four", "FirstVariable"
myCollection.Add "Two", "AnotherVariable"
SecondVariable = "FirstVariable"
'myCollection(SecondVariable) = "One" 'Cannot do this with a Collection; have to use a Sub like the example below
Call setCollectionValue(myCollection, SecondVariable, "One")
test2 = myCollection(SecondVariable) 'function returns "One"; the current value of "FirstVariable" in the Collection
End Function
Private Sub setCollectionValue(collect As Collection, key As String, value As String)
On Error Resume Next
collect.Remove key
On Error GoTo 0
collect.Add value, key
End Sub

an efficient way acess a range in a user defined type?

I've got a user defined type with about 5000 entries. I would like to select a range of the data in about 1,000 entry blocks and use it as an array. Is there a way to do this without looping?
Something like
MyArray = MyType(1:1000).property
rather than
for i = 1 to 1000
MyArray(i) = MyType(i).property
Next i
Thanks!
No, there is no way to convert a collection of elements into an array without looping or special accessor methods for the type - let alone convert a common property from a collection of elements into an array.
The only objects that support anything like this are Range objects, for which you can convert certain properties of an array of cells (range) into an array using:
MyArray = Range("A1:A1000").Value
Again, nothing like this is available for other types unless the programmer goes through the trouble of defining the behaviour - and even if they did define it, odds are the method would likely include iterating over the elements anyways, just within the type class.

Resources