【问题标题】:VBA Excel Format Range when value is found找到值时的VBA Excel格式范围
【发布时间】:2018-01-10 10:27:49
【问题描述】:

我正在尝试实现一个宏,它在大量数据中查找单词“TRUE”和“FALSE”,然后在找到时更改其上方单元格的颜色。

具体来说,我希望它不是为 TRUE/FALSE 单元格着色,而是直接在其上方的 30 个单元格着色。这就是事情变得棘手的地方......我希望有人能提供帮助。

我已尝试修改以下代码,但此时我主要将其添加为灵感。

Sub ChangeColor()
    lRow = Range("C" & Rows.Count).End(xlUp).Row
    Set MR = Range("C2:C" & lRow)
    For Each cell In MR
        Select Case cell.Value
            Case "Yes"
                cell_colour = 4
            Case "y"
                cell_colour = 4
            Case Else
                cell_colour = 3
            End Select
        cell.Interior.ColorIndex = cell_colour
    Next
End Sub

【问题讨论】:

  • 30 是固定值还是行数可以根据特定条件而变化?
  • 总是30!
  • 当它找到“TRUE”或“FALSE”时是否停止或继续查找。如果第一个是真的,你为什么不先给整个东西上色,然后从“TRUE”/“FALSE”开始为数组取消颜色
  • 它不应该在找到一个案例时停止 - 在数组中它会找到数百个“FALSE”和“TRUE” - 它应该相应地为每个人着色。
  • @CTH,通过数据字段数组添加了一种快速方法。

标签: vba excel formatting


【解决方案1】:

使用数据字段数组

循环遍历一个范围总是很耗时;这应该加快速度。

警告:格式化单个单元格可以最大化文件大小,所以至少我将整个 C 列重新格式化为 xlColorIndexNone

Option Explicit

Public Sub Mark30CellsAbove()
Dim ws   As Worksheet
Set ws = ThisWorkbook.Worksheets("MySheet")
Dim v    As Variant
Dim i    As Long, j As Long, n As Long, m As Long, r As Long
Dim Rng  As Range
Dim t    As Double
' stop watch
  t = Timer
' get last row in column C
  n = ws.Range("C" & ws.Rows.Count).End(xlUp).Row
' get values to one based 2dim array
  v = ws.Range("C1:C" & n).Value
' clear existing colors over the WHOLE column to minimize file size
  ws.Range("C:C").Interior.ColorIndex = xlColorIndexNone
' loop through C2:Cn and mark 30 rows before found condition
  For i = 2 To n
      ' check condition, find string "true" or "false"
        If InStr(".true.false.", "." & LCase(v(i, 1)) & ".") > 0 Then

            ' set range block - fixed rows count 30 above found cell
            If i < 32 Then      ' only in case of less than 30 rows
               Set rng = ws.Range("C2:C" & (i - 1))
            Else
               Set rng = ws.Range("C" & (i - 30) & ":C" & (i - 1))
            End If
            rng.Interior.ColorIndex = 4

        End If
  Next i
  MsgBox "Time needed: " & Format(Timer - t, "0.00") & " seconds."
End Sub

当然你也可以在If - EndIf 内循环,只是为了看看这个更慢的方法:

        If InStr(".true.false.", "." & LCase(v(i, 1)) & ".") > 0 Then

            ' Always avoid to loop through a range
            ' For j = i - 1 To i - 30 Step -1
                ' If j < 2 Then Exit For      ' optional escape if one line under title row
                ' ws.Cells(j, 3).Interior.ColorIndex = 4
            ' Next
         End If

