VBA
Копирование, возврат и передача массивов
Поиск…
Копирование массивов
Вы можете скопировать массив VBA в массив того же типа, используя оператор =
. Массивы должны быть одного типа, иначе код будет генерировать ошибку компиляции «Can not assign to array».
Dim source(0 to 2) As Long
Dim destinationLong() As Long
Dim destinationDouble() As Double
destinationLong = source ' copies contents of source into destinationLong
destinationDouble = source ' does not compile
Исходный массив может быть фиксированным или динамическим, но целевой массив должен быть динамическим. Попытка скопировать в фиксированный массив вызовет ошибку компиляции «Can not assign to array». Любые существующие данные в принимающем массиве теряются, а его границы и размеры изменяются так же, как исходный массив.
Dim source() As Long
ReDim source(0 To 2)
Dim fixed(0 To 2) As Long
Dim dynamic() As Long
fixed = source ' does not compile
dynamic = source ' does compile
Dim dynamic2() As Long
ReDim dynamic2(0 to 6, 3 to 99)
dynamic2 = source ' dynamic2 now has dimension (0 to 2)
Как только копия сделана, два массива являются отдельными в памяти, то есть две переменные не являются ссылками на одни и те же базовые данные, поэтому изменения, внесенные в один массив, не отображаются в другом.
Dim source(0 To 2) As Long
Dim destination() As Long
source(0) = 3
source(1) = 1
source(2) = 4
destination = source
destination(0) = 2
Debug.Print source(0); source(1); source(2) ' outputs: 3 1 4
Debug.Print destination(0); destination(1); destination(2) ' outputs: 2 1 4
Копирование массивов объектов
С массивами объектов копируются ссылки на эти объекты, а не сами объекты. Если изменение в объекте в одном массиве будет также изменено в другом массиве - они оба ссылаются на один и тот же объект. Однако установка элемента в другой объект в одном массиве не приведет его к этому объекту в другом массиве.
Dim source(0 To 2) As Range
Dim destination() As Range
Set source(0) = Range("A1"): source(0).Value = 3
Set source(1) = Range("A2"): source(1).Value = 1
Set source(2) = Range("A3"): source(2).Value = 4
destination = source
Set destination(0) = Range("A4") 'reference changed in destination but not source
destination(0).Value = 2 'affects an object only in destination
destination(1).Value = 5 'affects an object in both source and destination
Debug.Print source(0); source(1); source(2) ' outputs 3 5 4
Debug.Print destination(0); destination(1); destination(2) ' outputs 2 5 4
Варианты, содержащие массив
Вы также можете скопировать массив в переменную варианта и из нее. При копировании из варианта он должен содержать массив того же типа, что и принимающий массив, иначе он будет вызывать ошибку «Ошибка несоответствия типа».
Dim var As Variant
Dim source(0 To 2) As Range
Dim destination() As Range
var = source
destination = var
var = 5
destination = var ' throws runtime error
Возвращаемые массивы из функций
Функция в нормальном модуле (но не модуле класса) может возвращать массив, помещая ()
после типа данных.
Function arrayOfPiDigits() As Long()
Dim outputArray(0 To 2) As Long
outputArray(0) = 3
outputArray(1) = 1
outputArray(2) = 4
arrayOfPiDigits = outputArray
End Function
Результат функции можно затем поместить в динамический массив того же типа или варианта. К элементам также можно получить доступ, используя второй набор скобок, однако это вызовет функцию каждый раз, поэтому лучше сохранить результаты в новом массиве, если вы планируете использовать их более одного раза
Sub arrayExample()
Dim destination() As Long
Dim var As Variant
destination = arrayOfPiDigits()
var = arrayOfPiDigits
Debug.Print destination(0) ' outputs 3
Debug.Print var(1) ' outputs 1
Debug.Print arrayOfPiDigits()(2) ' outputs 4
End Sub
Обратите внимание, что возвращаемое на самом деле является копией массива внутри функции, а не ссылкой. Поэтому, если функция возвращает содержимое массива Static, его данные не могут быть изменены процедурой вызова.
Вывод массива через выходной аргумент
Обычно это хорошая практика кодирования для аргументов процедуры как входных данных и для вывода через возвращаемое значение. Однако ограничения VBA иногда требуют, чтобы процедура выводила данные через аргумент ByRef
.
Вывод в фиксированный массив
Sub threePiDigits(ByRef destination() As Long)
destination(0) = 3
destination(1) = 1
destination(2) = 4
End Sub
Sub printPiDigits()
Dim digits(0 To 2) As Long
threePiDigits digits
Debug.Print digits(0); digits(1); digits(2) ' outputs 3 1 4
End Sub
Вывод массива из метода класса
Выходной аргумент также может использоваться для вывода массива из метода / процедуры в модуле класса
' Class Module 'MathConstants'
Sub threePiDigits(ByRef destination() As Long)
ReDim destination(0 To 2)
destination(0) = 3
destination(1) = 1
destination(2) = 4
End Sub
' Standard Code Module
Sub printPiDigits()
Dim digits() As Long
Dim mathConsts As New MathConstants
mathConsts.threePiDigits digits
Debug.Print digits(0); digits(1); digits(2) ' outputs 3 1 4
End Sub
Передача массивов на прохождение
Массивы могут передаваться в процедуры, помещая ()
после имени переменной массива.
Function countElements(ByRef arr() As Double) As Long
countElements = UBound(arr) - LBound(arr) + 1
End Function
Массивы должны передаваться по ссылке. Если не указан какой-либо передающий механизм, например myFunction(arr())
, то VBA будет считать ByRef
по умолчанию, однако хорошая практика кодирования делает его явным. Попытка передать массив по значению, например myFunction(ByVal arr())
приведет к ошибке компиляции «Array argument должно быть ByRef» (или ошибке компиляции «Синтаксическая ошибка», если Auto Syntax Check
не проверена в параметрах VBE) ,
Передача по ссылке означает, что любые изменения в массиве будут сохранены в процессе вызова.
Sub testArrayPassing()
Dim source(0 To 1) As Long
source(0) = 3
source(1) = 1
Debug.Print doubleAndSum(source) ' outputs 8
Debug.Print source(0); source(1) ' outputs 6 2
End Sub
Function doubleAndSum(ByRef arr() As Long)
arr(0) = arr(0) * 2
arr(1) = arr(1) * 2
doubleAndSum = arr(0) + arr(1)
End Function
Если вы хотите избежать изменения исходного массива, будьте осторожны, чтобы написать функцию, чтобы она не меняла никаких элементов.
Function doubleAndSum(ByRef arr() As Long)
doubleAndSum = arr(0) * 2 + arr(1) * 2
End Function
Альтернативно создайте рабочую копию массива и работайте с копией.
Function doubleAndSum(ByRef arr() As Long)
Dim copyOfArr() As Long
copyOfArr = arr
copyOfArr(0) = copyOfArr(0) * 2
copyOfArr(1) = copyOfArr(1) * 2
doubleAndSum = copyOfArr(0) + copyOfArr(1)
End Function