【问题标题】:Excel Conditional formatting formula and ranges (VBA)Excel 条件格式公式和范围 (VBA)
【发布时间】:2018-11-11 05:11:50
【问题描述】:

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

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

据我所知,该引用可能是相对的(例如C3)或混合的(例如$C3C$3),但不是绝对的。它也将是基于https://www.ablebits.com/office-addins-blog/2014/08/07/relative-absolute-cell-references-excel-conditional-formatting/ 和其他一些网站的“应用范围内最左上角的单元格”。

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

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

此外,如果范围类似于$A$5,$E$1 - 没有“左上角”。那么excel(或用户)如何决定公式中应该包含哪些内容?

因此主要问题是:Excel 确定在公式中使用哪个单元格的系统是什么,因为我不相信它是“左上角” - 它可能是“找到最上面的行,然后找到最左边的单元格',或者可能是相反的,或者完全不同的东西。

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

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

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

【问题讨论】:

  • 如果您复制/粘贴为 paste.special 值或 paste.special 公式,这将保留任何条件格式并保持不变...
  • 感谢您的提醒,我知道这一点。但在尊重方面,这个问题是关于处理公式并适用于,而不是关于条件格式被搞砸的问题(这是它自己独立的问题,而且是一个大问题)。
  • 看来你的问题包含了很多问题,而且都混在了一起。我正在阅读它,当你的陈述在问题之间不断跳跃时,我的注意力正在迷失。您应该将它们分开以获得好的答案。你自己解决问题的技巧也是如此;如果你把所有的问题都看成一个大问题,那就很难解决了,但是如果你把它们分开,那么每个小问题都可以很容易地解决。
  • @usmanhaq,感谢您的意见。我进行了编辑以使其更清晰。说实话,我通常的目标是更简洁 - 但上次我问一个问题时,我被告知只给出一个非常有限的目标或需要我犯了一个错误,因为他们需要一个更大的图片来看看这件事是否我问的是什至是这样做的方法。我并不完全同意这一点,但我仍然尝试提供一些背景信息,尤其是因为这不是我的专业领域。

标签: excel vba conditional-formatting


【解决方案1】:

感谢您更新您的问题并在我的 cmets 下方找到

Excel 确定在公式中使用哪个单元格的系统是什么,因为我不相信它是“左上角” - 它可能是“找到最上面的行,然后找到最左边的单元格” ,或者可能是相反的,或者完全不同的东西。

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

例如

  • 如果条件格式应用于单元格 A1:D10 和条件 公式为 B2 > 0,这意味着如果值为 B2 > 0,对于其他人,如果值为 a,则将格式应用于任何单元格 偏移量为 (1, 1) 的单元格(在 A1 情况下为 B2)具有值 大于 0。即将检查 C3 的 B2 值的格式。
  • 如果条件格式应用于单元格 A1:D10 和条件 公式是 AND($B1 >= 30, $B1 = 30, $B1 = 30, $B2

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

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

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

如果你想在简单 Range 之类的框中找到母单元格,它只是单元格 (1, 1)

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

Sub find_topleft()

 Dim r, full_range As Range

 Set r = Range("$O$8:$O$17,$Q$4:$Q$13,$S$4:$S$6")

 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

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

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

【讨论】:

  • 非常感谢您的回答。 “母盒”的概念基本上是我在回答中发现的,但它可能更清楚。至于你的代码,那太好了。我将它转换为函数Private Function FindTopLeft(r As range, ws As Worksheet, rowabs As Boolean, colabs As Boolean) As String,因为我需要一个字符串,所以在最后添加了FindTopLeft = Cells(row_num, col_num).Address(rowabs, colabs),效果很好。
  • 我会对您对我所做的代码的想法感兴趣(请参阅我编辑的答案)。我怀疑我的会更快(我的使用字符串函数,除了在行/单元格之间进行转换,但更重要的是只对几个单元格执行此操作)。你怎么看?我将推迟选择答案,看看你说什么。我希望我能有两个答案,真的,因为关于 Mother Box,你的答案比我的更清楚,但我们的代码都可以工作,但方式各不相同。
  • 哦,我还认为,与其使用 UsedRange,不如将初始 row_num 和 col_num 设置为最大值,就像我所做的那样 - 这有点不太清楚,但可能会节省一点 CPU 时间。不过,我真的很喜欢你的代码。
  • 您的代码采用了不同的方法,但看起来不错,我这边的一些 cmets 是
  • (1) 我没有使用静态的最后一行和列号,因为它们在不同的 excel 版本中是不同的 (2) 我没有检查,但我认为删除 $ 符号不会有任何区别relativeCell = Replace(cell, "$", "") (3) 因为您已经在使用“range(relativeCell).Column”,所以您可以直接在整个范围内使用它,只需根据逗号分割实际范围 (4)我在全范围检查每个单元格并且您的代码仅检查范围名称的部分肯定会节省大量循环计数(5)您可以再等几天,如果幸运的话,其他人也会回答跨度>
【解决方案2】:

第一个答案: 简短版本:Excel 确实使用了最左上角的单元格 - 但它会这样做即使该单元格不是范围的一部分

我创建了一张空白工作表,选择了A5,E1,并输入了 NOT BLANK 的条件格式(Excel 使用公式执行此操作)。 Excel 创建了以下内容:

范围:$E$1,$A$5

公式:=LEN(TRIM(A1))&gt;0

因此,即使 A1 不在范围内,这也是公式中使用的内容。

我通过在工作表周围复制它来检查这一点,它保持一致。

因此 Excel 会找到区域中最左侧的列和区域中的最顶行,并将它们组合起来以生成应该被视为区域“左上角”的单元格,即使生成的单元格是实际上不是范围的一部分。

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

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

我仍然欢迎:

  • 任何可以改进有关公式中使用哪个单元格的答案的人(我没有对此进行广泛测试)
  • 任何可以提出找到上述“左上单元格”的好方法的人
  • 谁能提出一种搜索左上角单元格的公式字符串的好方法

编辑 - 这是 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-19
    • 2014-12-27
    • 2017-03-03
    • 1970-01-01
    • 1970-01-01
    • 2018-02-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多