Я не уверен, что это ускорит ваш процесс, но он пытается выполнить sh то, о чем вы спрашиваете в своем вопросе:
Вы можете использовать выражение, предложенное в комментарии @GSerg чтобы создать объект диапазона с только видимыми строками в таблице данных, например,
Dim filteredRange As Range
Set filteredRange = Sheets("privata").UsedRange.Rows.SpecialCells(xlCellTypeVisible)
Предполагая, что на листе есть хотя бы 1 видимая строка (это означает, что приведенный выше оператор не выдаст ошибку), вы затем можно использовать следующую функцию для доступа к этому диапазону, как если бы он был одним непрерывным диапазоном:
Function RelativeCell(rng As Range, ByVal row As Long, ByVal col As Long) As Range
Dim areaNum As Long: areaNum = 0
Dim maxRow As Long: maxRow = 0
Dim areaCount As Long: areaCount = rng.Areas.Count
Do While maxRow < row
areaNum = areaNum + 1
If areaNum > areaCount Then
Set RelativeCell = Nothing
Exit Function
End If
maxRow = maxRow + rng.Areas(areaNum).Rows.Count
Loop
Dim lastArea As Range: Set lastArea = rng.Areas(areaNum)
Set RelativeCell = lastArea.Cells(row - (maxRow - lastArea.Rows.Count), col)
End Function
Чтобы напечатать все отфильтрованные значения в столбце B, например, вы можете использовать вышеуказанный метод на filteredRange
объект (установленный ранее) следующим образом:
Dim r As Long: r = 1
Do
Dim cell As Range: Set cell = RelativeCell(filteredRange, r, 2)
If cell Is Nothing Then Exit Do
Debug.Print cell.Value
r = r + 1
Loop
Чтобы упростить приведенный выше код, вы также можете использовать функцию для определения последнего относительного номера строки в отфильтрованном диапазоне, используя следующую функцию:
Function RelativeCellLastRow(rng As Range) As Long
Dim r As Long: r = 0
Dim i As Long
For i = 1 To rng.Areas.Count
r = r + rng.Areas(i).Rows.Count
Next
RelativeCellLastRow = r
End Function
Тогда код для печати всех отфильтрованных значений в столбце B будет приведен к следующему:
Dim r As Long
For r = 1 To RelativeCellLastRow(filteredRange)
Debug.Print RelativeCell(testRng, r, 2).Value
Next
Если вы используете RelativeCellLastRow
, было бы хорошо убедитесь, что он выполняется только один раз, чтобы избежать ненужных пересчетов. В приведенном выше For
l oop он выполняется только один раз, поскольку VBA выполняет только ограничения For
l oop до первой итерации. Если вам нужно это значение несколько раз, вы можете сохранить его в переменной и использовать вместо него.
Идея функции RelativeCell
состоит в том, что диапазон, возвращаемый при вызове SpecialCells
, является мульти диапазон, то есть диапазон, составленный из нескольких несмежных диапазонов. relativeCell
пропускает несмежные области, пока не найдет номер строки, которую ищет. Если номер строки превышает общее количество строк в диапазоне, функция возвращает Nothing
, поэтому вызывающий код должен знать об этом, чтобы избежать вызова метода или свойства для Nothing
.
It. Также ничего не стоит, что RelativeCell
работает в диапазоне со скрытыми строками, а не со скрытыми столбцами. Со скрытыми столбцами код становится немного сложнее, но сложность может быть заключена в функцию RelativeCell
, не затрагивая код, использующий функцию.
Опять же, я не уверен, сделает ли это код быстрее. Когда я провел несколько тестов для эмуляции вашего сценария, используя лист с 6000+ строками и 30 столбцами случайных строк, копирование / вставка после фильтрации выполнялась очень быстро, но это могло быть связано с используемой машиной, версией Excel. что я использую (2016), или данные, которые я использовал. Сказав это, я надеюсь, что приведенный выше код поможет вам.