Как преодолеть ограничения ReDim Preserve
в многомерных массивах
Как уже упоминалось @ScottCraner, ReDim Preserve
может изменить только последнее измерение данного массива (поля данных) , Поэтому попытка изменить размер первого измерения 2-мерного массива (= "строки") завершится неудачей.
Однако вы можете преодолеть это неудобство, применив относительно неизвестную возможность фильтрации Application.Index()
(c .f. секция [2]
) и прибыль от дополнительного бонуса за меньшее количество петель.
Дополнительная информация: см. Некоторые особенности Application.Index()
функция
Sub GetRowsEqual10000()
With Sheet1
Dim lastRow As Long: lastRow = .Range("A" & .Rows.Count).End(xlUp).Row
Dim rng As Range: Set rng = .Range("A2:F" & lastRow)
End With
'[1] get data
Dim data: data = rng
'[2] rearrange data via Application.Index() instead ReDim Preserve plus loops
data = Application.Index(data, ValidRows(data, Condition:=10000), Array(1, 2, 3, 4, 5, 6))
End Sub
функция справки ValidRows
()
Function ValidRows(arr, Condition) As Variant
'Purpose: a) check condition (e.g. values equalling 10000) and b) get valid row numbers c) in a 2-dim vertical array
ReDim tmp(1 To UBound(arr)) ' provide for 1-based 2-dim array
Dim i As Long, ii As Long
For i = 1 To UBound(arr) ' loop through 1st "column"
If arr(i, 1) = Condition Then ' a) check condition
ii = ii + 1: tmp(ii) = i ' b) collect valid row numbers
End If
Next i
ReDim Preserve tmp(1 To ii) ' resize tmp array (here the 1st dimension is also the last one:)
ValidRows = Application.Transpose(tmp) ' c) return transposed result as 2-dim array
End Function
Редактировать в соответствии с комментарием (2020- 04-22)
Краткие указания на наиболее частое использование Application.Index()
:
Часто функция Application.Index()
используется для получения целой строки или массив столбцов из 2-мерного массива без необходимости l oop.
Для доступа к массиву двухмерных полей данных на основе 1, например, требуется указать один номер строки или столбца и установите для столбца соседнего аргумента или номера строки значение 0
(ноль), соответственно, что может привести, например, к
Dim horizontal, vertical, RowNumber As Long, ColumnNumber As Long
RowNumber = 17: ColumnNumber = 4
horizontal = Application.Index(data, RowNumber, 0)
vertical = Application.Index(data, 0, ColumnNumber)
* 1 048 * (Адресация к одному элементу
array будет осуществляться напрямую, однако через
data(i,j)
вместо теоретического
Application.Index(data, i, j)
)
Как использовать Application.Index()
для реструктуризации / цели фильтрации :
Чтобы извлечь выгоду из расширенных возможностей Application.Index()
, вам нужно передать не только имя массива (например, data
), но и аргументы строки | столбца в виде массивов, например:
data = Application.Index(data, Application.Transpose(Array(15,8,10)), Array(1, 2, 3, 4, 5, 6))
Обратите внимание, что параметр строк становится "вертикальным" 2-мерным массивом путем транспонирования, где Array(15,8,10)
даже изменит существующий порядок строк ( в приведенном выше примере кода это делается в последней строке кода в функции ValidRows()
). Аргумент столбцов Array(1,2,3,4,5,6)
, с другой стороны, остается "плоским" или "горизонтальным" и позволяет получить все существующие значения столбцов такими, как они есть.
Таким образом, вы в конечном итоге получаете любые данные элементы в заданных элементных индексах (представьте их как координаты в графике c).