Эффективность и функциональность в массиве типа range и присвоении массива нетипового типа с Range - PullRequest
0 голосов
/ 11 марта 2020

Я знаю, что это;

Arr() =Range("E2:X2500")

... затем работа с Arr и последующий сброс с помощью:

Range("E2:X2500")=Arr()

во много раз эффективнее (быстрее ) циклическое прохождение и ссылки на ячейки напрямую. Это скорость света!

Но это присвоение диапазона-массива только захватывает значение ячейки. Есть ли способ присвоить фактический диапазон (непрерывный или нет) массиву (с одинаковой скоростью света) таким образом, чтобы вы могли затем обрабатывать элементы массива так, как вы бы ссылались на ячейки, например:

arr(23).row 'getting a row number

Или;

If Arr(23).Value ="Pending" then arr(23).font.bold=1 else arr(23).font.bold=0

Я знаю, что могу затемнить массив типа range, где каждый элемент может хранить фактический диапазон одной ячейки. Но этот массив не может быть обработан таким же образом - с одним назначением вкладыша:

Dim Arr () as Range
Set Arr = Range("E2:X2500") 'error

Вместо этого мне нужно было бы перебрать каждую ячейку и назначить ее следующему элементу в массиве типа диапазона, который разрешил бы обрабатывать элементы так, как я бы относился к ячейкам, но загружался значительно дольше, поскольку я имею дело с L oop.

Также как бы я сбросить массив типа диапазона обратно на лист с той же простотой и эффективностью назначения одного вкладыша? Я думаю, что единственный способ - это использовать al oop еще раз, правильно?

. Дополнительный вопрос: по скорости, лучше ли ссылаться на ячейки через массив типа диапазона, а не на ячейки? напрямую через лист, или оба в основном одинаковые?

Спасибо!

1 Ответ

2 голосов
/ 11 марта 2020

Ну, использование массива сэкономит много времени выполнения кода. Но есть некоторые проблемы, которые необходимо понять:

  1. Первое, когда работа в VBA и ваш проект увеличивается, - это правильно объявить ваши переменные. Попробуйте сделать рефлекс, поместив Option Explicit поверх всех ваших модулей. В случае с массивом, с этой точки зрения, вещь остается такой:

    Dim Arr() As variant, arr1 As Variant

    Оба объявления работают в Excel . Но второй рекомендуется ( на майский вкус ), , когда вам нужен массив из диапазона . Когда вы хотите создать, скажем, массив результатов, он будет основан на нуле, и вы должны позаботиться о размере диапазона, в котором будут возвращаться значения.

  2. Содержимое массива не может быть найденным точно так же, как вы пытались ответить на ваш вопрос в случае нефиксированного / известного количества элементов. Посмотрите на следующий тестовый код:

    Sub testArrays() Dim sh As Worksheet, rng As Range, arrTest As Variant Set sh = ActiveSheet Set rng = sh.Range("A1:F4") arrTest = rng.value sh.Range("J1").Resize(UBound(arrTest, 1), UBound(arrTest, 2)).value = arrTest End Sub

Рекомендуется использовать arrTest = sh.Range("A1:F4").value. Используя диапазон Value. Excel может понять, что вам нужно, в соответствии с вашей декларацией, но вам будет полезно как-то отличить его от способа определения диапазона.

Иногда вам необходимо создать массив во время анализа динамических параметров. c диапазон. Если вы не можете знать новые размеры массива и вам нужно Redim (Preserve), может быть изменено только второе измерение массива, и в таком случае должна использоваться функция Transpose. И, наконец, полученный массив можно правильно загрузить в диапазон, только если вы знаете номер массива строк и столбцов.

Вы можете вывести строку диапазона из строки массива следующим образом: если мы ссылаемся на вышеприведенное arrTest, мы знаем, что его первая строка является первой строкой листа и имеет 5 столбцов.

Итак, arrTest(3, 1) будет sh.Range("A3").Value, а его строка будет 3.

Тогда arrTest(3, 4) будет sh.Range("D3").Value, и его строка будет также 3.

Если ваш массив взят из диапазона, начинающегося с пятой строки, вы должны добавить четыре, чтобы получить строку листа, извлеченную из строки массива ...

Итак, ваш пример может быть преобразован в :

If arrTest(3, 4) ="Pending" then sh.Cells(3, 4).Font.Bold=1 Else sh.Cells(3, 4).Font.Bold=0

Теперь, если вам нужен массив диапазонов, вы не можете сделать это так, как вы пытались. Вы должны использовать адрес диапазонов и построить диапазон в конце:

Sub testArraysBis() Dim sh As Worksheet, rng As Range, rng1 As Range, lastCol As Long Dim rng2, arrTest As Variant, arrT As Variant, arrF As Variant Set sh = ActiveSheet lastCol = sh.Cells(1, Cells.Columns.Count).End(xlToLeft).column Set rng = sh.Range(sh.Cells(1, 1), sh.Cells(4, lastCol)) Set rng1 = sh.Range("A5:F6") arrT = Array(rng.Address, rng1.Address) arrTest = rng.value Debug.Print UBound(arrTest), LBound(arrTest) sh.Range("J1").Resize(UBound(arrTest, 1), UBound(arrTest, 2)).value = arrTest Set rng2 = sh.Range(arrT(0)) Debug.Print rng2.Address arrF = sh.Range(arrT(0)).value Debug.Print UBound(arrF, 2) End Sub

rng2 диапазон будет построен с использованием строки адреса, извлеченной из * Массив 1065 *. Массив (arrF) также можно извлечь из первого элемента arrT ...

Epilog: лучший способ, с точки зрения скорости, это загрузить диапазон в массивах, выполнить всю обработку, используя их (в памяти и очень быстро из-за этого аспекта), , но самая важная проблема - это построить другой массив (или даже диапазон, используя Union) и извлеките данные в ОДИН РАЗ . Отправка каждого результата частичной обработки в ячейку / диапазон занимает много времени и других ресурсов, для большого размера диапазона ...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...