【问题标题】:excel vba - Is there a way to prevent macro button spamming?excel vba - 有没有办法防止宏按钮垃圾邮件?
【发布时间】:2018-11-28 10:02:50
【问题描述】:

我有一张包含几个宏按钮的表格,它们的作用都略有不同,一切都很好,除非用户垃圾邮件点击不同的按钮有点快。

我没有足够的经验知道这是一个常见问题还是我的代码工作方式的问题,但是如果单击一个宏按钮并在单击另一个按钮之前正确执行,似乎一切正常。即使是垃圾邮件单击同一个宏按钮似乎也能正常工作,但在快速连续单击两个或更多按钮时,代码无法正常执行。

代码本身只是查找具有特定值的单元格,并添加或删除行,有时还会从工作表的其他区域复制和粘贴。例如,如果您要单击按钮 X 查找工作表的 X 部分并在其下方添加一行,然后单击按钮 Y 查找工作表的部分 Y 并删除其上方的一行,则按钮 Y 将无法找到它需要找到的单元格(即使它存在)并触发一个错误消息框,告诉用户 Y 部分似乎丢失了,同时按钮 X 本身也会有一些奇怪的问题,比如删除错误的行,就好像它预期/补偿了什么它期望 Y 这样做。

我尝试在宏开始时对每个命令按钮使用CommandButton1.Enabled = False,并在每个宏结束时再次启用按钮,但无论在宏执行期间,我仍然可以垃圾邮件单击按钮。

有没有一种简单的方法可以防止在当前宏代码运行之前点击其他宏按钮?我试过禁用和启用按钮,我试过添加等待时间。如果我无法解决此问题,我可能会求助于保存重复的隐藏工作表,该工作表在出错时未隐藏,并且问题工作表被删除,另一个“备份”副本被创建并隐藏,同时用户通知不要向宏按钮发送垃圾邮件。

【问题讨论】:

  • 这些是activeX按钮吗?您是否尝试过使用超链接来运行代码?我总是使用超链接而不是按钮,但主要是为了防止调整大小错误
  • 是的,它们是 ActiveX 按钮。调整错误大小是什么意思?另外,我尝试将宏设置为不是 activeX 按钮的其他形状,但它们无法调用其他 sub,所以我没有进一步研究。
  • 调整大小错误是一个可怕的错误,您将笔记本电脑插入第二个屏幕,然后 Excel 工作表上的 activeX 按钮开始随着每次点击而增大(或者按钮上的文本变得如此小你看不到)
  • 我得调查一下,这听起来很可怕,哈哈。这里的大多数工作站都是插入底座的笔记本电脑,底座上有两个屏幕,以及带有双屏幕的标准工作站。
  • 我没有测试它,但是在宏开始时将全局(布尔)变量设置为 true 并在宏完成后设置为 false 是否有效?在宏的开头,您会问诸如“If disalbed=true then End sub”之类的问题?

标签: vba excel error-handling runtime-error


【解决方案1】:

在每个按钮的开头添加一个检查到全局变量。只有在没有其他按钮同时运行时才运行该按钮的代码。

如果代码运行时间较长,我添加了图标更改以显示程序在运行代码时很忙,正如 Chronocidal 所建议的那样。

Public Running As Boolean

Private Sub CommandButton1_Click()
If Running = False Then
    Running = True
    Application.Cursor = xlWait        

    ' Your Buttons Code

    Running = False
    Application.Cursor = xlDefault
Else ' (Optional)
    MsgBox ("I'm busy, try again later!")
End If

End Sub

【讨论】:

  • 或使用 Application.Cursor = xlWaitApplication.Cursor = xlDefault 将光标设置为沙漏/旋转圆圈 - 大多数 用户经过培训可以理解这意味着“停止做事直到电脑完成”
  • @Chronocidal 我喜欢额外的用户反馈。将更新答案以包含它。
【解决方案2】:

这是基于以下观察结果:

你看不到的,你不能点击。

所有按钮,无论是窗体按钮、ActiveX 按钮还是自选图形,都是Shapes。所有Shapes 要么是Visible,要么不是Visible

如果Shape 不是Visible,则无法单击它。因此,在每个按钮 sub 的开头都包含对以下内容的调用:

Sub HideAllButtons()
    Dim s As Shape
    For Each s In ActiveSheet.Shapes
        s.Visible = False
    Next s
End Sub

并在按钮代码的末尾包含对以下内容的调用:

Sub ShowAllButtons()
    Dim s As Shape
    For Each s In ActiveSheet.Shapes
        s.Visible = True
    Next s
End Sub

因此,当任何按钮正在运行时,用户将被“锁定”,无法点击任何其他按钮。

【讨论】:

  • 谢谢,这是在不改变按钮呈现方式的情况下获得我想要的最简单的方法。出于某种原因,在宏之前/之后的 Application.interactive = FalseTrue 以及 button.enabled = False 之类的东西并不能阻止按钮垃圾邮件 - 但隐藏按钮似乎有效。
  • @Angelo 用户就像鸡一样,喜欢啄东西。这种方法消除了“啄”的诱惑。
【解决方案3】:

我建议使用 UserForm 来托管您的 activeX 控件,或者如果您只有一两个按钮,请将它们替换为工作表上的超链接,并在 worksheet.followhyperlink 事件中使用以下代码来检查单击了哪个超链接:

Private Sub Worksheet_FollowHyperlink(ByVal Target As Hyperlink)
    If Target.Range.Address(False, False) = "A1" Then MsgBox ("Woah I clicked cell A1!")
End Sub

如果您有一个带有按钮的用户表单,那么您可以让每个按钮单击隐藏表单,直到宏自动完成:

Private Sub CommandButton1_Click()
UserForm1.Hide
    ' Do the macro stuff
UserForm1.Show
End Sub

【讨论】:

  • 我目前有 8 个按钮,以及两个当前用于切换工作表语言的选项按钮。对按钮使用用户表单有什么区别?
  • 事实上,您可以使用一个命令禁用整个用户表单,或者实际上隐藏表单以使按钮完全消失(无法单击不存在的内容!)
  • 我还想问一下 - 您是否在代码中某处有一个“DoEvents”行允许在宏运行时单击按钮?
  • 在单击宏按钮后关闭带有按钮的用户窗体听起来好像可以工作,尽管它确实使每个操作都单击 2 次而不是 1 次。此外,我没有任何 DoEvents代码。它们都是相对简单的宏,总共可能需要 1 或 2 秒才能执行,所以我没有考虑添加任何宏。
  • 您可以在单击按钮后自动隐藏表单 - 请参阅我修改后的答案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多