我有一张电子表格,其中有一张图表,列出了几个不同对象的左边缘、右边缘、顶部和底部相对于左上角某个点的位置。我想设置一个条件,当对象创建的某个区域与其他区域重叠时,将包含该对象的单元格格式化为红色。例如,如果:
......................对象 1:............对象 2............对象 3:
左边缘:........... 2 .........0.................3
右边缘:.........6...........................2.......................8
顶部:....................1........................10......................8
底部:................6 .........................12 .........................8
然后对象 1和对象 3会亮起红灯,因为它们重叠,但是对象 2会保持不亮,因为它不会在任何地方与任何其他东西重叠。我编写了一个程序,通过对每个对象执行一长串 AND 语句(每个对象的每条边执行三个 AND 语句)的 OR 操作,成功地实现了这一点,但这非常混乱、耗时、容易出错,并且对于超过 4 个对象来说完全不切实际。有没有更好的方法?如果有人能帮助我,我将不胜感激。
答案1
VBA 宏可以满足您的要求。在 Windows 上,Alt+F11 将调出 VBA 编辑器。
需要遵循的一般伪代码是:
- 选择第一行
- 清除其中的高亮格式
- 用来
For Each
水平行走 - 每个对象将其下方 4 个单元格的值存储在命名变量中
- 然后在内循环中将这些值与右侧的所有对象进行比较
- 比较将符合逻辑并结合水平和垂直重叠测试
- 如果有重叠,则标记两个单元格
使用此方法,如果您有 10 个盒子,则检查 45 对而不是 100 对(10*10)
答案2
还有几点需要考虑:
Sub DetectOverlaps()
Const OBJECTCOUNT As Long = 3
Dim i As Long, j As Long
Dim ArrObj1 As Variant, ArrObj2 As Variant
Dim Object1 As Range, Object2 As Range
Debug.Print: Debug.Print
For i = 1 To OBJECTCOUNT - 1
j = i + 1
While j <= OBJECTCOUNT
ArrObj1 = Range("A1").Offset(1, i).Resize(4, 1)
ArrObj2 = Range("A1").Offset(1, j).Resize(4, 1)
Set Object1 = CoordinatesToRange(ArrObj1)
Set Object2 = CoordinatesToRange(ArrObj2)
Debug.Print "checking " & i & "-" & j, Object1.Address & " vs. " & Object2.Address,
If Application.Intersect(Object1, Object2) Is Nothing Then
Debug.Print " -->ok"
Else
Debug.Print " -->COLLISION"
End If
j = j + 1
Wend
Next i
End Sub
Function CoordinatesToRange(RangeAsArray As Variant) As Range
' RangeAsArray contains coordinates, in order: left, right, top, bottom
Set CoordinatesToRange = Cells(RangeAsArray(3, 1) + 1, RangeAsArray(1, 1) + 1).Resize(RangeAsArray(4, 1) - RangeAsArray(3, 1) + 1, RangeAsArray(2, 1) - RangeAsArray(1, 1) + 1)
End Function
这利用该Application.Intersect
方法检测重叠范围(由矩形坐标构建)。这里的范围实际上没有意义,但只要坐标介于 0 和您版本的 Excel 中允许的最大行/列之间,这将判断任何两个范围对之间是否存在冲突。
我假设您对“对象”的定义是根植于A1
并具有一行和一列标题。顶部的常量只是用于指定感兴趣对象数量的廉价代码;您可以根据情况进行更改,或者在您的应用程序中使其动态化。