我在 Excel VBA 中编写了一些简单的代码,以使范围“闪烁”一种颜色 - 这是通过在相关范围上仔细绘制一个矩形对象并改变其透明度以使框逐渐消失来实现的。
这是代码(Sheet1
用于Worksheet_Change
事件):
Option Explicit
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Sub flashBox(ByVal area As Range, Optional ByVal fillColour As MsoRGBType = vbGreen)
Const animationSeconds As Single = 0.5
Const animationSteps As Long = 20
With area.Worksheet.Shapes.AddShape(msoShapeRectangle, area.Left, area.Top, _
Application.WorksheetFunction.Min(area.Width, 1000), _
Application.WorksheetFunction.Min(area.Height, 1000)) 'stop infinite boxes, could use view area to define this
.Line.Visible = msoFalse
.Fill.ForeColor.RGB = fillColour
Dim i As Long
For i = 1 To animationSteps
Sleep animationSeconds * 1000 / animationSteps
.Fill.Transparency = i / animationSteps
DoEvents 'screen repaint
Next i
.Delete
End With
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
flashBox Target, ColorConstants.vbMagenta
End Sub
我使用一个With
块来包含没有父变量的临时对象(我认为它非常整洁,并希望保持这种方式)。问题来自DoEvents
调用(需要强制为动画重新绘制屏幕)。
动画是从某些工作表更改事件中调用的,如果调用了 sub 的第二个实例(或者实际上似乎发生了任何事件),第一个实例将被终止半完整,并且永远不会完成 - 这意味着永远不会删除临时形状.
我该如何解决这个问题?