Select excel 中的按钮基于其位置(范围)
Select a button in excel based on its position (range)
我一直在寻找,似乎没有明确的答案。
在 excel 中,使用 VBA, 有没有办法 select 基于其位置的表单按钮(例如在单元格 'A3' 上方)? 找到按钮所在的单元格是可能的,但相反的似乎是不可能的(当然,除了遍历所有按钮)。
我问的原因是我有一列,其中每个单元格都有 2 个可能的值。如果选择其中一个值,我希望能够删除同一行但不同列中的按钮。
有人可以提出解决方案吗?
我不建议使用以下方法,因为必须满足很多要求才能使其正常工作。这绝对不是一个好习惯。但是,由于您不想重复,这可能就是您要查找的内容。
想法
通过 ActiveSheet.Buttons() collection 中的位置访问所需按钮,并使用当前单元格的 行确定一下。
ActiveSheet.Buttons(ActiveCell.Row - [Number of initial rows without a button]).Visible = False
要求
- 所有按钮都按升序排列,这意味着第一个按钮被放置在带有按钮的第一行,第二个按钮在下一行,依此类推。
- 你有每行一个按钮(你也可以调整代码,如果你有每行相同数量的按钮 )
- 所有按钮都位于 连续行 中(如果每个 行之间的行数相同 也可以工作 =]按钮行。当然,你得调整代码)
- 您可以 隐藏而不是删除 按钮(显然您不能删除按钮,因为它会影响 ActiveSheet.Buttons 的索引 collection)
截图
下面的截图是在 C3
被激活并且宏是 运行 之后制作的。
问题的前提似乎是迭代 sheets 上的按钮不知何故“不好”。我猜这里的“坏”是指慢。
在给定单元格上定位按钮的“明显”方法是迭代 sheet 上的按钮并测试 TopLeftCell
属性。测试此策略表明此 是 慢。但不是迭代按钮很慢,访问 TopLeftCell
属性 很慢。
那么,我们在迭代时还能测试什么?事实证明,访问 .Top
、.Left
、.Height
和 .Width
属性非常快。这些属性可用于相对于单元格定位按钮。
OP 没有具体说明他们使用的是 ActiveX 控件还是表单控件。以下代码是为 表单控件编写的。 如果需要,它可以很容易地适应 ActiveX。
假设:
- 按钮是表单控件。
- sheet 上只有按钮。如果存在其他形状,那么它可能会找到其中之一。
- 它正在寻找左上角在传递范围的左上角单元格内的按钮。
- 它只在非隐藏范围内调用。如果它需要为隐藏范围工作,那么它将需要额外的逻辑来避免误报。
- 如果找不到按钮 returns
Nothing
Function GetButtonOverCell(rng As Range) As Object
Dim btn As Object
Dim TL As Range
Set TL = rng.Cells(1, 1)
If TL.EntireRow.Hidden = True Or TL.EntireColumn.Hidden = True Then
Exit Function
End If
For Each btn In rng.Worksheet.Shapes
If TL.Top <= btn.Top Then
If TL.Left <= btn.Left Then
If TL.Top + TL.Height >= btn.Top Then
If TL.Left + TL.Width >= btn.Left Then
If btn.TopLeftCell.EntireRow.Hidden = False And btn.TopLeftCell.EntireColumn.Hidden = False Then
Set GetButtonOverCell = btn
Exit Function
End If
End If
End If
End If
End If
Next
End Function
在我的硬件上,在包含 1600 个按钮的 sheet 上进行测试,运行时间约为 0.1 秒。相比之下,使用测试 .TopLeftCell
的方法大约需要 27s
我一直在寻找,似乎没有明确的答案。
在 excel 中,使用 VBA, 有没有办法 select 基于其位置的表单按钮(例如在单元格 'A3' 上方)? 找到按钮所在的单元格是可能的,但相反的似乎是不可能的(当然,除了遍历所有按钮)。
我问的原因是我有一列,其中每个单元格都有 2 个可能的值。如果选择其中一个值,我希望能够删除同一行但不同列中的按钮。
有人可以提出解决方案吗?
我不建议使用以下方法,因为必须满足很多要求才能使其正常工作。这绝对不是一个好习惯。但是,由于您不想重复,这可能就是您要查找的内容。
想法
通过 ActiveSheet.Buttons() collection 中的位置访问所需按钮,并使用当前单元格的 行确定一下。
ActiveSheet.Buttons(ActiveCell.Row - [Number of initial rows without a button]).Visible = False
要求
- 所有按钮都按升序排列,这意味着第一个按钮被放置在带有按钮的第一行,第二个按钮在下一行,依此类推。
- 你有每行一个按钮(你也可以调整代码,如果你有每行相同数量的按钮 )
- 所有按钮都位于 连续行 中(如果每个 行之间的行数相同 也可以工作 =]按钮行。当然,你得调整代码)
- 您可以 隐藏而不是删除 按钮(显然您不能删除按钮,因为它会影响 ActiveSheet.Buttons 的索引 collection)
截图
下面的截图是在 C3
被激活并且宏是 运行 之后制作的。
问题的前提似乎是迭代 sheets 上的按钮不知何故“不好”。我猜这里的“坏”是指慢。
在给定单元格上定位按钮的“明显”方法是迭代 sheet 上的按钮并测试 TopLeftCell
属性。测试此策略表明此 是 慢。但不是迭代按钮很慢,访问 TopLeftCell
属性 很慢。
那么,我们在迭代时还能测试什么?事实证明,访问 .Top
、.Left
、.Height
和 .Width
属性非常快。这些属性可用于相对于单元格定位按钮。
OP 没有具体说明他们使用的是 ActiveX 控件还是表单控件。以下代码是为 表单控件编写的。 如果需要,它可以很容易地适应 ActiveX。
假设:
- 按钮是表单控件。
- sheet 上只有按钮。如果存在其他形状,那么它可能会找到其中之一。
- 它正在寻找左上角在传递范围的左上角单元格内的按钮。
- 它只在非隐藏范围内调用。如果它需要为隐藏范围工作,那么它将需要额外的逻辑来避免误报。
- 如果找不到按钮 returns
Nothing
Function GetButtonOverCell(rng As Range) As Object
Dim btn As Object
Dim TL As Range
Set TL = rng.Cells(1, 1)
If TL.EntireRow.Hidden = True Or TL.EntireColumn.Hidden = True Then
Exit Function
End If
For Each btn In rng.Worksheet.Shapes
If TL.Top <= btn.Top Then
If TL.Left <= btn.Left Then
If TL.Top + TL.Height >= btn.Top Then
If TL.Left + TL.Width >= btn.Left Then
If btn.TopLeftCell.EntireRow.Hidden = False And btn.TopLeftCell.EntireColumn.Hidden = False Then
Set GetButtonOverCell = btn
Exit Function
End If
End If
End If
End If
End If
Next
End Function
在我的硬件上,在包含 1600 个按钮的 sheet 上进行测试,运行时间约为 0.1 秒。相比之下,使用测试 .TopLeftCell
的方法大约需要 27s