Как можно ближе к вашему коду:
Function ShiftVector(rng As Range, n As Long)
Dim i As Long, nr As Long, b() As Variant
nr = rng.Rows.Count
ReDim b(nr, 1) As Variant
For i = 1 To n
b(nr - n + i, 1) = rng.Cells(i, 1)
Next i
For i = n + 1 To nr
b(i - n, 1) = rng.Cells(i, 1)
Next i
ShiftVector = b()
End Function
Дополнительные подсказки
Предполагая, что приведенный выше вопрос является упражнением, вы можете рассматривать приведенный выше код как обучающий шанс и сравните его с исходным кодом. Как правило, я бы предпочел, чтобы подход @ScottCraner проходил через двумерный массив, который не так требует времени , как цикл через диапазон с помощью VBA, по крайней мере, для больших наборов данных.
Лучше объявлять счетчики для таких данных как Long
вместо Integer
, поскольку строки сегодняшнего диапазона (1048576, ранее 65k) намного превышают ограничение целочисленных данных (от -32,768 до 32,767).
Вам не нужно транспонировать массив b
, поскольку он уже двумерный и может быть вставлен как вертикальный набор данных.
Предложение по улучшению
Вы можете назначить весь набор данных в 2-мерный (на основе 1) массив, например, как показано ниже
Dim tmp As Variant
tmp = rng.Value
Изменяя смещение диапазона, вы можете автоматически сдвинуть основную часть данных (с сохранением того же размера диапазона) :
tmp = rng.Offset(n).Value
Это позволяет вам повторно ввести только n
данные «обернуть» до конца предварительно заполненного массива tmp
:
Пример функции
Function SV(rng As Range, n As Long)
'a) get main part (starting n rows higher)
Dim tmp As Variant
tmp = rng.Offset(n) ' shift up vertically (by n rows)
'b) get "wrap around" part of n first rows
Dim wrap
wrap = rng.Resize(n, 1) ' assign to temporary array
'c) enter "wrap around" values to n bottom rows
Dim i As Long
For i = 1 To n
tmp(UBound(tmp) - n + i, 1) = wrap(i, 1)
Next i
'c) return rearranged array as function result
SV = tmp
End Function