Reducing time in Excel's VBA

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • kadghar
    Recognized Expert Top Contributor
    • Apr 2007
    • 1302

    Reducing time in Excel's VBA

    When it comes to work with Excel's VBA, many people face 'huge' (and i mean it) speed issues. This issues are very common when reading/writing data from/to a worksheet inside a loop.

    Reading and writing from Excel to VBA (and vice versa) is a slow task, and the only solution to get through this problem is to reduce the times it is done.

    An easy way out is to use a Variant. When you asign a Range to a Variant, the Variant wont become a Variant/Range, but a 2 dimension Array with the Range's values (great! ^.^). While doing this, you'll only read the data (Range) once. Also, when you asign an Array to a Range, the Range will take the Array's values. This way, you'll only have to write the data once.

    I think the easiest way to understand it will be with a little example:

    I'll write two columns of 20,000 random numbers in a sheet, then read those numbers and write its product in a third column. Example A will do it using FOR/NEXT to write the numbers, to read them and to write the product. Example B will do it using array's to write, read and write again (the product).

    I'll take the time each example takes to acomplish (using a 990mhz, 256 ram, old computer)

    [CODE=vb]Sub ExampleA()
    Dim t As Single
    Dim i As Long
    t = Timer
    With Worksheets(1)
    'STEP 1: Create the list
    For i = 1 To 20000
    .Cells(i, 1) = Rnd
    .Cells(i, 2) = Rnd
    Next
    'STEP 2: Read the list, write the product
    For i = 1 To 20000
    .Cells(i, 3) = .Cells(i, 2) * .Cells(i, 2)
    Next
    End With
    MsgBox "Example A took " & Timer - t & " seconds."
    End Sub[/CODE]

    It took 14.5625 secs

    [CODE=vb]Sub ExampleB()
    Dim t As Single
    Dim Var1 As Variant
    Dim Arr1() As Double, Arr2() As Double
    t = Timer
    With Worksheets(2)
    'STEP 1: Create the list
    ReDim Arr1(1 To 2000, 1 To 2)
    For i = 1 To UBound(Arr1)
    Arr1(i, 1) = Rnd
    Arr1(i, 2) = Rnd
    Next
    Range(.Cells(1, 1), .Cells(UBound(A rr1), 2)) = Arr1
    'STEP 2: Read the list, write the product
    Var1 = Range(.Cells(1, 1), .Cells(UBound(A rr1), 2))
    ReDim Arr2(1 To UBound(Var1), 1 To 1)
    For i = 1 To UBound(Var1)
    Arr2(i, 1) = Var1(i, 1) * Var1(i, 2)
    Next
    Range(.Cells(1, 3), .Cells(UBound(A rr2), 3)) = Arr2
    End With
    MsgBox "Example B took " & Timer - t & " seconds."
    End Sub[/CODE]
    It took 8.98 x 10^-2 seconds (0.0898 secs)

    after this, we can conclude:

    Example B is 166 times faster than Example A, and it does exactly the same thing.

    My only suggestion: Do not use Cells or Range references inside a loop.

    Kad.

    For editors corner: any comment or sugestion, be welcome
  • asedt
    New Member
    • Jun 2008
    • 130

    #2
    Hi, intresting usfull to know for some applications.

    Fast computers make us lazy :P

    Is it not true that the faster version needs memory to save the array, so in bigger aplications that can be a lot of memmory needed. (Me thinking something like 20 columns * ~ 12 avrage number of chars * 20.000 rows = 4.8 MB)

    In som smaller applications the speed is not that important with todays computers. (as long as the macro takes less than 5 sec to complete anyway).

    One solution is maybe to take them in "chunks" like 1000 rows at the time or something so you have balence in number of writes/ memmory usage and then you need to use some math for calculating how to do to get best preformance and base it on the platform.

    Comment

    • kadghar
      Recognized Expert Top Contributor
      • Apr 2007
      • 1302

      #3
      yes!!! ^.^

      that's exactly the point. memory management is like roads, garages and cars...

      the variables and arrays you have in your RAM are the roads, the things you write in tables are the garages, and your iformation are the cars.

      if you only move one car from one garage to another each time, you'll be able to move it quite fast, but it'll take years to move all your cars.

      if you move all your cars at once, you'll have Manhantan and nobody will get anywhere.

      you should always look forward an optimum point where you can move many cars each time and move them fast.

      when this method is not used propertly, you'll have this NY case.

      or even worse, have you seen this simpsons' chapter where mr. burns has many many diseases?? (ok, if you have, you'll understand what i mean)

      Comment

      • asedt
        New Member
        • Jun 2008
        • 130

        #4
        Originally posted by kadghar
        yes!!! ^.^
        that's exactly the point.
        Good, then all I said wasn’t rubbish. Can't remember if I have seen that episode, will need to scan my memory...

        Comment

        Working...