【问题标题】:Call each button containing certain macro调用包含特定宏的每个按钮
【发布时间】:2015-10-06 13:36:46
【问题描述】:

我正在尝试为每个循环执行一个检查活动工作表中的每个按钮的循环,以查看该按钮是否包含某个宏。如果为按钮分配了正确的宏,那么我希望按钮调用 sub,然后转到下一个按钮。

这就是我的想象:

Sub ExecuteAllButtonsContainingX()

Dim Btn As Button   
Dim Btn_count As Integer

Btn_count = 1

For Each Btn In Application.Workbooks.ActiveSheet.Buttons
    Btn(Btn_count).Select  

    If ***[The selected button contains Macro X]*** Then
        ***[Call the macro that is assigned to the selected button as if the button was clicked on]***
    Else
    End If    

    Btn_count = Btn_count + 1

Next Btn

End Sub

我没有得到的是
i) 如何检查按钮是否分配了某个宏,以及
ii) 从所选按钮调用宏

【问题讨论】:

  • 宏是否取决于单击它的按钮 - 即它使用Application.Caller 吗?如果是这样,我认为你不能。如果没有,你已经有两个很好的答案了。 :)
  • 是的,它确实取决于单击哪个按钮并且它使用 application.caller :(
  • 我认为您必须重写被调用的宏(如果可以的话),以便它接受一个可选的 Variant 参数,您可以向该参数传递一个按钮。然后它可以测试它是否丢失(直接从按钮调用时)或接受按钮而不是使用Application.Caller
  • 当我想到它时,结合 ChrisUnbroker 的答案,这将是关键。如何使用可选的 Variant 参数来传递按钮?
  • 查看我刚刚发布的答案。

标签: vba excel button


【解决方案1】:

您可以这样做(代码中的 cmets):

Sub ExecuteAllButtonsContainingX()
    Dim Btn As Button
    'Counter is redundant if you use [For Each] loop.
    'Dim Btn_count As Integer
    '-------------------------------------------------

    'Btn_count = 1


    For Each Btn In ActiveSheet.Buttons

        'Btn(Btn_count).Select      '<--- This is redundant. You don't have to
                                    '     select button to check its properties.


        'If property [OnAction] of the current button is not empty
        'it means there is some macro assigned to this button.
        If Len(Btn.OnAction) Then

            'This action is called only if there is some macro
            'assigned to the current button.
            Call Application.Run(Btn.OnAction)

        End If

        'Btn_count = Btn_count + 1

    Next Btn

End Sub

【讨论】:

  • 谢谢!但是,您建议的代码将从所有按钮调用所有宏。我只想调用包含某个宏名称的按钮。例如。假设有三种类型的按钮和三种不同类型的宏,我们称它们为按钮 1、2 和 3。工作表中每种类型都有几个按钮。我希望调用一种类型的所有按钮。例如。如果是 Button 类型 2 但不是 Button 类型 1 或 3,则代码会遍历所有按钮并执行它。
【解决方案2】:

这可以解决问题 - 但如果按钮上没有附加宏,不确定会发生什么。

Sub ExecuteAllButtonsContainingX()

    Dim Btn As Shape

    For Each Btn In Sheet1.Shapes
        If Btn.FormControlType = xlButtonControl Then
            Run Btn.OnAction
        End If
    Next Btn

End Sub

【讨论】:

  • 使用@mielk - 他查看按钮而不是形状,并检查是否附加了宏。 :)
【解决方案3】:

如果您的宏名称是固定的,则可以这样做:

Sub ExecuteAllButtonsContainingX()
Dim Btn As Button

For Each Btn In ActiveSheet.Buttons

    If Btn.OnAction = "insertMacroNameHere" Then

        Run Btn.OnAction

    End If

Next Btn

End Sub

如果它经常更改,您可以将其作为参数传递:

Sub ExecuteAllButtonsContainingX(macroName As String)
Dim Btn As Button

For Each Btn In ActiveSheet.Buttons

    If Btn.OnAction = macroName Then

        Run Btn.OnAction

    End If

Next Btn

End Sub

【讨论】:

  • 这看起来完全正确,正是我想要的。但是,由于某种原因,它永远不会进入“Run Btn.OnAction”,即它会跳过所有按钮,即使是那些包含正确宏名称的按钮
  • 尝试通过为工作簿名称添加前缀来更改 sub 中的宏名称,例如“Workbook1.xlsx!宏名”。如果这没有解决,请查看调试器中 OnAction 属性的值。
  • 还有一个问题。尽管执行了宏,但由于该宏依赖于 application.caller,因此它会以错误代码 1004 停止
【解决方案4】:

由于您需要宏知道哪个按钮调用了它,因此您需要重新编码按钮调用的宏以获取可选参数。按钮在调用宏时不需要传递任何东西,所以它们不会改变,但是这个循环代码在调用宏时需要传递按钮。

例如,下面是按钮调用的示例宏,编码为采用可选参数:

Sub foomsg(Optional vButton As Variant)
    Dim btn                   As Button
    If IsMissing(vButton) Then
        Set btn = ActiveSheet.Buttons(Application.Caller)
    Else
        Set btn = vButton
    End If
    MsgBox btn.Name
End Sub

然后这里有一个宏,用于循环并为每个使用它的按钮调用该宏:

Sub foo()
    Dim btn                   As Button
    Dim sMacroName            As String
    Dim cf                    As ControlFormat

    sMacroName = "foomsg"
    For Each btn In ActiveSheet.Buttons
        If Right$(btn.OnAction, Len(sMacroName)) = sMacroName Then
            Run btn.OnAction, btn
        End If
    Next btn
End Sub

希望这是有道理的。如果没有,请问!

【讨论】:

  • 这太棒了,它解决了一切!非常感谢!
猜你喜欢
  • 2020-10-26
  • 2022-04-17
  • 2020-09-24
  • 1970-01-01
  • 2013-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多