简体   繁体   English

根据VBA中其他单元格的值,有条件地格式化单元格的循环范围

[英]Conditionally formatting a looped range of cells based on value in other cell in VBA

在此处输入图片说明

I am trying to conditionally format a range of cells based on the number in the column to each cell groupings' left. 我正在尝试根据每个单元格分组左侧的列中的数字有条件地格式化一系列单元格。 Basically, if in row 13, the gray column to the left of each cell grouping = 0, then I want the whole cell grouping to its right to turn green, if = 15, turn yellow, if = 25 turn red. 基本上,如果在第13行中,每个单元格分组左侧的灰色列= 0,那么我希望其右侧的整个单元格分组变为绿色,如果= 15,则变为黄色,如果= 25则变为红色。 Row 12 is what is happening with my code right now and row 13 is what I want it to look like. 第12行是我的代码现在正在发生的事情,第13行是我希望它的外观。 I can't seem to get the loop correct. 我似乎无法使循环正确。

Sub Highlight3()

   For i = 1 To ActiveSheet.Cells(Rows.Count, 4).End(xlUp).Row

     If Cells(i, 4) = "Highlight" Then
        For j = 1 To 15

     Range(Cells(i, j * 4 + 2), Cells(i + 1, j * 4 + 4)).Select

        Selection.FormatConditions.Delete
        Selection.FormatConditions.Add Type:=xlExpression, Formula1:="=$E$23 = 0"
        Selection.FormatConditions(Selection.FormatConditions.Count).SetFirstPriority
          With Selection.FormatConditions(1).Interior
           .Color = rgbRed
         End With

        Selection.FormatConditions.Add Type:=xlExpression, Formula1:="=$E$23= 15"
        Selection.FormatConditions(Selection.FormatConditions.Count).SetFirstPriority
          With Selection.FormatConditions(1).Interior
           .Color = rgbGold
          End With

        Selection.FormatConditions.Add Type:=xlExpression, Formula1:="=$E$23 = 25"
        Selection.FormatConditions(Selection.FormatConditions.Count).SetFirstPriority
          With Selection.FormatConditions(1).Interior
           .Color = rgbGreen
          End With


       Next j
      End If
  Next i
End Sub

Avoid Select because it's slow and unyieldy. 避免Select因为它速度慢且不灵活。 Just directly assign your Ranges to variables and work with those. 只需将范围直接分配给变量并使用它们即可。

Sub Highlight3()

    For i = 1 To ActiveSheet.Cells(Rows.Count, 4).End(xlUp).Row Step 2

        If Cells(i, 4) = "Highlight" Then
            For j = 1 To 15

            Dim r As Range
            Set r = Range(Cells(i, j * 4 + 2), Cells(i + 1, j * 4 + 4))

            Dim checkAddress As String
            checkAddress = Cells(i, j * 4 + 1).Address

            With r.FormatConditions
                .Delete

                .Add Type:=xlExpression, Formula1:="=" & checkAddress & " = 0"
                .Item(.Count).Interior.Color = rgbRed

                .Add Type:=xlExpression, Formula1:="=" & checkAddress & " = 15"
                .Item(.Count).Interior.Color = rgbGold

                .Add Type:=xlExpression, Formula1:="=" & checkAddress & " = 25"
                .Item(.Count).Interior.Color = rgbGreen
            End With

            Next j
        End If
    Next i
End Sub

Things to notice: 注意事项:

  • No more ugly use of selection - get the Range r once and do all the tasks with its conditional formatting in one clean block. 不再丑陋地使用选择-一次获取Range r,并在一个干净的块中使用其条件格式执行所有任务。

  • No longer sets the new conditional formats to have first priority. 不再将新的条件格式设置为具有优先级。 Edit that back in if necessary, but I was guessing that it was just something that the Macro Recorder did. 如有必要,请重新编辑该文件,但我猜测这只是Macro Recorder所做的。

  • Builds the formatting formula to check against the address directly left of the first cell. 构建格式公式以检查第一个单元格正好左侧的地址。 Make sure that the expression for checkAddress is what you'd expect, because I had to infer it from your picture and code. 确保checkAddress的表达式符合您的期望,因为我必须从您的图片和代码中推断出它。 If that area with the value 0/15/25 is actually two merged cells (kinda looks like it is), then make sure this formula is for the upper cell, because that cell will be the one that actually holds the value. 如果该值为0/15/25的区域实际上是两个合并的单元格(有点像),则请确保此公式适用于较高的单元格,因为该单元格将是实际保存该值的单元格。

  • Again, hard to tell from just a picture, but it looks like each of your "rows" is actually two cells high (based on your code, too). 同样,仅凭一张图片很难分辨,但是看起来每个“行”实际上高两个单元格(也基于您的代码)。 So you actually want to step through values of i by 2 at a time, not 1 at a time. 因此,您实际上想一次将i的值逐步增加2,而不是一次1。

If any of the assumptions I've just listed about your table's formatting are wrong, let me know and I'll help iron out any remain kinks in the code. 如果我刚刚列出的有关表格式的任何假设均不正确,请告诉我,我将帮助消除代码中的所有遗留问题。

This should do what you want and also be a bit faster: 这应该可以完成您想要的操作,并且速度更快:

Sub Highlight3()

  Dim i As Long, j As Byte, myCols As Range, myRng As Range

  Set myCols = Range("$B:$D")

  For i = 1 To ActiveSheet.Cells(Rows.Count, 4).End(xlUp).Row
    If Cells(i, 4) = "Highlight" Then

      If myRng Is Nothing Then
        Set myRng = Intersect(Rows(i), myCols)
      Else
        Set myRng = Union(myRng, Intersect(Rows(i), myCols))
      End If

      i = i + 1 'skip the line after, because it will never have a value / merged cell

    End If
  Next

  If myRng Is Nothing Then Exit Sub

  For i = 4 To 60 Step 4
    For j = 0 To 1
      With myRng.Offset(j, i)

        .Cells(1).Offset(-j).Activate
        .FormatConditions.Delete 'if that does not interfer with other stuff, better use the next line
        'If j = 0 Then myCols.Offset(, i).FormatConditions.Delete

        .FormatConditions.Add Type:=xlExpression, Formula1:="=" & .Cells(1).Offset(-j, -1).Address(0) & "=0"
        .FormatConditions(.FormatConditions.Count).SetFirstPriority
        .FormatConditions(1).Interior.Color = rgbRed

        .FormatConditions.Add Type:=xlExpression, Formula1:="=" & .Cells(1).Offset(-j, -1).Address(0) & "=15"
        .FormatConditions(.FormatConditions.Count).SetFirstPriority
        .FormatConditions(1).Interior.Color = rgbGold

        .FormatConditions.Add Type:=xlExpression, Formula1:="=" & .Cells(1).Offset(-j, -1).Address(0) & "=25"
        .FormatConditions(.FormatConditions.Count).SetFirstPriority
        .FormatConditions(1).Interior.Color = rgbGreen

      End With
    Next
  Next

End Sub

tested it locally and it worked... there may be issues which I can not know (better test it with a copy of your workbook). 在本地对其进行了测试,并且可以正常工作……可能存在一些我不知道的问题(最好使用工作簿的副本进行测试)。

The first part pushes all lines in a range which is used in the second part. 第一部分在第二部分使用的范围内推动所有行。 This way, each pack of columns needs only 2 steps (no need to run EVERY line). 这样,每列列仅需要2个步骤(无需运行每行)。

If you have any questions or problems with this code, just ask ;) 如果您对此代码有任何疑问或问题,只需询问;)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM