VBA developers often need to read data in from Ranges and write results out to other Ranges. It’s a very common task in dashboards for example. The snag is that reading or writing 1 cell at a time can be slow, especially if you have a lot of input or output to deal with. However there are ways to work more efficiently with large tables.
Example 1 – Reading Ranges
Let’s say you’ve need to read some data from A1:A1000 on a worksheet into an array. One way to do this is as follows:
For i = 1 To 1000 MyArray1(i) = Range("A" & i).Value Next
However it’s actually very easy to achieve almost the same thing in 1 simple line of code:
MyArray2 = Range("A1:A1000").Value
There is a catch but – in my opinion – it’s a minor one. MyArray2 will actually have 2 dimensions, whereas MyArray1 is constructed with 1. In this example, MyArray2 will have the following bounds:
Dimension 1 ~ 1 To 1000 (representing the row)
Dimension 2 ~ 1 To 1 (single column)
So instead of using MyArray1(i) you now use MyArray2(i, 1). The speed boost can be significant and this next example should help to illustrate the point.
Example 2 – Writing Ranges
Create a blank spreadsheet and coopy the following macro into a blank Module. The idea is that in our code we first do some calculations and store the results in an array. When the code finishes, that array is displayed in cells on a worksheet. Obviously my example calculations are very simple but you could replace them with anything you wish.
Sub test() Const rMax As Long = 1000 'total rows Const cMax As Long = 100 'total columns Dim t As Single 'used to time how long each version takes Dim v As Variant 'array containing results of my calculations Dim r As Long 'row counter Dim c As Long 'column counter 'This is my "calculation routine" ... ReDim v(1 To rMax, 1 To cMax) For r = 1 To rMax For c = 1 To cMax v(r, c) = r + c Next Next 'Now let's create the output ... 'The slow version! Cells.Clear t = Timer 'start the timer For r = 1 To rMax For c = 1 To cMax Cells(r, c).Value = v(r, c) Next Next MsgBox "Slow version took " & Round(Timer - t, 1) & " seconds" 'Quick version Cells.Clear t = Timer 'restart the timer Range("A1").Resize(rMax, cMax).Value = v MsgBox "Quick version took " & Round(Timer - t, 1) & " seconds" End Sub
On my PC I got the following messages:
Slow version took 5.4 seconds
Quick version took 0.1 seconds
..see what the comparison is on your machine.
(As a final note, if you do output these results 1 cell at a time then you may not need to store the results in an array at all. I’ve only structured it like this so I can directly compare the time taken creating outputs. In doing so, I hope this illustrates that there are occasions when this might be a good thing to do!)