【问题标题】:How to skip to nth element of for next loop如何跳到下一个循环的第n个元素
【发布时间】:2017-03-14 15:25:24
【问题描述】:

我正在尝试在 Excel 中返​​回过滤表的第 n 个可见元素。 Current methods 告诉我使用 SpecialCells(xlCellTypeVisible) 方法,然后循环遍历元素,同时使用 For Each... Next 循环计算它们。

这似乎不是最理想的;我不想知道前 19 个范围,只知道第 20 个。有没有办法直接跳到循环的第 20 个元素?

或者也许循环遍历.Areas 并计算它们的大小;这意味着您只需进入包含第 n 个元素的Area,然后在 that 区域内进行子循环以精确定位元素。这会更快吗?

当然,如果你能想出更好的方法来获取过滤表的第 n 个元素,那也很好!

我获取表格范围的代码是:

Dim inptTbl As Range
Set inptTbl = ThisWorkbook.Sheets("compiled").ListObjects("Table2").ListColumns("Company").Range.SpecialCells(xlCellTypeVisible)

然后循环,好吧,我还没有写,但我猜:

i=0
Dim r As Range
For Each r in inptTbl
    i=i+1
    If i = 20 Then Exit For
Next r
Debug.Print r.Address

按所述循环遍历区域:

Set inptTbl = ThisWorkbook.Sheets("compiled").ListObjects("Table2")
Set test = inptTbl.ListColumns("Company").Range.SpecialCells(xlCellTypeVisible)

runningTot = 0
arIndex = 1
Do Until test.Areas(arIndex).Cells.Count + runningTot > 20
    runningTot = runningTot + test.Areas(arIndex).Cells.Count
    arIndex = arIndex + 1
Loop
i = 0
Dim r As Range
For Each r In test.Areas(arIndex)
    If i = 20 - runningTot Then Exit For
    i = i + 1
Next r
Debug.Print r.Address

【问题讨论】:

  • 从您拥有多区域范围的那一刻起,我认为您需要逐个迭代区域或可见单元格。

标签: vba excel


【解决方案1】:

最终更新

正如您提到的,您正在寻找最有效的方法,我会遍历 区域 而不是单个单元格。

Sub test2()
    Dim a As Range, rng As Range
    Dim n As Long, total As Long, adj As Long

    n = 20
    Set rng = ThisWorkbook.Worksheets("Sheet1").Range("A1:A1000").SpecialCells(xlCellTypeVisible)

    For Each a In rng.Areas
        adj = n - total
        total = total + a.Cells.Count
        If total >= n Then
            Debug.Print a.Cells(adj, 1).Address
            Exit Sub
        End If
    Next a
End Sub


更新 #2

为了保持这个答案相对干净,我删除了我之前的努力。

最后,仍然使用xlCellTypeVisible,这应该适用于任何的情况。它会调整范围的大小,直到有 20 个可见单元格,然后返回该范围内的最后一个单元格。

Sub test()
    Dim rng As Range, r As Range
    Dim n As Long

    n = 20 'update for your required value of n

    With ThisWorkbook.Worksheets("Sheet1") 'relevant sheet name
        Set r = .Range("A1") 'where to start?
        Set rng = r.Resize(n, 1)
    End With

    While rng.SpecialCells(xlCellTypeVisible).Count < n
        Set rng = rng.Resize(rng.Rows.Count + 1, 1)
    Wend

    Debug.Print rng.Cells(rng.Rows.Count + r.Row - 1, r.Column).Address

End Sub

【讨论】:

  • 嗯是吗?这是我首先尝试的,但奇怪的是它包含隐藏单元格,尽管.SpecialCells(xlCellTypeVisible) 作为条件,导致$A$20 被返回——不管A1:A100 上的过滤
  • 如果第 20 行之前的某些行被隐藏,那仍然会返回 A20。我试过?Range("A1:A10, A30:A40").Cells(20, 1).address,它返回了$A$20
  • 是的,我想是的。 .Cells 总是从左上角的单元格开始索引,它不会进一步检查。
  • 如果过滤的行(即隐藏)是连续的,您更新的答案可能会起作用,但如果行(2:4、6:9、12:17、21:23、27:30)被隐藏怎么办?
  • 啊。好地方..回到绘图板!
【解决方案2】:

过滤后的范围可能有许多不连续的区域(请参阅Get Excel filter results into VBA array)。如果您正在遍历可见单元格,则使用区域,但如果您想跳转到第 20 个可见元素,只需运行 For Next 循环,直到达到您想要检索的范围。

Dim r As Long, v As Long

v = 20

With Selection
    For r = 1 To .Rows.Count
        v = v + (Not .Cells(r).EntireRow.Hidden)
        If v = 0 Then Exit For
    Next r

    Debug.Print .Cells(r).Value
End With

为了方便起见,我在这里使用了Selection;您可以从表格中检索实际的单元格范围。

【讨论】:

    【解决方案3】:

    理想情况下需要查看您的完整代码,但您可以计算可见单元格并执行类似的操作,而不是使用For Each....Next

    Sub test()
    Dim vcells as Long
    
    vcells = Activesheet.Usedrange.SpecialCells(xlCellTypeVisible).Rows.Count
    
    For i = 20 to vcells
        `your code here
    Next i
    
    End Sub
    

    【讨论】:

    • 我已经添加了代码。我不太确定你的代码做了什么:你计算过滤器范围内的可见行以获得循环的上限,我明白了,但是从 i = 20 开始有什么意义?
    • @Greedo 因为你想从第 20 次迭代开始,我从你的问题中了解到,一旦你有过滤范围,你想忽略前 19 个范围。
    • 啊,我明白了,我想你误解了我的意思。我的意思是我不关心前 19 个 visible 单元格的 properties,我只关心第 20 个(或nth) 可见单元格。
    猜你喜欢
    • 2017-07-11
    • 2014-01-08
    • 1970-01-01
    • 2017-11-11
    • 1970-01-01
    • 2021-07-11
    • 1970-01-01
    • 1970-01-01
    • 2010-09-20
    相关资源
    最近更新 更多