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



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

我想知道公式是否包含一个单元格引用,该引用将在AppliesTo指定的范围内更改,例如C3:D10范围内的=NOT(ISNUMBER(C3))

据我所知,该引用可能是相对的(例如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)并没有给出正确的答案(根据Excel制作的公式,BE8)。

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

因此,主要的问题是:Excel的系统是什么来决定在公式中使用哪个单元格,因为我不认为它是"左上角"——它可能是"找到最上面的一行,然后在那里找到最左边的单元格",也可能是相反的,或者完全不同

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

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

请注意,这些奇怪的范围来自于使用"条件格式"在工作表上剪切和粘贴的行和列,Excel因此会截断条件格式(更改范围和更改公式,两者都没有用户输入)。因此,在这种情况下,首要任务是处理Excel将公式设置为自己的任何内容,不一定是用户可能会做什么,但处理两者会更好。

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

Excel决定在公式中使用哪个单元格的系统是什么,因为我不认为它是"左上角"——它可能是"找到最上面的行,然后在那里找到最左边的单元格",也可能是相反的,或者完全不同

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

例如

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

在第一种情况下,对照公式检查的第一个细胞是A1,甚至在第二种情况下对照条件公式检查的细胞是A1(我们称之为母细胞)

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

对于您的第二个问题,我如何才能在给定范围内找到该单元格

如果你想在一个简单的框中找到母细胞,它只是细胞(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

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

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

第一个答案:简短版本:Excel确实使用了最左上角的单元格,但它确实使用了即使该单元格不在范围内

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

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

配方:=LEN(TRIM(A1))>0

因此,尽管A1不在范围内,但这就是公式中使用的内容。

我在纸上复印了一遍,结果保持了一致。

因此,Excel会找到范围中最左边的列和范围中最上面的行,并将它们组合在一起,生成应被视为范围"左上角"的单元格,即使生成的单元格实际上不是范围的一部分

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

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

我仍然欢迎:

  • 任何能够改进配方中使用哪种细胞的答案的人(我没有对此进行广泛测试)
  • 任何能提出找到上述"左上角单元格"的好方法的人
  • 任何能够提出搜索左上角单元格的公式字符串的好方法的人

EDIT-这是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

最新更新