【问题标题】:selecting multiple different ranges in a loop VBA在循环VBA中选择多个不同的范围
【发布时间】:2021-01-09 03:58:04
【问题描述】:

我是 VBA 的新手,我正在尝试创建一个宏,通过 C 列搜索找到包含“teston”的所有单元格,然后找到它下方包含“testoff”的单元格并突出显示它们之间的所有单元格在它旁边的列中。有多个 teston 实例要测试。

此代码有效,但仅突出显示 teston 到 testoff 的第一个实例

    Dim findrow As Long, findrow2 As Long


    On Error GoTo errhandler


    findrow = Range("C:C").Find("teston", Range("C1")).Row
    findrow2 = Range("C:C").Find("testoff", Range("C" & findrow)).Row
    Range("F" & findrow + 1 & ":F" & findrow2 - 1).Select
        With Selection.Interior
                .Pattern = xlSolid
                .PatternColorIndex = xlAutomatic
                .Color = 16764159
                .TintAndShade = 0
                .PatternTintAndShade = 0
              End With
errhandler:
    MsgBox "No Cells containing specified text found"

这是我试图做的,以突出它们,但它没有突出任何东西

    Range("A1").Select
    Selection.End(xlDown).Select
    Dim lastcell As Long
    lastcell = ActiveCell.Row
    
    Dim findrow As Long, findrow2 As Long, I As Long, inext As Long
    
    inext = 1
    
    On Error GoTo errhandler
    
      Do While I < lastcell
              
            findrow = Range("C" & inext & ":" & "C" & lastcell).Find("test1", Range("C1")).Row
            findrow2 = Range("C" & inext & ":" & "C" & lastcell).Find("test2", Range("C" & findrow)).Row
            Range("F" & findrow + 1 & ":F" & findrow2 - 1).Select
                With Selection.Interior
                        .Pattern = xlSolid
                        .PatternColorIndex = xlAutomatic
                        .Color = 16764159
                        .TintAndShade = 0
                        .PatternTintAndShade = 0
                End With
            Range("findrow2").Select
            inext = ActiveCell.Row
            findrow = findrow2
                I = I + 1
       Loop
              
errhandler:
    MsgBox "No Cells containing specified text found"

【问题讨论】:

  • 如果 C 列包含多个 testons 而只有一个 testoff,您的宏应该填充什么范围?
  • 我没有马上注意到这条线 - Range("findrow2").Select。它能做什么?更准确地说,你认为它应该做什么?
  • 我的意思是,无论命名范围“findrow2”是什么,inext 总是指向这一行并且不会在循环中移动 - 所以你只绘制第一个 test1/test2 对。而且这个命名范围必须存在,否则你会去errhandler:或者你真的要去那里?
  • 我试图通过选择 findrow2 来获取单元格行 Range("findrow2").Select ` 然后获取单元格值并将其设置为 inext 以便下一个循环从 @987654328 开始@ 并从那里往下走
  • 啊,也许你想写inext = Range("C" &amp; findrow2).Row或者简单的inext = findrow2

标签: excel vba loops


【解决方案1】:

不要单独寻找它们。只需浏览整个专栏,它们就会被自己找到。

Sub color_between_tests()
Dim tSearch As Range
Dim oCell As Range
Dim bColorOn As Boolean
    Set tSearch = Application.Intersect(ActiveSheet.UsedRange, ActiveSheet.Columns("C"))
    bColorOn = False
    For Each oCell In tSearch
        oCell.Offset(0, 3).Interior.Color = 16764159
        Select Case oCell.Text
            Case "teston"
                bColorOn = True
            Case "testoff"
                bColorOn = False
            Case Else
                If Not bColorOn Then oCell.Offset(0, 3).Interior.Pattern = xlNone
        End Select
    Next oCell
End Sub

【讨论】:

  • 谢谢这个工作,但它需要几分钟来执行,我试图让它运行得更快,我不确定我的原始代码看起来像在做什么,但我试图去从 C1 找到第一个案例,让我们说 C54 到 C86,然后“再次”开始搜索,但从 C86 开始寻找下一个测试,我也在试图弄清楚为什么我的原始代码不起作用,因为从我的知识有限,看起来应该可以正常工作
  • 在循环前使用Application.ScreenUpdating = False,在退出程序前使用Application.ScreenUpdating = True应该可以解决长时间执行的问题。要从给定位置继续搜索,findrow 必须包含 Range("C" &amp; findrow2) 而不是 Range("C1")(记得在开始搜索之前设置 findrow2 = 1!)
  • 谢谢我之前尝试过'Range("C" & findrow2)' 但我之前忘记设置'findrow2 = 1' 所以我猜什么都没发生。我是否应该一直使用 'Application.ScreenUpdating = False' 和 'Application.ScreenUpdating = False' 来加速其他宏?
  • 我只是尝试将其设置为 1 并将 C1 替换为 "C" & findrow2 但它仅突出显示第一种情况,即使我让它循环了 10 次
  • 关于.ScreenUpdatingHERE
【解决方案2】:

试试这个 - 假设每个 teston 后面都有一个 testoff,并且没有值对的嵌套

Sub Tester()

    Dim rngSrch As Range, ws As Worksheet, allOn As Collection, c As Range, c2 As Range
    
    Set ws = ActiveSheet
    Set rngSrch = ws.Columns("C")
    
    Set allOn = FindAll(rngSrch, "teston") 'first find all the "teston"
    For Each c In allOn
        'for each one find the next "testoff"
        Set c2 = rngSrch.Find("testoff", after:=c, lookat:=xlWhole)
        If Not c2 Is Nothing Then
            If c2.Row > c.Row Then
                ws.Range(c.Offset(1, 3), c2.Offset(-1, 3)).Interior.Color = vbYellow
            Else
                Exit For 'wrapped back up - exit
            End If
        End If
    Next c
    
End Sub

'find all matches in a given range
Public Function FindAll(rng As Range, val As String) As Collection
    Dim rv As New Collection, f As Range, addr As String
    Set f = rng.Find(what:=val, after:=rng.Cells(rng.Cells.Count), _
        LookIn:=xlValues, lookat:=xlWhole, SearchOrder:=xlByRows, _
        SearchDirection:=xlNext, MatchCase:=False)
    If Not f Is Nothing Then addr = f.Address()
    Do Until f Is Nothing
        rv.Add f
        Set f = rng.FindNext(after:=f)
        If f.Address() = addr Then Exit Do
    Loop
    Set FindAll = rv
End Function

【讨论】:

  • 我试了一下,它执行了一两分钟,但完成后没有突出显示
  • 对我来说很好。
【解决方案3】:

这应该会提高速度

Dim oCell As Range
Dim R As Long
Dim Color_On As Boolean

R = Cells(Rows.Count, 3).End(xlUp).Row
Range("F1:F" & R).Interior.Pattern = xlNone
For Each oCell In Range("C1:C" & R)
    Color_On = oCell = "teston" Or Color_On
    If Color_On Then oCell.Offset(0, 3).Interior.Color = 16764159
    Color_On = Color_On And (oCell <> "testoff")
Next oCell

【讨论】:

  • 非常感谢这非常有效!有没有理由为什么这种方式只需要大约一秒钟的时间,而其他的需要大约 5 分钟?
  • 这是一个“被操纵”的代码。 ; ) 说真的:更少的指令、更少的比较和更少的赋值 = 更快的代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-10
  • 1970-01-01
  • 1970-01-01
  • 2014-03-04
相关资源
最近更新 更多