【讨论】:

  • 我非常喜欢这种方法。但是,我在适应我的需要时遇到了问题。如果我想指定范围是从 E5:196 开始,并且所有行都包含数据 - 你会怎么做?
  • 我在 If LCase(v(i, 1)) = "TRUE" Then ' search string "true" 中收到“下标超出范围错误 9”消息由于测距仍然存在。
  • @CTH, ad) 当数组元素未在定义的数组范围内寻址时,会发生错误 9,但是在我的测试中,一切运行良好。 - 那么您是否更改或拼错了上面的代码,您是否将v(i, 1) 称为二维数组(因为它仅指一列,第二个索引值始终为 1)? ivalue 你有问题。您可以在For ... 循环之后插入一个临时的Debug.Print "i=" &amp; i, "array items count from " &amp; LBound(v,1) &amp; " To " &amp; UBound(v,1) 以获取最后一个有效的索引号或使用错误处理程序来检查。
  • @CTH,顺便说一下LCase 函数转换为小写,所以你必须检查If LCase(v(i, 1)) = "true" 或使用大写If UCase(v(i, 1)) = "TRUE" 来获得任何结果。我使用InStr 将两个搜索字符串组合在一个语句中。
  • @CTH,很高兴它成功了。至于你的问题:如果你想扩大搜索范围,只需定义v = ws.Range("C1:BRX" &amp; n).Value,插入一个子循环For j=1 to UBound(v, 2)' after For i=2 to n`,不要引用v(i, 1)(=只有第一列) ,但在下一个代码行中将v(i, j) 写入您的条件。请参阅上面的提示以获得灵活的范围尺寸。
【解决方案2】:

我发布的代码应该只突出显示 B 列中值与 A 列中相应单元格不同的单元格。我对其进行了测试,它工作正常。

如果你想尝试条件格式:

选择 B 列,或 B 列中要有条件地着色的部分。

在下文中,我将假设 B1 是所选内容中的活动单元格。

在功能区的主页选项卡上,单击条件格式 > 新建规则...

选择“使用公式确定要格式化的单元格”。 输入公式 =B1A1

如果活动单元格不在第 1 行,请相应调整公式。例如,如果选择中的活动单元格是 B3,则使用 =B3A3

点击格式化...

激活“填充”选项卡。

选择所需的填充颜色。

单击“确定”直到所有对话框都关闭。

更改 A 列和/或 B 列中的一些值以查看结果。

参考 - https://social.technet.microsoft.com/Forums/ie/en-US/2fffa4d8-bbba-473b-9346-5fce8f0728a8/using-vba-to-change-a-cell-colour-based-on-the-information-in-a-different-cell-excel-2010?forum=excel

【讨论】:

  • 这没什么用——因为我的数据集大约是 30,000 列 x 300 行。不过谢谢。
  • 嘿@CTH,您的 Excel 工作表仅在单列中包含真假值,或者它可以在工作表中的任何位置? ..如果它在一个列中,那么无论你有多少数据它都会起作用:)
  • TRUE/FALSE 值位于 5-6 个不同的行中。
【解决方案3】:

首先你需要检查单元格的行是否高于30,然后你可以偏移来改变颜色:

因此而不是这一行:cell.Interior.ColorIndex = cell_colour 写这个:

If cell.Row > 30 Then cell.Offset(-30, 0).Interior.ColorIndex = cell_colour

【讨论】:

  • 这是一个约数的数组。 300 行 x 3000 列。 TRUE/FALSE 语句将始终位于预定义的行中,并且应始终为语句正上方的 30 个单元格着色。
【解决方案4】:

这可以在没有 VBA 的情况下完成。您应该使用公式设置两种条件格式。第一:

=COUNTIF(OFFSET(INDIRECT(ADDRESS(ROW(), COLUMN())),1,0,29,1), "TRUE")>0

和 false 一样。要突出显示单元格,您只需使用突出显示单元格规则(CF 的顶部选项)。

【讨论】:

    【解决方案5】:

    我会使用 条件格式

    标记所有数据并按“条件格式”。输入 2 条规则 使用公式... 第一条规则是 TRUE。假设您从 Col A 开始:

    =COUNTIF(A2:A31;TRUE)
    

    第二条规则类似,只是将TRUE换成FALSE。在公式下方,按“格式”按钮设置颜色。

    说明: 我恢复了逻辑:我不是搜索 TRUE/FALSE 然后格式化上面的单元格,而是查找每个单元格,如果它至少有一个条目 TRUE 对应。在接下来的 30 个单元格中为 FALSE。但是,我不得不承认,我不知道 Excel 处理这么多数据的速度有多快。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-04
      • 2015-11-26
      相关资源
      最近更新 更多