如何比较两个多区域范围
How to compare two multi-area ranges
我有两个范围类型的变量,比如 r1 和 r2。我如何检查它们是否在同一范围内?如果它是单个单元格或单个连续的单元格区域,这很容易(我们可以假设它们在同一张纸上):
If r1.Address = r2.Address Then
但是如果它们是多区域范围 (r1.Areas.Count > 0) 怎么办?在大多数情况下,上述代码行仍然有效,但区域地址在 r1 和 r2 地址中出现的顺序可能不同。例如,在某些情况下您将遇到以下情况:
Debug.Print r1.Address
Debug.Print r2.Address
可以导致
"$A,$B"
"$B,$A"
它们显然是相同的范围,但上面 IF 语句中的条件将计算为 false。
理想情况下,我想说 IF r1 = r2 Then,但这行不通。也许我可以试试 Union...
编辑:
我也试过了
If r1 Is r2 Then
但这也不管用。
考虑一个简单的双循环:
Sub SameCheck(R1 As Range, R2 As Range)
Dim r As Range
For Each r In R1
If Intersect(r, R2) Is Nothing Then
MsgBox "not the same"
Exit Sub
End If
Next r
For Each r In R2
If Intersect(r, R1) Is Nothing Then
MsgBox "not the same"
Exit Sub
End If
Next r
MsgBox "the same"
End Sub
测试如下:
Sub MAIN()
Call SameCheck(Range("A1:Z100"), Range("B9"))
Call SameCheck(Range("A1:C3"), Range("A1:C3"))
End Sub
我在 SO 的其他地方遇到了一个很好的解决方案:
If (Intersect(r1,r2).Cells.Count = r1.Cells.Count) AND Intersect(r1,r2).Cells.Count = r2.Cells.Count Then
这是可行的,因为如果两个范围不完全相同,那么两个范围的交集的单元格将始终少于其中至少一个单元格。
编辑
根据下面 Rusan 的评论,很明显,在某些情况下,即使 r1 和 r2 是 "same",上述条件也会计算为 False。我使用引号是因为它需要被定义,我说它们是 "same" 范围的意思:如果你在 r1 的外边缘周围画一个边界,在 r2 的外边缘周围画一个边界,那么边界必须是沿着完全相同的路径。
正如 Rusan 指出的那样,如果 r1 和 r2 中的一个或两个具有重叠的单元格,则会出现问题。因此我们需要先"de-overlap"他们:
Public Function GetNonOverlappedRange(r As Range) As Range
Dim cell As Range, area As Range, newRange As Range
For Each area In r.Areas
For Each cell In area
If newRange Is Nothing Then
Set newRange = cell
Else
If Intersect(cell, newRange) Is Nothing Then
Set newRange = Union(newRange, cell)
End If
End If
Next
Next
Set GetNonOverlappedRange = newRange
End Function
然后
Set r3 = GetNonOverlappedRange(r1)
Set r4 = GetNonOverlappedRange(r2)
If (Intersect(r3,r4).Cells.Count = r3.Cells.Count) AND Intersect(r3,r4).Cells.Count = r4.Cells.Count Then
'If this is true then r1 and r2 are the "same" range
我应该指出,Gary 的学生在下面的回答提供了我问题的正确答案,我会将其标记为正确答案,但我认为构建上面的 "de-overlapping" 函数还是很有用的,因为我可以看到很多需要它的情况。
我有两个范围类型的变量,比如 r1 和 r2。我如何检查它们是否在同一范围内?如果它是单个单元格或单个连续的单元格区域,这很容易(我们可以假设它们在同一张纸上):
If r1.Address = r2.Address Then
但是如果它们是多区域范围 (r1.Areas.Count > 0) 怎么办?在大多数情况下,上述代码行仍然有效,但区域地址在 r1 和 r2 地址中出现的顺序可能不同。例如,在某些情况下您将遇到以下情况:
Debug.Print r1.Address
Debug.Print r2.Address
可以导致
"$A,$B"
"$B,$A"
它们显然是相同的范围,但上面 IF 语句中的条件将计算为 false。
理想情况下,我想说 IF r1 = r2 Then,但这行不通。也许我可以试试 Union...
编辑:
我也试过了
If r1 Is r2 Then
但这也不管用。
考虑一个简单的双循环:
Sub SameCheck(R1 As Range, R2 As Range)
Dim r As Range
For Each r In R1
If Intersect(r, R2) Is Nothing Then
MsgBox "not the same"
Exit Sub
End If
Next r
For Each r In R2
If Intersect(r, R1) Is Nothing Then
MsgBox "not the same"
Exit Sub
End If
Next r
MsgBox "the same"
End Sub
测试如下:
Sub MAIN()
Call SameCheck(Range("A1:Z100"), Range("B9"))
Call SameCheck(Range("A1:C3"), Range("A1:C3"))
End Sub
我在 SO 的其他地方遇到了一个很好的解决方案:
If (Intersect(r1,r2).Cells.Count = r1.Cells.Count) AND Intersect(r1,r2).Cells.Count = r2.Cells.Count Then
这是可行的,因为如果两个范围不完全相同,那么两个范围的交集的单元格将始终少于其中至少一个单元格。
编辑
根据下面 Rusan 的评论,很明显,在某些情况下,即使 r1 和 r2 是 "same",上述条件也会计算为 False。我使用引号是因为它需要被定义,我说它们是 "same" 范围的意思:如果你在 r1 的外边缘周围画一个边界,在 r2 的外边缘周围画一个边界,那么边界必须是沿着完全相同的路径。
正如 Rusan 指出的那样,如果 r1 和 r2 中的一个或两个具有重叠的单元格,则会出现问题。因此我们需要先"de-overlap"他们:
Public Function GetNonOverlappedRange(r As Range) As Range
Dim cell As Range, area As Range, newRange As Range
For Each area In r.Areas
For Each cell In area
If newRange Is Nothing Then
Set newRange = cell
Else
If Intersect(cell, newRange) Is Nothing Then
Set newRange = Union(newRange, cell)
End If
End If
Next
Next
Set GetNonOverlappedRange = newRange
End Function
然后
Set r3 = GetNonOverlappedRange(r1)
Set r4 = GetNonOverlappedRange(r2)
If (Intersect(r3,r4).Cells.Count = r3.Cells.Count) AND Intersect(r3,r4).Cells.Count = r4.Cells.Count Then
'If this is true then r1 and r2 are the "same" range
我应该指出,Gary 的学生在下面的回答提供了我问题的正确答案,我会将其标记为正确答案,但我认为构建上面的 "de-overlapping" 函数还是很有用的,因为我可以看到很多需要它的情况。