Как можно проверить переменные диапазона Excel VBA для ссылок на целые столбцы ..? - PullRequest
0 голосов
/ 27 июня 2018

Какие существуют способы проверки переменной диапазона Excel VBA для ссылок на целые столбцы?

Я использую Excel 2007 VBA, перебирая переменные Range с циклами For-Each. Диапазоны передаются в функцию в качестве параметров. Ссылки на отдельные ячейки, диапазоны ячеек и целые строки в порядке.

Например, это okiedokie:

Range("A1")     'One cell
Range("A1:D4")  'Range of cells.
Range("10:20")  'Entire rows 10 through 20.

Но если какой-либо из диапазонов имеет ссылки на целые столбцы, функция приведет к полной остановке. Например, это не okiedokie, и их нужно проверить и избежать:

Range("A:A")
Range("A:Z")
Range("AA:ZZ")

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

Вот три способа, о которых я могу думать, но я хотел бы знать, есть ли другие ..?

  1. Самый простой и быстрый способ - подсчет строк. Если Range(x).Rows.Count=1048576, это максимальное количество строк на листе. Тем не менее, это не сработает, если фактическое количество строк окажется точно таким же числом, или если по какой-то дикой случайности было несколько перекрывающихся областей / диапазонов что все сложилось до этого числа. И то и другое маловероятно, но возможно. Кроме того, если версия Excel изменится, может измениться и это число, что приведет к нарушению кода.

  2. Использовать совпадение RegEx с текстом Range.Address (False, False) с шаблоном, например ([A-Z]{1,3}):([A-Z]{1,3}). Я думаю, что это будет средний на шкале скорости.

  3. Используйте петли VBA, If-Then и строковые функции, такие как InStr() и Mid(), чтобы выбрать текст Range.Address(False,False). Я думаю, что это будет самый медленный способ сделать это.

Ответы [ 3 ]

0 голосов
/ 27 июня 2018

Не уверен, что я полностью понимаю вопрос, но это может сработать для вас:

Public Sub Test()
    Debug.Print RowCheck(ThisWorkbook.Worksheets("Sheet1").Range("A1:A10"))
End Sub

Public Function RowCheck(InputRange As Range)
    Dim u As Long 'used number of rows
    Dim x As Long 'max number of rows for any column
    Dim r As Long 'number of rows based on input range

    With InputRange
        u = Cells(Rows.Count, .Columns(1).Column).End(xlUp).Row
        r = .Rows.Count
        x = Rows.Count
    End With

    If r = x And u < r Then
        RowCheck = "A bad column reference provided"
    Else
        RowCheck = "This is a valid reference"
    End If
End Function
0 голосов
/ 27 июня 2018

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

Но в переводе это означает ... все строки в данных, или UsedRange. Это возможно при большом количестве данных, которые UsedRange могут действительно попасть в последнюю строку в 1048576. И любая комбинация Range ссылок, переданных моему Function , может привести к огромной области, которая покрывает весь столбец, вплоть до максимальной строки.

Конечно, вероятность того, что это произойдет, очень мала, но мне нравится охватывать все основы в моем коде. Но ключ к этой загадке - UsedRange. Это создает «синтетический максимум последней строки». Если GrandRange, из-за отсутствия лучшего имени, покрывает все строки в UsedRange, то моя функция не имеет ничего общего и не возвращает данных. И поэтому простой IF-Then-Exit должен дать мне решение, которое я искал:

If Intersect(UsedRange,LeGrandeRange).Rows.Count = UsedRange.Rows.Count Then
    'All rows in `UsedRange` are affected.
    'Nothing to do.
    Exit Function
Else
    'Do everything here.
    'Then exit normally.
    ...
    ...
    ...
Endif
0 голосов
/ 27 июня 2018

Вы можете проверить, является ли диапазон ссылкой на столбец, сравнив Range.Address с Range.EntireColumn.Address следующим образом:

If Range("AA:ZZ").Address = Range("AA:ZZ").EntireColumn.Address Then
    'This returns True
End If

If Range("AA1:ZZ4").Address = Range("AA1:ZZ4").EntireColumn.Address Then
    'This returns False
End If
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...