excel vba array formulas code example
Example 1: vba array from worksheet data
'In Excel VBA, the quickest way to pull data from a worksheet into a VBA array
'is to do it all at once:
Dim v As Variant
v = Range("a1:b20").Value
'Please note that, here, 'v' is a scalar variable of type Variant. Scalar means
'that 'v' is NOT an array. But interestingly in this case, 'v' can be
'treated exactly like an array. To understand why, please keep reading...
'Variant variables can be assigned many types of values, for example,
'all of the following (and many others) are valid:
v = 123
v = 12.19971
v = "abcdefg"
Set v = New Collection
'IN ADDITION, a Variant can also be assigned an entire array, dynamic or static:
Dim v As Variant, arr() As Long
ReDim arr(1 to 4)
arr(1) = 11
arr(2) = 12
arr(3) = 13
arr(4) = 14
v = vArrA
'Now that the array of Longs 'arr' has been assigned to the Variant 'v', we can
'access the elements directly from 'v':
MsgBox v(4) '<--displays: 14
'A very efficient way to read data from a worksheet range is to directly assign
'the data to a Variant by having that variable point to an array of Variants:
v = Sheet1.Range("a1:b20").Value
'The 'Value' property of the Range object creates a 2D array of Variant
'elements the same size as the specified range, in this case,
'20 rows of 2 columns, with a lower bound of 1 for both array dimensions.
'Here, we assign that array directly to the scalar Variant 'v', all in one go.
'The scalar Variant 'v' can now be treated as an array, even though it is
'actually a scalar variable that points to an array THAT WAS NEVER NAMED:
MsgBox v(2, 20) '<--displays: the value that was in Sheet1, cell B20
'As long as the worksheet range consists of more than one cell, this method
'always results in an array and that array is always 2D. It is never 1D.
'If the range consists of only ONE cell, then this method does NOT create an
'array; instead, it assigns that one cell's scalar value to the Variant 'v'.
'This one-cell treatment must bo gaurded against.
'However, this shortcut method of copying Excel ranges to VBA arrays is
'very convienent and its use is common. The advantage is not only
'extremely concise code; this technique is much faster than copying
'cell-by-cell... and the speed improvement grows with the size of
'the range being copied.
'The code can even be shortened:
v = [Sheet1!a1:b20]
'The square brackets are a shorthand notation for VBA's Evaluate() function.
'This shorthand produces exactly the same results as the previous example,
'because the Evaluate() function returns a Range object in this instance and
'the default property of the Range object is the 'Value' property.
'In the above examples, the Range object is returning its
'default... the Range.Value property. But keep in mind that the
'Range.Value2 property is roughly 20% quicker. So it slightly more
'performant to code these two examples like so:
v = [Sheet1!a1:b20].Value2
v = Sheet1.Range("a1:b20").Value2
'Important: the array created using the 'Value' or 'Value2' properties
' is completely detached from the source range on the
' worksheet. Either can be updated and the changes will NOT
' affect the other.
'Note: VBA utilizes the OLE/COM SAFEARRAY data structure for its
' array implementation:
' https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-oaut/2e87a537-9305-41c6-a88b-b79809b3703a
' https://ecs.syr.edu/faculty/fawcett/Handouts/cse775/presentations/BruceMcKinneyPapers/safeArrays.htm
' http://www.roblocher.com/whitepapers/oletypes.html
'
'
'
Example 2: excel vba reset array to zeros fastest way
'In VBA to reset a dynamic array of Longs or Doubles to all zeros, the simplest way
'is to use the Redim() function. It's also extremely fast, roughly four times
'faster than iterating over the array to set each element.
Sub Test_ArrayZeroing()
Dim i&, k&, a() As Long
Dim time1#, time2#
k = 100000000 '<--100 million elements
ReDim a(1 To k)
For i = 1 To k: a(i) = i: Next '<--Fill array
time1 = Timer
'For i = 1 To k: a(i) = 0: Next '<--Method 1: 1125 ms
ReDim a(1 To k) '<--Method 2: 260 ms (easy and faster)
time2 = Timer
Debug.Print "Test_ArrayZeroing: " & (time2 - time1) * 1000
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'If you are willing to use an external call to Windows then an much faster
'method exists:
Private Declare PtrSafe Sub AssignZero Lib "kernel32" Alias "RtlZeroMemory" (pDst As Any, Optional ByVal CB& = 4)
Sub Test_ArrayZeroing()
Dim i&, k&, a() As Long
Dim time1#, time2#
k = 100000000 '<--100 million elements
ReDim a(1 To k)
For i = 1 To k: a(i) = i: Next '<--Fill array
time1 = Timer
'For i = 1 To k: a(i) = 0: Next '<--Method 1: 1125 ms
'ReDim a(1 To k) '<--Method 2: 260 ms
AssignZero a(1), k * 4 '<--Method 3: 74 ms (super fast)
time2 = Timer
Debug.Print "Test_ArrayZeroing: " & (time2 - time1) * 1000
End Sub
'Note that when using AssignZero() with an array of Doubles, remember that
'Doubles require 8 bytes of memory each, as opposed to the 4 bytes required
'for Longs.
'So the call to AssinZero() would like this for and array of Doubles:
AssignZero a(1), k * 8
'Note that the first argument of AssignZero() should be the first element
'of the array to be reset to zeros. The lowerbound in the above examples is 1,
'but your array may have a lowerbound of 0... or some other number.
'Note that all three methods here work for arrays of Longs and Doubles. But to
'zero out an array of Variants, the only option is Method 1. This is because
'the default value for a Variant is EMPTY, not zero... and AssignZero() will
'not work because Variants store and require metadata in addition to
'the value... and that metadata would be wiped out by AssignZero().
'Note that to reset an array to some value other than zero, the only
'option is to use Method 1.
'Note that this entire post is about Dynamic arrays. If you wish to zero out a Static
'array of Longs or Doubles you may also use the 'Erase' statement:
Erase a
'
'
'