+ Reply to Thread
Results 1 to 22 of 22

Scripting.Dictionary Code Returning Incorrect Results

Hybrid View

NeedForExcel Scripting.Dictionary Code... 07-21-2015, 12:59 AM
NeedForExcel Re: Scripting.Dictionary Code... 07-21-2015, 01:10 AM
Kyle123 Re: Scripting.Dictionary Code... 07-21-2015, 01:41 AM
NeedForExcel Re: Scripting.Dictionary Code... 07-21-2015, 02:07 AM
skywriter Re: Scripting.Dictionary Code... 07-21-2015, 01:46 AM
NeedForExcel Re: Scripting.Dictionary Code... 07-21-2015, 02:09 AM
skywriter Re: Scripting.Dictionary Code... 07-21-2015, 02:25 AM
skywriter Re: Scripting.Dictionary Code... 07-21-2015, 02:23 AM
Kyle123 Re: Scripting.Dictionary Code... 07-21-2015, 02:28 AM
jindon Re: Scripting.Dictionary Code... 07-21-2015, 02:38 AM
skywriter Re: Scripting.Dictionary Code... 07-21-2015, 02:54 AM
NeedForExcel Re: Scripting.Dictionary Code... 07-21-2015, 03:09 AM
NeedForExcel Re: Scripting.Dictionary Code... 07-21-2015, 02:58 AM
Kyle123 Re: Scripting.Dictionary Code... 07-21-2015, 03:16 AM
skywriter Re: Scripting.Dictionary Code... 07-21-2015, 03:33 AM
Kyle123 Re: Scripting.Dictionary Code... 07-21-2015, 03:33 AM
Kyle123 Re: Scripting.Dictionary Code... 07-21-2015, 03:41 AM
skywriter Re: Scripting.Dictionary Code... 07-21-2015, 03:53 AM
bakerman2 Re: Scripting.Dictionary Code... 07-21-2015, 04:46 AM
NeedForExcel Re: Scripting.Dictionary Code... 07-21-2015, 04:53 AM
NeedForExcel Re: Scripting.Dictionary Code... 07-21-2015, 05:03 AM
bakerman2 Re: Scripting.Dictionary Code... 07-21-2015, 05:44 AM
  1. #1
    Forum Expert NeedForExcel's Avatar
    Join Date
    03-16-2013
    Location
    Pune, India
    MS-Off Ver
    Excel 2016:2019, MS 365
    Posts
    3,879

    Scripting.Dictionary Code Returning Incorrect Results

    Hi,

    I am trying out this code on the attached file -

    Sub ScrpDict()
    
        Dim Dict As Scripting.Dictionary, R As Variant
        Set Dict = New Scripting.Dictionary
        
        With Dict
            For Each R In Range("A2:A17")
                If R <> "" Then .Item(R) = Empty
            Next R
            MsgBox .Count
        End With
        
    End Sub
    However, even when I am using the .Item() property, it is still not returning unique values.

    I want to get the unique values on the D Column..
    Attached Files Attached Files
    Cheers!
    Deep Dave

  2. #2
    Forum Expert NeedForExcel's Avatar
    Join Date
    03-16-2013
    Location
    Pune, India
    MS-Off Ver
    Excel 2016:2019, MS 365
    Posts
    3,879

    Re: Scripting.Dictionary Code Returning Incorrect Results

    Got it..

    For Each R In Range("A2:A17") should have been For Each R In Range("A2:A17").Value

    Marking the thread solved..

  3. #3
    Forum Guru Kyle123's Avatar
    Join Date
    03-10-2010
    Location
    Leeds
    MS-Off Ver
    365 Win 11
    Posts
    7,239

    Re: Scripting.Dictionary Code Returning Incorrect Results

    You also need to check whether the key already exists or you'll start running into errors

  4. #4
    Forum Expert NeedForExcel's Avatar
    Join Date
    03-16-2013
    Location
    Pune, India
    MS-Off Ver
    Excel 2016:2019, MS 365
    Posts
    3,879

    Re: Scripting.Dictionary Code Returning Incorrect Results

    Quote Originally Posted by Kyle123 View Post
    You also need to check whether the key already exists or you'll start running into errors
    But wouldn't using .item() replace the key if it already existed?

    I also wanted to know the best way (Avoiding Loops) to spit out these unique values to say column F!
    Last edited by NeedForExcel; 07-21-2015 at 02:10 AM.

  5. #5
    Forum Expert skywriter's Avatar
    Join Date
    06-09-2014
    Location
    USA
    MS-Off Ver
    365 Version 2409
    Posts
    2,789

    Re: Scripting.Dictionary Code Returning Incorrect Results

    You could also write it this way.

    You will not get an error if the key exists if written in this form.

    The way you wrote it originally will not error if the key exists either.

    Sub ScrpDict()
    
        Dim Dict As Scripting.Dictionary, R As Range
        Set Dict = New Scripting.Dictionary
        
        With Dict
            For Each R In Range("A2:A17")
                If R.Value <> "" Then .Item(R.Value) = Empty
            Next R
            MsgBox .Count
        End With
      End Sub
    Last edited by skywriter; 07-21-2015 at 01:49 AM.

  6. #6
    Forum Expert NeedForExcel's Avatar
    Join Date
    03-16-2013
    Location
    Pune, India
    MS-Off Ver
    Excel 2016:2019, MS 365
    Posts
    3,879

    Re: Scripting.Dictionary Code Returning Incorrect Results

    Quote Originally Posted by skywriter View Post
    You could also write it this way.
    So does R.Value & only R makes the difference?

    I also wanted to know the best way (Avoiding Loops) to spit out these unique values to say column F!

  7. #7
    Forum Expert skywriter's Avatar
    Join Date
    06-09-2014
    Location
    USA
    MS-Off Ver
    365 Version 2409
    Posts
    2,789

    Re: Scripting.Dictionary Code Returning Incorrect Results

    But wouldn't using .item() replace the key if it already existed?
    Remember with this method what you are doing is manipulating the item. You are saying with the item that belongs to this key, change the value of the item.

    If the key doesn't exist it adds it and gives the value you state to the item.

    If it does exist you are only saying change the value of the item that is paired with this already existing key.
    Last edited by skywriter; 07-21-2015 at 02:28 AM.

  8. #8
    Forum Expert skywriter's Avatar
    Join Date
    06-09-2014
    Location
    USA
    MS-Off Ver
    365 Version 2409
    Posts
    2,789

    Re: Scripting.Dictionary Code Returning Incorrect Results

    You could use transpose, but transpose has a limit of 65,536 rows. If you have less than that you are okay.

    Sub ScrpDict()
    
        Dim Dict As Scripting.Dictionary, R As Range
        Set Dict = New Scripting.Dictionary
        
        With Dict
            For Each R In Range("A2:A17")
                If R.Value <> "" Then .Item(R.Value) = Empty
            Next R
            MsgBox .Count
        End With
        Range("B1").Resize(Dict.Count, 1) = Application.Transpose(Dict.keys)
        
      End Sub
    Last edited by skywriter; 07-21-2015 at 02:27 AM.

  9. #9
    Forum Guru Kyle123's Avatar
    Join Date
    03-10-2010
    Location
    Leeds
    MS-Off Ver
    365 Win 11
    Posts
    7,239

    Re: Scripting.Dictionary Code Returning Incorrect Results

    The biggest bottleneck is that you're looping through a range. Loops aren't bad, looping through worksheet cells is, every time you access the worksheet, it's like hitting the brakes in a car.

    Also don't loop through arrays with a for each x in y construct, use that for collections, for arrays you should be using for x to y and accessing by index.

    Finally as sky writer says, you can use transpose but ymmv it tends to be slow (much slower than a loop for large data sets) and has limits on the number of values it will transpose.

    Re the item, yes but that's not a good thing really. Everytime you update or add to a dictionary I think it re-indexes (which isn't good for performance) that's why it has an exists property so you can check before adding something

  10. #10
    Forum Guru
    Join Date
    08-15-2004
    Location
    Tokyo, Japan
    MS-Off Ver
    2013 O.365
    Posts
    22,834

    Re: Scripting.Dictionary Code Returning Incorrect Results

    NeedForExcel

    Remember, when you loop though the range with Dictionary, you can not avoid Value property.
    .Item(R.Value) = Empty

  11. #11
    Forum Expert skywriter's Avatar
    Join Date
    06-09-2014
    Location
    USA
    MS-Off Ver
    365 Version 2409
    Posts
    2,789

    Re: Scripting.Dictionary Code Returning Incorrect Results

    After Kyle's post I did a little experiment.

    I copied some data with lots of duplicates all the way down to 1 million rows.

    I ran my original code that did not check if the key exists.
    I did not time it, but I would guess that it took around 3 seconds.

    I then ran the .exists code on the same 1 million rows and I would guess it took just under 2 seconds.

    I then put everything in an array and looped the array with the .exists and it was very fast. I would guess under a second.

    Kyle thanks for the information.
    Last edited by skywriter; 07-21-2015 at 02:58 AM.

  12. #12
    Forum Expert NeedForExcel's Avatar
    Join Date
    03-16-2013
    Location
    Pune, India
    MS-Off Ver
    Excel 2016:2019, MS 365
    Posts
    3,879

    Re: Scripting.Dictionary Code Returning Incorrect Results

    Quote Originally Posted by skywriter View Post
    I then put everything in an array and looped the array with the .exists and it was very fast. I would guess under a second.
    Can you post the code that used array along with the .exists method?

  13. #13
    Forum Expert NeedForExcel's Avatar
    Join Date
    03-16-2013
    Location
    Pune, India
    MS-Off Ver
    Excel 2016:2019, MS 365
    Posts
    3,879

    Re: Scripting.Dictionary Code Returning Incorrect Results

    @ skywriter - Perfect! Thank you for clarifying yet again..

    @ jindon - Thank you for this very important input.. I'll remember that..

    @ Kyle123 -

    The biggest bottleneck is that you're looping through a range
    So are you saying this isnt the best method? (Dont consider the Hard Coded range. I'v done that just for convenience while learning)

    For Each R In Range("A2:A17")
          If R.Value <> "" Then .Item(R.Value) = Empty
    Next R
    you can use transpose but ymmv it tends to be slow
    So which method if not transpose is best?

    Thank you for the input guys.. You guys are awesome..

  14. #14
    Forum Guru Kyle123's Avatar
    Join Date
    03-10-2010
    Location
    Leeds
    MS-Off Ver
    365 Win 11
    Posts
    7,239

    Re: Scripting.Dictionary Code Returning Incorrect Results

    I'd do it like this, bear in mind most of these optimisations are not noticeable on small data sets:
    Sub ScrpDict()
    
        Dim Dict As Scripting.Dictionary
        Dim R As Variant, keys As Variant
        Dim x As Long
        
        Set Dict = New Scripting.Dictionary
        
        R = Sheets(1).Range("A2:A101").Value2 'Value2 is faster than .Value
        
        With Dict
            For x = LBound(R) To UBound(R) 'Loop through Arrays by index
                If Len(R(x, 1)) > 0 And Not .Exists(R(x, 1)) Then 'Check whether the element exists
                    .Add R(x, 1), Nothing 'Could also be empty
                End If
            Next x
        End With
        
        ReDim R(1 To Dict.Count, 1 To 1) 'Create an array to write to the sheet
        keys = Dict.keys() 'Get the keys
        
        For x = LBound(keys) To UBound(keys) 'Manual transpose to keys to a 2d array
            R(x + 1, 1) = keys(x)
        Next x
        
        Sheets(2).Range("A1").Resize(UBound(R), 1).Value2 = R 'Write the keys to a range
        
    End Sub
    Last edited by Kyle123; 07-21-2015 at 03:24 AM.

  15. #15
    Forum Expert skywriter's Avatar
    Join Date
    06-09-2014
    Location
    USA
    MS-Off Ver
    365 Version 2409
    Posts
    2,789

    Re: Scripting.Dictionary Code Returning Incorrect Results

    I'd do it like this, bear in mind most of these optimisations are not noticeable on small data sets
    I have a sheet with a million rows, it ran very fast.

    I ran it 3 times.
    0.61, 0.62 and 0.61 seconds.
    Last edited by skywriter; 07-21-2015 at 03:35 AM.

  16. #16
    Forum Guru Kyle123's Avatar
    Join Date
    03-10-2010
    Location
    Leeds
    MS-Off Ver
    365 Win 11
    Posts
    7,239

    Re: Scripting.Dictionary Code Returning Incorrect Results

    Did you change the range at the top?

  17. #17
    Forum Guru Kyle123's Avatar
    Join Date
    03-10-2010
    Location
    Leeds
    MS-Off Ver
    365 Win 11
    Posts
    7,239

    Re: Scripting.Dictionary Code Returning Incorrect Results

    No problem ,tanks for the rep

  18. #18
    Forum Expert skywriter's Avatar
    Join Date
    06-09-2014
    Location
    USA
    MS-Off Ver
    365 Version 2409
    Posts
    2,789

    Re: Scripting.Dictionary Code Returning Incorrect Results

    Did you change the range at the top?
    Here's the code wrapped by the timer code. I don't know how accurate this timer code is, but I consistently get 0.61 and 0.62 on a million rows of data. It's very fast.

    Sub CalculateRunTime_Seconds()
    'PURPOSE: Determine how many seconds it took for code to completely run
    'SOURCE: www.TheSpreadsheetGuru.com/the-code-vault
    
    Dim StartTime As Double
    Dim SecondsElapsed As Double
    
    'Remember time when macro starts
      StartTime = Timer
     Dim Dict As Scripting.Dictionary
        Dim R As Variant, keys As Variant
        Dim x As Long
        
        Set Dict = New Scripting.Dictionary
      
        R = Sheets(1).Range("A1:A1000000").Value2 'Value2 is faster than .Value
        
        With Dict
            For x = LBound(R) To UBound(R) 'Loop through Arrays by index
                If R(x, 1) <> "" And Not .Exists(R(x, 1)) Then 'Check whether the element exists
                    .Add R(x, 1), Nothing 'Could also be empty
                End If
            Next x
        End With
        
        ReDim R(1 To Dict.Count, 1 To 1) 'Create an array to write to the sheet
        keys = Dict.keys() 'Get the keys
        
        For x = LBound(keys) To UBound(keys) 'Manual transpose to keys to a 2d array
            R(x + 1, 1) = keys(x)
        Next x
        
        Sheets(2).Range("A1").Resize(UBound(R), 1).Value2 = R 'Write the keys to a range
    
    
    'Determine how many seconds code took to run
      SecondsElapsed = Round(Timer - StartTime, 2)
    
    'Notify user in seconds
      MsgBox "This code ran successfully in " & SecondsElapsed & " seconds", vbInformation
    
    End Sub
    Last edited by skywriter; 07-21-2015 at 03:58 AM.

  19. #19
    Forum Guru bakerman2's Avatar
    Join Date
    10-03-2012
    Location
    Antwerp, Belgium
    MS-Off Ver
    MSO Home and Business 2024
    Posts
    7,359

    Re: Scripting.Dictionary Code Returning Incorrect Results

    For a little more accuracy I always use this for timing.
    Private Declare Function getFrequency Lib "kernel32" _
    Alias "QueryPerformanceFrequency" (cyFrequency As Currency) As Long
    Private Declare Function getTickCount Lib "kernel32" _
    Alias "QueryPerformanceCounter" (cyTickCount As Currency) As Long
    
    Function MicroTimer() As Double
    ' Returns seconds.
        Dim cyTicks1 As Currency
        Static cyFrequency As Currency
        MicroTimer = 0
    ' Get frequency.
        If cyFrequency = 0 Then getFrequency cyFrequency
    ' Get ticks.
        getTickCount cyTicks1
    ' Seconds
        If cyFrequency Then MicroTimer = cyTicks1 / cyFrequency
    End Function
    Use like
    Sub tst()
        dTime = MicroTimer
        For i = 1 To 10000
            DoEvents
        Next
        dTime = MicroTimer - dTime
        dTime = Round(dTime, 3)
        MsgBox CStr(dTime) & " Seconds", _
            vbOKOnly + vbInformation, "CalcTimer"
    End Sub
    where the For...Next replaces the code you want to execute.

    'Source: http://msdn.microsoft.com/en-us/libr...ffice.12).aspx
    Last edited by bakerman2; 07-21-2015 at 04:49 AM.

  20. #20
    Forum Expert NeedForExcel's Avatar
    Join Date
    03-16-2013
    Location
    Pune, India
    MS-Off Ver
    Excel 2016:2019, MS 365
    Posts
    3,879

    Re: Scripting.Dictionary Code Returning Incorrect Results

    @ skywriter, Kyle, Jindon & bakerman2 - Thank you all for the inputs..

    I'll study the code given by Kyle & Skywriter.

    Cheers Guys!

    Marking the thread solved, and adding reps..

  21. #21
    Forum Expert NeedForExcel's Avatar
    Join Date
    03-16-2013
    Location
    Pune, India
    MS-Off Ver
    Excel 2016:2019, MS 365
    Posts
    3,879

    Re: Scripting.Dictionary Code Returning Incorrect Results

    @Kyle - I ran your code on a million rows...

    It is insanely fast..

  22. #22
    Forum Guru bakerman2's Avatar
    Join Date
    10-03-2012
    Location
    Antwerp, Belgium
    MS-Off Ver
    MSO Home and Business 2024
    Posts
    7,359

    Re: Scripting.Dictionary Code Returning Incorrect Results

    Performing actions in memory is a technique I already use several years.
    Run FillRange and then LoopMemory.
    Run FillRange again and then run LoopCells. See the difference. I only took 500000 otherwise you have the time to get a cup of coffee when running LoopCells.
    Private Declare Function getFrequency Lib "kernel32" _
    Alias "QueryPerformanceFrequency" (cyFrequency As Currency) As Long
    Private Declare Function getTickCount Lib "kernel32" _
    Alias "QueryPerformanceCounter" (cyTickCount As Currency) As Long
    
    Function MicroTimer() As Double
    ' Returns seconds.
        Dim cyTicks1 As Currency
        Static cyFrequency As Currency
        MicroTimer = 0
    ' Get frequency.
        If cyFrequency = 0 Then getFrequency cyFrequency
    ' Get ticks.
        getTickCount cyTicks1
    ' Seconds
        If cyFrequency Then MicroTimer = cyTicks1 / cyFrequency
    End Function
    
    Sub FillRange()
    Dim sn(1 To 500000, 1 To 1)
    For i = 1 To 500000
        sn(i, 1) = "AB"
    Next
    Range("A1").Resize(UBound(sn)) = sn
    
    End Sub
    
    Sub LoopMemory()
    dTime = MicroTimer
    sn = Sheets(1).Columns(1).SpecialCells(2)
        For i = 1 To UBound(sn)
            sn(i, 1) = sn(i, 1) & "C"
        Next
    Range("A1").Resize(UBound(sn)) = sn
    dTime = MicroTimer - dTime
    dTime = Round(dTime, 3)
    MsgBox CStr(dTime) & " Seconds", _
        vbOKOnly + vbInformation, "CalcTimer"
    End Sub
    
    Sub LoopCells()
    dTime = MicroTimer
        For Each R In Sheets(1).Columns(1).SpecialCells(2)
                R.Value = R.Value & "C"
        Next R
    
    
    dTime = MicroTimer - dTime
    dTime = Round(dTime, 3)
    MsgBox CStr(dTime) & " Seconds", _
        vbOKOnly + vbInformation, "CalcTimer"
    End Sub

+ Reply to Thread

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Similar Threads

  1. [SOLVED] VBA Scripting.Dictionary Code Late Binding Error
    By NeedForExcel in forum Excel Programming / VBA / Macros
    Replies: 20
    Last Post: 07-20-2015, 03:06 AM
  2. Cant get data to populate in VBA code from array & scripting dictionary
    By leanne2011 in forum Excel Programming / VBA / Macros
    Replies: 4
    Last Post: 05-25-2015, 04:38 AM
  3. need help with scripting dictionary
    By leanne2011 in forum Excel Programming / VBA / Macros
    Replies: 22
    Last Post: 10-04-2014, 04:33 PM
  4. Sum function returning incorrect results
    By Elena.P in forum Excel Formulas & Functions
    Replies: 2
    Last Post: 08-16-2013, 01:26 PM
  5. [SOLVED] Scripting Dictionary help
    By williams485 in forum Excel Programming / VBA / Macros
    Replies: 7
    Last Post: 12-13-2012, 08:22 AM
  6. [SOLVED] VLOOKUP returning incorrect results
    By Jennsy in forum Excel Formulas & Functions
    Replies: 3
    Last Post: 11-01-2012, 03:08 PM
  7. Replies: 6
    Last Post: 04-05-2011, 09:27 AM

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts

Search Engine Friendly URLs by vBSEO 3.6.0 RC 1