Excel 条件格式公式和范围 (VBA)

Excel Conditional formatting formula and ranges (VBA)

我有一个FormatCondition。我正在阅读 .Formula1.AppliesTo

我想查找公式是否包含将在 AppliesTo 指定的范围内发生变化的单元格引用,例如 =NOT(ISNUMBER(C3))C3:D10.

范围内

据我所知,该引用可能是相对的(例如 C3)或混合的(例如 $C3C),但不是绝对的。它也将是基于 https://www.ablebits.com/office-addins-blog/2014/08/07/relative-absolute-cell-references-excel-conditional-formatting/ 和其他一些网站的 'top-left most cell in the applied range'。

如果范围类似于 C3:D10,那很容易。使用例如 myRange.Cells(1, 1) 找到左上角,使用 .Address 或类似方法将其转换为字符串,然后在公式中查找该字符串,以及添加 $ 的相关变体。当然,我必须小心字符串之类的东西(例如左上角的单元格是 C3' and formula is="CC3NE"`),但这是可能的(不过,我还是欢迎就如何做得更好提出建议,但这不是问题)。

真正的问题是范围是否更复杂,条件格式似乎经常发生。一个例子是 $CQ:$FT,$BE,$BE:$BE,$CU:$FT,$CU:$FT,$BE:$BE,$BE:$BE,$CQ:$FT,$CQ:$FT,$BE:$BE.Cells(1, 1) 没有给出正确答案(BE8,根据 Excel 制定的公式)。

此外,如果范围类似于 $A,$E - 没有 'top left' 怎么办?那么excel(或用户)如何决定公式中应该包含哪些内容呢?

因此主要问题是:Excel 确定在公式中使用哪个单元格的系统是什么,因为我不相信它是 'top left' - 它可能是 'find the topmost row, then find the leftmost cell there',也可能是相反的,或者完全不同的东西。

第二个问题是:如何最好地找到给定范围内的单元格?

额外的问题(如果这里没有得到回答,我很高兴)是:有没有一种好的方法可以在公式中找到对该单元格的引用,包括相对和混合版本细胞的?

请注意,这些奇怪的范围是由于在 sheet 上使用条件格式剪切和粘贴行和列,结果 Excel 切断了条件格式(更改范围,并更改公式,两者都无需用户输入)。因此,当务之急是处理 Excel 在这种情况下将公式设置为独立的任何内容,不一定是用户可能会做的事情——但同时处理两者会更好。

第一个回答: 简短版本:Excel 确实使用最左上角的单元格 - 但它会这样做 即使单元格不属于范围 .

我创建了一个空白 sheet,选择了 A5,E1,并输入了 NOT BLANK 的条件格式(Excel 使用公式)。 Excel 创建了以下内容:

范围:$E,$A

公式:=LEN(TRIM(A1))>0

所以即使 A1 不在范围内,公式中也使用了它。

我通过在 sheet 周围复制它来检查它,它保持一致。

因此 Excel 找到范围中最左边的列和范围中最上面的行,并将它们组合以生成应被视为 'top left' 的单元格范围,即使结果单元格实际上不是范围的一部分。

这也暗示了第二个问题的答案:找到范围内最上面的行;找到最左边的列;然后使用结合了两者的单元格与公式进行比较。您可以通过遍历范围字符串,或者逐个单元格遍历范围本身来做到这一点;也许有更好的方法(欢迎提出建议)。

它不是很漂亮,但如果我能找到一个好的方法来做这两件事,它会起作用。

我仍然欢迎:

  • 任何可以改进这个关于公式中使用哪个单元格的答案的人(我没有对此进行广泛测试)
  • 任何人都可以建议找到上述 'top left cell' 的好方法
  • 任何可以提出搜索左上角单元格公式字符串的好方法的人

编辑 - 这是 Usmanhaq 出色方法的替代代码方法 - 它作为字符串遍历范围:

Private Function FindTopLeft(rangeStr As String, rowabs As Boolean, colabs As Boolean) As String
    newRange = Replace(rangeStr, ":", ",")
    newRangeArray = Split(newRange, ",")
    Dim lowestRow As Long
    Dim lowestCol As Long
    lowestRow = 2147483647
    lowestCol = 2147483647

    For Each cell In newRangeArray
        cell = Trim(cell)
        If cell <> "" Then
            cCol = range(relativeCell).Column
            cRow = range(relativeCell).Row
            If cCol < lowestCol Then lowestCol = cCol
            If cRow < lowestRow Then lowestRow = cRow
        End If
    Next

    FindTopLeft = Cells(lowestRow, lowestCol).Address(rowabs, colabs)

End Function

感谢更新您的问题并在下面找到我的评论

Excel 确定在公式中使用哪个单元格的系统是什么,因为我不相信它是 'top left' - 它可能是 'find the topmost row, then find the leftmost cell there',也可能反过来,或者完全不同。

通常 Excel 中的范围类似于具有固定长度和宽度的框或矩形,例如B3:C8。在这种简单的框类型范围的情况下,最左上角的单元格是条件格式中所有公式的基础。换句话说,在第一次公式评估时,将根据条件格式中应用的公式检查此单元格的值。 (暂且称此细胞为母细胞)

例如

  • 如果条件格式应用于单元格 A1:D10 并且有条件 公式为 B2 > 0,这意味着如果值为 B2 > 0,对于其他人,如果 a 的值适用于任何单元格 偏移量为 (1, 1) 的单元格(在 A1 情况下为 B2)具有值 大于 0。即,将检查 C3 的 B2 值的格式。
  • 如果条件格式应用于单元格 A1:D10 并且有条件 公式是 AND($B1 >= 30, $B1 <= 60) 这意味着将格式应用于 如果条件值为真,则单元格 A1,但现在差异来了, 因为 B 现在因为 $B 是静态的,对于条件格式 B2 条件将再次为 AND($B1 >= 30, $B1 <= 60) 与 C1 相同 和 D1,但对于 A2、B2、C2 和 D2,它将是 AND($B2 >= 30, $B2 <= 60)

在第一种情况下,根据公式检查的第一个单元格是 A1,即使在第二种情况下,根据条件公式检查的单元格也是 A1(我们称之为母单元格)

现在如果范围不像一个框,它是一个用逗号分隔的混合范围,即使在这种情况下,如果我们在该范围周围制作一个框,母单元格是左上角的单元格,它不是范围的第一个单元格但框的第一个单元格。

对于你的第二个问题,我怎样才能最好地找到给定范围内的那个单元格?

如果你想在像简单Range这样的方框中找到母单元格,它只是单元格(1, 1)

如果你想找到混合范围内的单元格,可能有一些功能,但我不知道;我会发现通过使用如下循环

Sub find_topleft()

 Dim r, full_range As Range

 Set r = Range("$O:$O,$Q:$Q,$S:$S")

 Set full_range = Sheets("Sheet1").UsedRange

 row_num = full_range.Rows.Count + full_range.Row - 1
 col_num = full_range.Columns.Count + full_range.Column - 1

 For Each c In r
    If c.Row < row_num Then
    row_num = c.Row
    End If

    If c.Column < col_num Then
    col_num = c.Column
    End If
 Next

 Debug.Print row_num
 Debug.Print col_num

End Sub

有没有一种好的方法可以在公式中找到对该单元格的引用,包括该单元格的相对版本和混合版本?

该单元格与第一个问题的答案中所述的公式直接相关联。