2009-11-02 3 views
4

Есть ли предел тому, что я могу выбрать в диапазоне через VBA? В основном, я обнаружил, что если я должен скрыть целую строку, находясь в цикле, это займет довольно много времени, если есть много строк, которые нужно скрыть.Ограничение по диапазону

ех) - Скрыть любую строку, которая не имеет значения в колонке А

For i = 1 to 600 
    With Range("A" & i) 
     If .value = vbEmpty then .EntireRow.Hidden = True 
    End With 
Next 

Чем более быстрый способ сделать это, чтобы сделать одного диапазона, который ссылается на каждой из этих строк, а затем сделать сингл ".entirerow.hidden = true". И да, у меня уже есть application.screenupdating = false set.

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

Следующий код объявляет функцию, которая принимает как стандартный массив номеров строк (в случае, если массив сделан перед рукой), так и аргументы параметров (в случае, если вы не хотите объявлять массив перед началом работы, и список строк мал). Затем он создает строку, которая используется в ссылке диапазона.

Function GetRows(argsArray() As Long, ParamArray args() As Variant) As Range 

    Dim rngs As String 
    Dim r 

    For Each r In argsArray 
     rngs = rngs & "," & r & ":" & r 
    Next 
    For Each r In args 
     rngs = rngs & "," & r & ":" & r 
    Next 

    rngs = Right(rngs, Len(rngs) - 1) 
    Set GetRows = Range(rngs) 

End Function 
Function dfdfd() 

    Dim selList(50) As Long, j As Long 
    For i = 1 To 100 
     If i Mod 2 = 1 Then 
      selList(j) = i 
      j = j + 1 
     End If 
    Next 
    selList(50) = 101 
    GetRows(selList).Select 

End Function 

Вторая функция «dfdfd» используется только для примера, когда она терпит неудачу. Чтобы увидеть, когда это работает, просто создайте новый массив с say-5 элементами и попробуйте это. Оно работает. (?)

Окончательное обновление:

Option Explicit 

Public Sub test() 
    Dim i As Integer 
    Dim t As Long 
    Dim nRng As Range 

    t = Timer() 
    Application.ScreenUpdating = False 
    Set nRng = [A1] 
    For i = 1 To 6000 
     Set nRng = Union(nRng, Range("A" & i)) 
    Next 
    nRng.RowHeight = 0 
    'nRng.EntireRow.Hidden = true 
    Application.ScreenUpdating = True 
    Debug.Print "Union (RowHeight): " & Timer() - t & " seconds" 
    'Debug.Print "Union (EntireRow.Hidden): " & Timer() - t & " seconds" 
End Sub 

Результаты:

Union (высота строки: 0.109375 секунд
Union (скрытый ряд): 0.625 секунды

ответ

6

Я думаю, магическая функция, которую вы Здесь вы найдете Union(). Он встроен в Excel VBA, поэтому посмотрите на его помощь. Он делает то, что вы ожидаете.

Прокрутите диапазоны, но вместо построения строки создайте многодиапазонный диапазон. Затем вы можете сразу выбрать или установить свойства всего объекта.

Я не знаю, что (если есть) ограничение на количество областей, которые вы можете создать в одном диапазоне, но оно больше 600. Я не знаю, какие (если есть) пределы есть при выборе или настройке свойств многозонного диапазона, но, вероятно, стоит попробовать.

+0

Отлично! Огромное спасибо. – JakeTheSnake

2

Более быстрый вариант может заключаться в использовании SpecialCells свойство, чтобы найти пробелы затем скрыть строки:

Sub HideRows() 

    Dim rng As Range 

    Set rng = ActiveSheet.Range("A1:A600") 
    Set rng = rng.SpecialCells(xlCellTypeBlanks) 
    rng.EntireRow.Hidden = True 

End Sub 

Это будет работать только на клетках внутри UsedRange, я думаю.

+0

Также очень полезно; Однако мой поиск пустых ячеек был случайным для моей проблемы. – JakeTheSnake

+0

Упс. Во всяком случае, при дальнейшем расследовании, кажется, что существует ограничение (8 192) на количество несмежных ячеек, которые могут быть добавлены в диапазон через свойство SpecialCells, см. Статью базы знаний MS 832293. Так что даже если это была ваша проблема , вы, вероятно, столкнетесь с трудностями с моим решением. – dendarii

2

Несовершеннолетний убыстрение можно получить, если вы установите свойство RowHeight 0. На моей системе он идет в два раза быстрее (на 6000 итераций около 1,17 секунды против 2,09 секунд)

Вы не упомянули что «довольно долгое время», и какая версия XL вы используете ...

Возможно, проблема в том, что ваша строка обнаруживает код, который проверяет строку, которую вы хотите скрыть (?).

Вот мой тестовый код в XL 2003 (закомментировать одну версию, то другой):

Option Explicit 

Public Sub test() 
    Dim i As Integer 
    Dim t As Long 

    t = Timer() 
    Application.ScreenUpdating = False 
    For i = 1 To 6000 
    With Range("A" & i) 
     'If .Value = vbEmpty Then .EntireRow.Hidden = True 
     If .Value = vbEmpty Then .RowHeight = 0 
    End With 
    Next 
    Application.ScreenUpdating = True 
    Debug.Print Timer() - t & " seconds" 
    End Sub 
+0

Отлично! Используя комбинацию Union и RowHeight, макрос работает очень быстро. Модификация кода обновлена ​​в OP. – JakeTheSnake

1

Там есть ограничение на длину строки. Я просто столкнулся с аналогичной проблемой и обнаружил, что если String Txt из Range (Txt) больше 255 символов, мой VBA выдает Error.eg. код:

Debug.Print sheet1.Range("R2300,T2300,V2300,R2261,T2261,V2261,R1958,T1958,V1958,R1751,T1751,V1751,R1544,T1544,V1544,R1285,T1285,V1285,R1225,T1225,V1225,R1193,T1193,V1193,R1089,T1089,V1089,R802,T802,V802,R535,T535,V535,R264,T264,V264,R205,T205,V205,R168,T168,V168,R135,T135,V135,R101").Areas.count 

выдает ошибку (256 символов в строке), тогда как код

Debug.Print sheet1.Range("R230,T2300,V2300,R2261,T2261,V2261,R1958,T1958,V1958,R1751,T1751,V1751,R1544,T1544,V1544,R1285,T1285,V1285,R1225,T1225,V1225,R1193,T1193,V1193,R1089,T1089,V1089,R802,T802,V802,R535,T535,V535,R264,T264,V264,R205,T205,V205,R168,T168,V168,R135,T135,V135,R101").Areas.count 

имеет 255 символов и печатает "46" без ошибок. Количество областей в обоих случаях одинаково.

Смежные вопросы