范围限制难题

时间:2009-11-02 19:45:14

标签: excel vba

我可以通过VBA在一个范围内选择一些限制吗?基本上我发现如果我在循环中隐藏整行,如果要隐藏很多行,则需要很长时间。

ex) - 隐藏A列中没有值的任何行

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”仅用于给出失败时的示例。要查看它的工作原理,只需创建一个包含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

结果:

联盟(行高:0.109375秒
联盟(隐藏行):0.625秒

4 个答案:

答案 0 :(得分:6)

我认为你在这里寻找的神奇功能是Union()。它内置于Excel VBA中,请查看它的帮助。它完全符合您的期望。

遍历您的范围,但不是构建字符串,而是构建一个多区域范围。然后,您可以一次选择或设置整个事物的属性。

我不知道在一个范围内你可以建立的区域数量是多少(如果有的话),但它大于600.我不知道有什么(如果有的话)限制选择或设置多区域范围的属性,但它可能值得一试。

答案 1 :(得分: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中的单元格。

答案 2 :(得分:2)

如果将RowHeight属性设置为0,则可以获得次要加速。 在我的系统上它的速度提高了一倍     (6000次迭代约1.17秒对2.09秒)

你没有提到“很长一段时间”是什么,以及你正在使用的XL版本......

您的问题可能部分是行检测代码,用于检查您要隐藏的行(?)。

这是我在XL 2​​003中的测试代码(注释掉一个版本然后另一个版本):

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

答案 3 :(得分:1)

字符串长度有限制。我刚刚遇到类似的问题,发现如果是String Txt的话 范围(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"没有错误。在两种情况下,区域数量都相同。