Копирование значений из диапазона ячеек в массив и обратно с помощью VBA Excel. Простейшие примеры обмена значениями между диапазоном и массивом.
Как известно, VBA обрабатывает информацию в массивах значительно быстрее, чем в ячейках рабочего листа Excel. Поэтому, при работе с большими объемами данных, удобнее использовать массивы, чем наблюдать во время выполнения кода за мерцанием изображения на экране или просто смотреть в неизменную картинку, если обновление экрана отключено (Application.ScreenUpdating = False). Здесь обмен значениями между массивом и диапазоном ячеек будет вполне уместен.
Копирование значений из диапазона ячеек в массив
Чтобы скопировать значения из диапазона ячеек в массив, необходимо объявить переменную универсального типа (As Variant) и присвоить ей значения диапазона ячеек с помощью оператора присваивания (=):
Dim a As Variant a = Range(«A1:C3») |
VBA Excel автоматически преобразует объявленную переменную в двумерный массив, соответствующий размерности диапазона ячеек, в нашем случае в массив — a(1 To 3, 1 To 3), и заполняет его значениями. Нумерация измерений массивов, созданных таким образом, начинается с единицы (1).
Можно, в этом случае, объявить сразу динамический массив, чтобы изначально указать, что эта переменная будет массивом. Так как свойством диапазона ячеек по умолчанию в VBA Excel является значение (Value), его можно в коде явно не указывать, но, при желании, можно и указать. Получится такая конструкция, аналогичная первой:
Dim a() As Variant a = Range(«A1:C3»).Value |
Стоит отметить, что для копирования значений из диапазона ячеек в массив можно использовать только обычную переменную или динамический массив универсального типа (Variant). VBA Excel автоматически преобразовывает их в двумерный массив. Если объявить двумерный массив с указанной заранее размерностью, использовать его не получится, будет сгенерирована ошибка с сообщением: Can’t assign to array (Нельзя назначать массив).
Копирование значений из массива в диапазон ячеек
Значения в диапазон ячеек добавляются из массива с помощью оператора присваивания (=):
Range(«A6:F15») = a ‘или Range(«A6:F15»).Value = a ‘где a — переменная двумерного массива |
Обратите внимание, что вставить значения в диапазон ячеек можно только из двумерного массива. Размерность такого массива может начинаться с нуля (0). Количество элементов в измерениях массива должно совпадать с количеством строк и столбцов в диапазоне ячеек. Если вам нужно вставить значения в одну строку или в один столбец, укажите размерность единственной строки или единственного столбца как (0) или (1 To 1), если вы хотите использовать нумерацию измерений своего массива с единицы. Например, для записи десяти значений из массива в одну строку можно объявить такой массив — massiv(9, 0), или в один столбец — massiv(0, 9).
Для вставки значений в диапазон ячеек из массива идеально подойдет массив, созданный для копирования в него значений из диапазона. В этом случае, данные с рабочего листа Excel переносятся в массив, обрабатываются и, после обработки, вставляются обратно в ту же или другую таблицу на том же или другом рабочем листе.
Обмен значениями между двумя диапазонами
Обмен значениями можно осуществить в VBA Excel не только между массивом и диапазоном, но и между двумя диапазонами одинаковой размерности:
Range(«B2:D6») = Range(«G7:I11»).Value |
У диапазона, являющегося источником значений, обязательно должно быть указано свойство Value
.
Если диапазон ячеек, принимающий значения, по размеру меньше диапазона-источника, то он будет заполнен полностью:
Range(«B2:D6») = Range(«G5:L13»).Value |
Если принимающий диапазон ячеек по размеру больше передающего, то часть его будет заполнена значениями диапазона-источника, а остальные ячейки — значениями #Н/Д
:
Range(«B2:D6») = Range(«G7:H9»).Value |
Простейшие примеры обмена значениями
Эти примеры составлены так, чтобы вам не пришлось совершать лишних действий, просто скопируйте их в свой модуль любой книги Excel с поддержкой макросов и запустите по очереди на выполнение.
Пример 1
Заполнение двумерного массива значениями и и их присвоение диапазону ячеек на рабочем листе Excel:
Sub Test1() Dim a(2, 2) As Variant a(0, 0) = «телепузик» a(0, 1) = «журналист» a(0, 2) = «ящерица» a(1, 0) = «короед» a(1, 1) = «утенок» a(1, 2) = «шмель» a(2, 0) = 200 a(2, 1) = 300 a(2, 2) = 400 Range(«A1:C3»).Value = a End Sub |
В данном случае переменная массива не обязательно должна быть универсального типа (As Variant), например, если бы в нее записывались только текстовые данные, ее можно было бы объявить как строковую (As String), и все бы работало.
Пример 2
Объявление обычной переменной универсального типа, присвоение ей значений из диапазона ячеек «A1:C3», записанных кодом первого примера, и вставка этих значений из полученного двумерного массива в диапазон «D10:F12»:
Sub Test2() Dim a As Variant a = Range(«A1:C3») Range(«D10:F12») = a End Sub |
Естественно, указанные диапазоны ячеек расположены на активном листе.
Пример 3
Допустим, на рабочем листе «Лист1» в ячейках «A1:A5» записано количество какого-то товара, а в ячейках «B1:B5» — его цена. Необходимо к этой информации добавить сумму каждого товара, умножив количество на цену, и перенести данные на «Лист2».
Sub Test3() Dim a As Variant, i As Long a = Лист1.Range(«A1:C5») For i = 1 To 5 a(i, 3) = a(i, 1) _ * a(i, 2) Next Лист2.Range(«A1:C5») = a End Sub |
Массив создан сразу с размерностью 5×3 с элементами под суммы. Даже если на первом листе в ячейках «C1:C5» есть какие-то значения, в массиве они будут перезаписаны результатами вычислений.
Копирование значений из массива в массив
Этот пример показывает, как в VBA Excel можно скопировать значения из одного массива в другой:
Sub Test4() Dim arr1, arr2 arr1 = Range(«G7:I11») arr2 = arr1 Range(«B2:D6») = arr2 End Sub |
Using the shape of the Range
Another approach in creating a function for ArrayFromRange
would be using the shape and size of the Range to determine how we should structure the array. This way we don’t have to load the data into an intermediate array to determine the dimension.
For instance, if the target range is only one cell, then we know we want to return an array with the single value in it Array(target.value)
.
Below is the complete function that should deal with all cases. Note, this uses the same technique of using the Application.Transpose
method to reshape the array.
' Helper function that returns an array from a range with the
' correct dimensions. This fixes the issue of single values
' not returning as an array, and when a 2 dimension array is returned
' when it only has 1 dimension of data.
'
' @author Robert Todar <robert@roberttodar.com>
Public Function ArrayFromRange(ByVal target As Range) As Variant
Select Case True
' Single cell
Case target.Cells.Count = 1
ArrayFromRange = Array(target.Value)
' Single Row
Case target.Rows.Count = 1
ArrayFromRange = Application.Transpose( _
Application.Transpose(target.Value) _
)
' Single Column
Case target.Columns.Count = 1
ArrayFromRange = Application.Transpose(target.Value)
' Multi dimension array
Case Else
ArrayFromRange = target.Value
End Select
End Function
Testing the ArrayFromRange
function
As a bonus, here are the tests that I ran to check that this function works.
' @requires {function} ArrayDimensionLength
' @requires {function} ArrayCount
Private Sub testArrayFromRange()
' Setup a new workbook/worksheet for
' adding testing data
Dim testWorkbook As Workbook
Set testWorkbook = Workbooks.Add
Dim ws As Worksheet
Set ws = testWorkbook.Worksheets(1)
' Add sample data for testing.
ws.Range("A1:A2") = Application.Transpose(Array("A1", "A2"))
ws.Range("B1:B2") = Application.Transpose(Array("B1", "B2"))
' This section will run all the tests.
Dim x As Variant
' Single cell
x = ArrayFromRange(ws.Range("A1"))
Debug.Assert ArrayDimensionLength(x) = 1
Debug.Assert ArrayCount(x) = 1
' Single Row
x = ArrayFromRange(ws.Range("A1:B1"))
Debug.Assert ArrayDimensionLength(x) = 1
Debug.Assert ArrayCount(x) = 2
' Single Column
x = ArrayFromRange(ws.Range("A1:A2"))
Debug.Assert ArrayDimensionLength(x) = 1
Debug.Assert ArrayCount(x) = 2
' Multi Column
x = ArrayFromRange(ws.Range("A1:B2"))
Debug.Assert ArrayDimensionLength(x) = 2
Debug.Assert ArrayCount(x) = 4
' Cleanup testing environment
testWorkbook.Close False
' Print result
Debug.Print "testArrayFromRange: PASS"
End Sub
Helper functions for the tests
In my tests I used two helper functions: ArrayCount
, and ArrayDimensionLength
. These are listed below for reference.
' Returns the length of the dimension of an array
'
' @author Robert Todar <robert@roberttodar.com>
Public Function ArrayDimensionLength(sourceArray As Variant) As Integer
On Error GoTo catch
Do
Dim currentDimension As Long
currentDimension = currentDimension + 1
' `test` is used to see when the
' Ubound throws an error. It is unused
' on purpose.
Dim test As Long
test = UBound(sourceArray, currentDimension)
Loop
catch:
' Need to subtract one because the last
' one errored out.
ArrayDimensionLength = currentDimension - 1
End Function
' Get count of elements in an array regardless of
' the option base. This Looks purely at the size
' of the array, not the contents within them such as
' empty elements.
'
' @author Robert Todar <robert@roberttodar.com>
' @requires {function} ArrayDimensionLength
Public Function ArrayCount(ByVal sourceArray As Variant) As Long
Dim dimensions As Long
dimensions = ArrayDimensionLength(sourceArray)
Select Case dimensions
Case 0
ArrayCount = 0
Case 1
ArrayCount = (UBound(sourceArray, 1) - LBound(sourceArray, 1)) + 1
Case Else
' Need to set arrayCount to 1 otherwise the
' loop will keep multiplying by zero for each
' iteration
ArrayCount = 1
Dim dimension As Long
For dimension = 1 To dimensions
ArrayCount = ArrayCount * _
((UBound(sourceArray, dimension) - LBound(sourceArray, dimension)) + 1)
Next
End Select
End Function
Return to VBA Code Examples
In this Article
- Assign Range to Array
- Assign Value From a Single Column
- Assign value from multiple columns
This tutorial will demonstrate how to populate an array with a range of cells.
Assign Range to Array
We can easily populate a Variant array with a range of cells.
Assign Value From a Single Column
This example will loop through Range(“A1:A10”), assigning the the cell values to an array:
Sub TestArrayValuesSingle()
'Declare the array as a variant array
Dim arRng() As Variant
'Declare the integer to store the number of rows
Dim iRw As Integer
'Assign range to a the array variable
arRng = Range("A1:A10")
'loop through the rows - 1 to 10
For iRw = 1 To UBound(arRng)
'show the result in the immediate window
Debug.Print arRng(iRw , 1)
Next iRw
End Sub
The UBound is used to set the array upper bound (eg 10) so that the loop knows to loop 10 times.
The Debug.Print function will show you the value contained in the array in the immediate window.
Assign value from multiple columns
Sub TestArrayValuesMultiple()
'Declare the array as a variant array
Dim arRng() As Variant
'Declare the integer to store the number of rows
Dim iRw As Integer
'Declare the integer to store the number of columns
Dim iCol as Integer
'Assign range to a the array variable
arRng = Range("A1:C10")
'loop through the rows - 1 to 10
For iRw = 1 To UBound(arRng,1)
'now - while in row 1, loop through the 3 columns
For iCol = 1 to UBound(arRng,2)
'show the result in the immediate window
Debug.Print arRng(iRw, iCol)
Next iCol
Next iRw
End Sub
In the code above, we have populated the array with the values in Range(“A1:C10”).
The UBound is once again used – but this time it is needed twice – once to loop through the rows, and then again to loop through the columns.
The Debug.Print function will show you the value contained in the array in the immediate window.
VBA Coding Made Easy
Stop searching for VBA code online. Learn more about AutoMacro — A VBA Code Builder that allows beginners to code procedures from scratch with minimal coding knowledge and with many time-saving features for all users!
Learn More!
VBA Arrays And Worksheet Ranges
This page describes how to transfer data between VBA arrays and worksheet ranges.
Data transfer between worksheet cells and VBA variables is an expensive operation
that should be kept to a minimum. You can considerably increase the performance of your Excel application
by passing arrays of data to the worksheet, and vice versa, in a single operation rather
than one cell at a time. If you need to do extensive calculations on data in VBA,
you should transfer all the values from the worksheet to an array, do the calculations
on the array, and then, possibly, write the array back to the worksheet. This keeps the number
of times data is transferred between the worksheet and VBA to a minimum. It is far more
efficient to transfer one array of 100 values to the worksheet than to transfer 100 items at a time.
This page shows you how to transfer data between worksheet cells and VBA ararys.
You will find that with large amounts of data being transferred between the
worksheet and the array, working with the array is much faster than working
directly with worksheet cells.
It is very simple to read a range on a worksheet and put it into an array
in VBA. For example,
Dim Arr() As Variant Arr = Range("A1:C5")
When you bring in data from a worksheet to a VBA array, the array is always
2 dimensional. The first dimension is the rows and the second dimension is
the columns. So, in the example above, Arr is implicitly sized as
Arr(1 To 5, 1 To 3) where 5 is the number of rows and
3 is the number of columns. A 2 dimensional array is created even if the worksheet data
is in a single row or a single column (e.g, Arr(1 To 10, 1 To 1)).
The array into which the worksheet data is loaded always has an lower bound
(LBound) equal to 1, regardless of what Option Base
directive you may have in your module. You cannot change this behavior. For example,
Dim Arr() As Variant Arr = Range("A1:A10")
Here, Arr is dimensioned automatically by VBA as Arr(1 to 10,
1 To 1).
You can use code like the following to loop through the array of the worksheet values:
Dim Arr() As Variant Arr = Range("A1:B10") Dim R As Long Dim C As Long For R = 1 To UBound(Arr, 1) For C = 1 To UBound(Arr, 2) Debug.Print Arr(R, C) Next C Next R
There is a special case when the range on the worksheet is a single cell. Expanding on the code above,
you should use the code below if it is possible that the range is a single cell:
Dim Arr() As Variant Dim RangeName As String Dim R As Long Dim C As Long Dim RR As Range RangeName = "TheRange" Set RR = Range(RangeName) If RR.Cells.Count = 1 Then ReDim Arr(1 To 1, 1 To 1) Arr(1, 1) = RR.Value Else Arr = Range(RangeName) End If
Once you have calculated an array with the appropriate values, you
can write it back to the worksheet. The array may be 1 or 2 dimensional.
To write a one dimensional array back to the worksheet, you must create a
Range object, resize that range to the size of your
array, and then write to the range.
Suppose we have a one dimensional array and want to write that out to the worksheet starting
at cell K1. The code must first resize the destination range. For
example,
Dim Destination As Range Set Destination = Range("K1") Set Destination = Destination.Resize(1, UBound(Arr)) Destination.Value = Arr
This code will write the values of Arr to range that is
one row tall by UBound(Arr) columns wide, starting at
range K1. If you want the results passed to a range that is
one column wide spanning several rows, use code like the following to resize the range
and set the values.
Dim Destination As Range Set Destination = Range("K1") Set Destination = Destination.Resize(UBound(Arr), 1) Destination.Value = Application.Transpose(Arr)
NOTE that the parameters to Resize are reversed and that
the array Arr is transposed before being written to the worksheet.
If you have a 2 dimensional array, you need to use Resize to
resize the destination range to the proper size. The first dimension is the number of rows
and the second dimension is the number of columns. The code below illustrates writing an array
Arr out to the worksheet starting at cell K1.
Dim Destination As Range Set Destination = Range("K1") Destination.Resize(UBound(Arr, 1), UBound(Arr, 2)).Value = Arr
You can transpose the array when writing to the worksheet:
Set Destination = Range("K1") Destination.Resize(UBound(Arr, 2), UBound(Arr, 1)).Value = Application.Transpose(Arr)
Here, the parameters to Resize are reversed and the array
Arr is transposed.
When you read from a worksheet to an array variable, VBA will automatically size
the array to hold the range on the worksheet. You don’t have to concern yourself
with sizing the array. However, when writing an array from VBA to the worksheet,
you must resize the destination range to hold the array. We saw this earlier in
the examples. Basically, you use code like the following.
Dim NumRows As Long Dim NumCols As Long NumRows = UBound(Arr,1) - LBound(Arr,1) + 1 NumCols = UBound(Arr,2) - LBound(Arr,2) + 1 Set Destination = Range("K1").Resize(NumRows, NumCols).Value = Arr
If the array being passed to the worksheet is smaller than the Range to which it is written, the
unused cells get a #N/A error. If the array being passed is larger than
the range to which it is written, the array is truncated on the right or bottom to fit the range.
As you’ve seen in the examples, passing array between the worksheet and VBA is really quite simple. Used correctly,
the code snippets above can have a strong effect on increasing the performance of your VBA application.
This page last updated: 13-September-2012. |
Home / VBA / Arrays / VBA Range to an Array
Steps to Add a Range into an Array in VBA
- First, you need to declare a dynamic array using the variant data type.
- Next, you need to declare one more variable to store the count of the cells from the range and use that counter for the loop as well.
- After that, assign the range where you have value to the array.
- From here, we need to create a loop to print all the values to the immediate window so that you can see that all the values are assigned to the array.
Sub myArrayRange()
Dim iAmount() As Variant
Dim iNum As Integer
iAmount = Range("A1:A11")
For iNum = 1 To UBound(iAmount)
Debug.Print iAmount(iNum, 1)
Next iNum
End Sub
And when you run the above code it shows you all the values you have assigned from the range (“A1:A11) to the array iAmount and prints it to the immediate window.
In the same way, you can also use a multi-dimensional array.
Sub myArrayRange()
Dim iAmount() As Variant
Dim iNum1 As Integer
iAmount = Range("A1:B13")
For iNum1 = 1 To UBound(iAmount, 1)
Debug.Print iAmount(iNum1, 1) & " " & iAmount(iNum1, 2)
Next iNum1
End Sub
Or you can also do this way as well.
Sub myArrayRange()
Dim iAmount() As Variant
Dim iNum1 As Integer
Dim iNum2 As Integer
iAmount = Range("A1:B13")
For iNum1 = 1 To UBound(iAmount, 1)
For iNum2 = 1 To UBound(iAmount, 2)
Debug.Print iAmount(iNum1, iNum2)
Next iNum2
Next iNum1
End Sub