View Full Version : Getting max value from a dictionary
cblake843
11-29-2018, 06:25 AM
With the below code I am trying to simply get the max value of y and x after they have been added to a dictionary. The y and x values are integers and generated as part of a function which works fine. I had it working and then crashed without saving it , now I can't recall how it happened.
My code :-
When printing the max it simply takes the current value of y or x. When doing dictionary.count it's always 1 so doesn't appear to appending the data correcty to the dictionary
Dim dict As Object
Set dict = CreateObject("Scripting.Dictionary")
Dict.Add y, x
For Each i In dict
Debug.Print i
Debug.Print application.max(i)
Next i
Tried the below but the max value is being overwritten can't see how or where
Dim key As Variant
Dim dict As Dictionary
Set dict = New Dictionary
dict.Add y, x
For Each key In dict.Keys
Debug.Print "Value X: " & dict.Item(key), "Max X:" & Application.Max(dict.Item(key))
Debug.Print "Key Y: " & key, "Max Y:" & Application.Max(key)
Next
Paul_Hossler
11-29-2018, 08:02 AM
Assuming that the key is not the same as the data something like this
Option Explicit
Sub test()
Dim dict As Object
Dim i As Long, y As Long, x As Long, iMax As Long
Dim v As Variant
Set dict = CreateObject("Scripting.Dictionary")
' i is the Key, 10i is the Data
For i = 1 To 10
dict.Add i, 10 * i
Next
For Each v In dict.items
Debug.Print v
If v > iMax Then iMax = v
Next
MsgBox iMax
End Sub
or this if the key and the data are the same
Sub test2()
Dim dict As Object
Dim i As Long, y As Long, x As Long, iMax As Long
Dim v As Variant
Set dict = CreateObject("Scripting.Dictionary")
' i is the Key and the Data
For i = 1 To 10
dict.Add i, i
Next
For Each v In dict.items
Debug.Print v
Next
MsgBox Application.WorksheetFunction.Max(dict.keys)
End Sub
cblake843
11-29-2018, 11:51 PM
Assuming that the key is not the same as the data something like this
Option Explicit
Sub test()
Dim dict As Object
Dim i As Long, y As Long, x As Long, iMax As Long
Dim v As Variant
Set dict = CreateObject("Scripting.Dictionary")
' i is the Key, 10i is the Data
For i = 1 To 10
dict.Add i, 10 * i
Next
For Each v In dict.items
Debug.Print v
If v > iMax Then iMax = v
Next
MsgBox iMax
End Sub
or this if the key and the data are the same
Sub test2()
Dim dict As Object
Dim i As Long, y As Long, x As Long, iMax As Long
Dim v As Variant
Set dict = CreateObject("Scripting.Dictionary")
' i is the Key and the Data
For i = 1 To 10
dict.Add i, i
Next
For Each v In dict.items
Debug.Print v
Next
MsgBox Application.WorksheetFunction.Max(dict.keys)
End Sub
Thanks , one point that does not work is that Y is already declared as an integer , when I replace i for y in your code I still don't get a max value only a current value.
What am I doing wrong ?
cblake843
11-30-2018, 01:28 AM
I think I see what is happening now. The dictionary is only 1 line (row) , for some reason it is getting reset therefore it only contains one at a time. Anyway around this ?
BTW y is an integer from another fuction which contains values such as
30 , 60 , 90 , 120 , 200 but then can start again 20 , 40 , 80 etc. I want all this data in a dictionary (or container) and obtain the largest value.
Dim dict As Object
Dim i As Long, iMax As Long
Dim v As Variant
Set dict = CreateObject("Scripting.Dictionary")
For i = 1 To 2
dict.Add i, y
Next
For Each v In dict.Items
Debug.Print v
Next
Debug.Print "MAX :" & Application.WorksheetFunction.Max(dict.Item(1))
Debug.Print "MAX1 :"; dict.Items()(UBound(dict.Items))
Aflatoon
11-30-2018, 02:40 AM
Application.Max(dict.Items())
and
Application.Max(dict.Keys())
should work.
Schau mal erst: http://www.snb-vba.eu/VBA_Dictionary_en.html
Sub M_snb()
with createobject("scripting.dictionary")
for j=1 to 25
x0=.Item(j*20)
next
msgbox application.max(.keys)
end with
End Sub
cblake843
11-30-2018, 03:07 AM
This doesn't work as the dictionary is being overwritten , so at any 1 time it only contains one value. My understanding is the dictionary should contain all values written to it. It's not clear why this is happening.
cblake843
11-30-2018, 03:09 AM
The main issue is the dictionary only contains 1 value (row) , it appears to be overwritten on each iteration. I have no idea why this is doing it
cblake843
11-30-2018, 03:16 AM
Sub M_snb() with createobject("scripting.dictionary")
for j=1 to 25
x0=.Item(j*20)
next
msgbox application.max(.keys)
end with End Sub.
Assignment to constant not permitted
Please copy the code properly into your workbook
cblake843
11-30-2018, 04:50 AM
Please copy the code properly into your workbook
which code exactly ?
Aflatoon
11-30-2018, 09:19 AM
Given that you haven't posted the full code that actually populates your dictionary, it will be fairly difficult to fix that for you. ;)
cblake843
11-30-2018, 10:31 AM
Given that you haven't posted the full code that actually populates your dictionary, it will be fairly difficult to fix that for you. ;)
Thanks for the reply and I see your point I will post the full code Monday! To summarize the posted code is within a sub where ‘y’ gets updated on each pass. Why it is not incrementally added to the dictionary but instead it overwrites the value. Should I set the dict in a spereate function or sub ! This is causing me a big headache!
Aflatoon
11-30-2018, 10:42 AM
Yes you should. You're creating a new one at each iteration currently.
cblake843
11-30-2018, 10:59 AM
Yes you should. You're creating a new one at each iteration currently.
Any coding hints how to do this? Create the dict in a separate sub or function ? And then add to it from the main routine?
Paul_Hossler
11-30-2018, 11:53 AM
If you mean that there could be duplicate Keys and you only want one instance to that Key, with the largest Data then
Option Explicit
Sub test()
Dim dict As Object
Dim K As Long, D As Long, iMax As Long
Dim v As Variant
Set dict = CreateObject("Scripting.Dictionary")
' K is the Key, D is the Data
For K = 1 To 10
D = 1000 * Rnd
If dict.exists(K) Then
If D > dict(K) Then dict(K) = D
Else
dict.Add K, D
End If
Next
For Each v In dict.items
Debug.Print D
If v > iMax Then iMax = v
Next
MsgBox iMax
End Sub
This makes the index number the Key, so you can have the same Data
Sub test1()
Dim dict As Object
Dim K As Long, D As Long, iMax As Long
Dim v As Variant
Set dict = CreateObject("Scripting.Dictionary")
' K is the Key, D is the Data
For K = 1 To 1000
D = 1000 * Rnd
dict.Add CStr(dict.Count), D
'purposely adding duplicate data
dict.Add CStr(dict.Count), D
dict.Add CStr(dict.Count), D
dict.Add CStr(dict.Count), D
Next
For Each v In dict.items
Debug.Print v
If v > iMax Then iMax = v
Next
MsgBox iMax
End Sub
Maybe more details and an example would help
cblake843
12-03-2018, 01:42 AM
So i created this function and is called from another sub
Call mydict(inputer, y)
When I try to access it I get errors sub or function not defined.
Debug.Print "KEY" & dict(Key)
Debug.Print "MAX" & Application.Max(Items
Public Function mydict(inputer, y)
Dim dict As Scripting.Dictionary
Set dict = New Scripting.Dictionary
dict.Add inputer, y
End Function
What's missing ?
Aflatoon
12-03-2018, 02:01 AM
That's not going to help you as you're still creating a new dictionary each time, and your variable is local to the function.
I suggest you post your code that is trying to loop and populate the dictionary.
cblake843
12-03-2018, 02:09 AM
Here is the main sub. I want to write the values of y on each iteration and store them in a dictionary to be accessed at the end of the sub.
Private Sub CalculateCoordinates(sThread, node As IXMLDOMNode)
Dim parent_node As IXMLDOMNode, x As Integer, y As Integer, y_max_branch As Integer, nList As IXMLDOMNodeList
Dim StepId As String, strXpath As String
Dim inputer, inputer2, inputer3, inputer4 As String
Dim stry As String
*******************Call dict(inputer, y)
Call AddCoordinates(node, x, y)
End Sub
As mentioned I've tried a separate function but this does not work. Any suggestions are most appreicated
Why do you ignore all apparently not so much appreciated suggestions in this thread ?
cblake843
12-03-2018, 02:36 AM
Why do you ignore all apparently not so much appreciated suggestions in this thread ?
I haven't ignored any of them , in fact I have tried everything suggested yet I still have a dictionary that is overwritten each line and can't get a max value as a result.
The problem is where to create the dictionary so that I do not create a new one each time I write to it?
cblake843
12-03-2018, 02:41 AM
Why do you ignore all apparently not so much appreciated suggestions in this thread ?
I have not ignored the suggestions , in fact I have tried each and everyone extensively without success
Aflatoon
12-03-2018, 04:14 AM
There is no looping at all in what you posted - why did you remove it? It makes it much harder to help you if you won't post your code. Declare and instantiate the dictionary before whatever your loop is, then add the items to it inside the loop.
cblake843
12-03-2018, 05:15 AM
There is no looping at all in what you posted - why did you remove it? It makes it much harder to help you if you won't post your code. Declare and instantiate the dictionary before whatever your loop is, then add the items to it inside the loop.
Thanks for the reply , where should I declare and insttantiate the dictionary exactly ? If i declare it like this :-
Public Sub collz()
Dim dict As Dictionary
Set dict = New Dictionary
End Sub
The sub where I want to write to it and access
dict.Add inputer, y says object not defined etc
Aflatoon
12-03-2018, 05:28 AM
Declare it in the routine with the loop that populates it.
cblake843
12-03-2018, 05:38 AM
Why do you ignore all apparently not so much appreciated suggestions in this thread ?
But is the whole problem ,it then creates a new dictionary each time where it only retains 1 line. It is then not possible to get a max value with only one line
Da Capo al Fine:
Sub M_snb()
with createobject("scripting.dictionary")
for j=1 to 25
x0=.Item(j*20)
next
msgbox application.max(.keys)
end with
End Sub
Paul_Hossler
12-03-2018, 08:32 AM
But is the whole problem ,it then creates a new dictionary each time where it only retains 1 line. It is then not possible to get a max value with only one line
Just taking a wild guess here, I'd suspect that you're doing something wrong
My post 16 has two different approaches depending on what you're trying to do
Both will add new lines to the dictionary and both will print out the max
If you can't get it to work, you'd better post a sample workbook with whatever code you have and a description of what it is you are trying to accomplish
cblake843
12-03-2018, 10:33 AM
Da Capo al Fine:
Sub M_snb()
with createobject("scripting.dictionary")
for j=1 to 25
x0=.Item(j*20)
next
msgbox application.max(.keys)
end with
End Sub
I’ve already tried something similar(see previous post) , I’m trying to write the value of y to a dict? Currently it overwrites the dict so there is only 1 line in the dict. All I need to do is create the dict in another sub but can’t quite get the code working. Any suggestions ?
cblake843
12-03-2018, 10:38 AM
Just taking a wild guess here, I'd suspect that you're doing something wrong
My post 16 has two different approaches depending on what you're trying to do
Both will add new lines to the dictionary and both will print out the max
If you can't get it to work, you'd better post a sample workbook with whatever code you have and a description of what it is you are trying to accomplish
Yeah thanks, it was very good example by didn’t work for my issue. How can I declare the dict outside of the sub so it doesn’t just write one line overwriting each time?
Paul_Hossler
12-03-2018, 11:58 AM
Did you try making it a Module Level variable?
This version keeps a max number of keys = 10
If you want to keep on adding, then use the second approach in my #16
Option Explicit
'module level variable
Dim dict As Object
Sub test()
Dim v As Variant
Dim iMax As Long
If dict Is Nothing Then
Set dict = CreateObject("Scripting.Dictionary")
End If
Call test2(10)
Call test2(12)
Call test2(15)
For Each v In dict.items
If v > iMax Then iMax = v
Next
MsgBox iMax
Set dict = Nothing
End Sub
Private Sub test2(N As Long)
Dim K As Long, D As Long
' K is the Key, D is the Data
For K = 1 To 10
D = N * Rnd
If dict.exists(K) Then
If D > dict(K) Then dict(K) = D
Else
dict.Add K, D
End If
Next
End Sub
Did you try making it a Module Level variable?
fyi, related:
http://www.vbaexpress.com/forum/showthread.php?64151-VBA-save-a-variable-when-criteria-is-met&p=386060&viewfull=1#post386060
cblake843
12-04-2018, 01:30 AM
Did you try making it a Module Level variable?
This version keeps a max number of keys = 10
If you want to keep on adding, then use the second approach in my #16
Option Explicit
'module level variable
Dim dict As Object
Sub test()
Dim v As Variant
Dim iMax As Long
If dict Is Nothing Then
Set dict = CreateObject("Scripting.Dictionary")
End If
Call test2(10)
Call test2(12)
Call test2(15)
For Each v In dict.items
If v > iMax Then iMax = v
Next
MsgBox iMax
Set dict = Nothing
End Sub
Private Sub test2(N As Long)
Dim K As Long, D As Long
' K is the Key, D is the Data
For K = 1 To 10
D = N * Rnd
If dict.exists(K) Then
If D > dict(K) Then dict(K) = D
Else
dict.Add K, D
End If
Next
End Sub
Thanks , I can see how it will work but not for my issue. I want the dictionary to be populated by the below sub and also accessed each pass in the same sub. I need it to take the value of y from the callcoordinates sub below
Private Sub CalculateCoordinates(sThread, node As IXMLDOMNode)
Dim parent_node As IXMLDOMNode, x As Integer, y As Integer, y_max_branch As Integer, nList As IXMLDOMNodeList
Dim StepId As String, strXpath As String
Dim inputer, inputer2, inputer3, inputer4 As String
Dim stry As String
Call AddCoordinates(node, x, y)
End Sub
Paul_Hossler
12-04-2018, 08:46 AM
Thanks , I can see how it will work but not for my issue. I want the dictionary to be populated by the below sub and also accessed each pass in the same sub. I need it to take the value of y from the callcoordinates sub below
I'm struggling to see why it would NOT work
Again, if you attach a sample workbook showing what you start with and what you want to do it will be easier
cblake843
12-05-2018, 02:42 AM
So for the routine I posted in 33 , where should i define the dicitonary (i.e not in the SUB as it creates a new one each time) and where to write to it and where to access it? When I define the dictionary outside of the sub , i get errors like object required etc etc . I can't post the whole workbook.
Paul_Hossler
12-05-2018, 07:41 AM
So for the routine I posted in 33 , where should i define the dicitonary (i.e not in the SUB as it creates a new one each time) and where to write to it and where to access it? When I define the dictionary outside of the sub , i get errors like object required etc etc . I can't post the whole workbook.
1. Yes
2. Use CreateObject() in the right place to create a single instance of dict
3. Make a small sample workbook with your macros and some sample data that does show the problem and post that
Powered by vBulletin® Version 4.2.5 Copyright © 2025 vBulletin Solutions Inc. All rights reserved.