【问题标题】:Range limit conundrum范围限制难题
【发布时间】:2021-10-22 01:52:14
【问题描述】:

我可以通过 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。

我遇到的问题是,如果范围的字符串引用太长,它就会失败。

下面的代码声明了一个函数,它接受标准的行号数组(如果数组是事先创建的)和参数参数(如果你不想事先声明一个数组,并且行列表很小)。然后它创建一个用于范围引用的字符串。

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 秒

【问题讨论】:

    标签: excel vba


    【解决方案1】:

    我认为您在这里寻找的神奇函数是 Union()。它内置在 Excel VBA 中,因此请查看它的帮助。它完全符合您的预期。

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

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

    【讨论】:

      【解决方案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 内的单元格。

      【讨论】:

      • 也很有帮助;不过,我对空单元格的搜索对我的问题来说是偶然的。
      • 糟糕。无论如何,在进一步调查中,似乎可以通过 SpecialCells 属性添加到范围的非连续单元格的数量有限制(8,192),请参阅 MS 知识库文章编号 832293。所以即使这是你的问题,您可能会在我的解决方案中遇到困难。
      【解决方案3】:

      如果将 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
      

      【讨论】:

      • 太棒了!使用 Union 和 RowHeight 的组合,宏现在运行得非常快。在 OP 中更新了代码修改。
      【解决方案4】:

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

      【讨论】:

        猜你喜欢
        • 2011-08-11
        • 1970-01-01
        • 1970-01-01
        • 2023-04-03
        • 2021-11-07
        • 2011-04-23
        • 1970-01-01
        相关资源
        最近更新 更多