带有参数的Excel VBA CommandBar.OnAction很难执行/未能按预期执行

|| 因此,我在Google上搜索了一下,似乎在制作自定义弹出菜单时,如果要传递参数,则可以实现,但是对我来说有两个主要问题: 1)您调用的函数将执行,但是您将无法在其上激活断点,甚至无法使用Stop。 2)奇怪的是,它似乎两次被调用,这也不是很有帮助。 代码说明(请放在模块中而不是工作表中)
Option Explicit

Sub AssignIt()

    Dim cbrCmdBar As CommandBar
    Dim strCBarName As String

    On Error Resume Next

    strCBarName = \"MyNewPopupMenu\"

    \'Delete it first so multiple runs can occur without appending
    Application.CommandBars(strCBarName).Delete

    \' Create a menu bar.
    Set cbrCmdBar = Application.CommandBars.Add(Name:=strCBarName, Position:=msoBarMenuBar)

    \' Create a pop-up menu.
    strCBarName = \"MyNewPopupMenu\"
    Set cbrCmdBar = Application.CommandBars.Add(Name:=strCBarName, Position:=msoBarPopup)

    \'DEFINE COMMAND BAR CONTROL
    With Application.CommandBars(strCBarName).Controls.Add(Type:=msoControlButton)
    .Caption = \"MyMenu\"
    .OnAction = BuildProcArgString(\"MyProc\", \"A\", \"B\", \"C\") \'You can add any number of arguments here!
    End With

    \'DEFINE COMMAND BAR CONTROL
    With Application.CommandBars(strCBarName).Controls.Add(Type:=msoControlButton)
        .Caption = \"Test No Args\"
        .OnAction = \"CallWithNoArgs\"
    End With


    Application.CommandBars(strCBarName).ShowPopup

End Sub


Sub CallWithNoArgs()

    MsgBox \"No Args\"

End Sub

\'FUNCTION TO BUILD PROCEDURE ARGUMENTS (You just have to plop this in any of your modules)
Function BuildProcArgString(ByVal ProcName As String, ParamArray Args() As Variant)

    Dim TempArg
    Dim Temp

    For Each TempArg In Args
        Temp = Temp + Chr(34) + TempArg + Chr(34) + \",\"
    Next

    BuildProcArgString = ProcName + \"(\" + Left(Temp, Len(Temp) - 1) + \")\"

End Function

\'AND FINALLY - THE EXECUTABLE PROCEDURE!
Sub MyProc(x, y, z)

    MsgBox x & y & z
    Debug.Print \"arrgggh why won\'t the breakpoint work, and why call twice!!!!!!\"

End Sub
如果有人可以提供帮助,那将是很好。似乎过去有另一位开发人员遇到了麻烦,因此对于5个项目,我们有Method_1 ... Method_5,其编号已传递给Method_Core(ByVal i As Integer)样式。我认为我也会走这条路线,尽管非常丑陋,但比我下面模拟的效果更好。 PS。这是一个快速的模型,因此我不会公开专有代码等     
已邀请:
不要问我为什么会这样,但是可以。该信息的来源是在非显而易见的实例中使用带有参数的过程
Sub AssignIt()
Const strCBarName As String = \"MyNewPopupMenu\"
Dim cbrCmdBar As CommandBar

    \'Delete it first so multiple runs can occur without appending
    On Error Resume Next
    Application.CommandBars(strCBarName).Delete
    On Error GoTo 0

    \' Create a pop-up menu.
    Set cbrCmdBar = Application.CommandBars.Add(Name:=strCBarName, Position:=msoBarPopup)

    \'DEFINE COMMAND BAR CONTROL
    With Application.CommandBars(strCBarName).Controls.Add(Type:=msoControlButton)
        .Caption = \"MyMenu\"
        .OnAction = \"\'MyProc \"\"A\"\",\"\"B\"\",2\'\"
    End With
    Application.CommandBars(strCBarName).ShowPopup
End Sub

Sub MyProc(x As String, y As String, z As Integer)
    MsgBox x & y & (z * 2)
    Debug.Print \"AHA!!! the breakpoint works, and it\'s only called once!!!!!!\"
End Sub
关键是在单引号引起的
.OnAction
事件中调用该过程。另外,您需要用双引号将双引号转义。数值参数不需要转义。     
您可以使用.Parameter属性。这是生产中的代码示例(仅包含感兴趣的行):
        Dim i As Integer
        Set cl = MainForm.Controls(\"classroomList\")
        For i = 0 To cl.ListCount - 1
            With .Controls.Add(Type:=msoControlButton)
                .Caption = cl.List(i)
                .faceId = 177
                .OnAction = \"\'\" & ThisWorkbook.Name & \"\'!\" & \"assignClassroom\"
                .Parameter = cl.List(i)
            End With
        Next i
该过程可能类似于:
Public Sub assignClassroom(Optional someArg as SomeType)
\' code here
CommandBars.ActionControl.Parameter \'The parameter here
\' more code here
End Sub
    
出现两次调用且没有断点的原因是因为.OnAction调用中的参数周围带有括号(“()”):
    .OnAction = BuildProcArgString(\"MyProc\", \"A\", \"B\", \"C\")
最佳猜测:使用这些括号时,.OnAction的解析器会阻塞。 这应该工作:
    .OnAction = \"\'BuildProcArgString\" & chr(34) & \"MyProc\" & _
    chr(34) & \",\" & chr(34) & \"A\" & chr(34) & \",\" & chr(34) & _
    \"B\" & chr(34) & \",\" & chr(34) &  \"C\" &  \"\'\"
其他说明: 1)应该使用第一个双引号之后和最后一个双引号之前的单引号来封装整个调用。 2)Chr(34)是双引号(“)的ASCII字符。所有数据类型(int,long,string等)和带引号的逗号都必须以Chr(34)开头。一个例外是结尾的单引号(\“ \'\”)。例:
    .OnAction = \"\'m_Test\" & Chr(34) & 100 & Chr(34) & \",\" & Chr(34) & _
     intVariable & Chr(34) & \",\" & Chr(34) & \"String\" & Chr(34) & _
     \",\" & Chr(34) & stringVariable & \"\'\"
该函数调用:
    Public Function m_Test(i as Integer, iVar as Integer, s as String, sVar as String)
3).OnAction似乎没有传递数组或对象。可以传递数组中的一项(例如.OnAction = \“ \'myTest \”&Chr(34)&Args(0)&\“ \'\”),但不能传递整个数组(例如.OnAction = \ “ \'myTest \”&Chr(34)&Args&\“ \'\”)。可以传递对象指针(参考:http://www.access-programmers.co.uk/forums/showthread.php?t=225415)。但是我在传递指向数组的指针方面没有成功。 4)原始示例中使用的.OnAction没有用引号引起来,因此.OnAction调用是在调用AssignIt()时但在弹出菜单弹出之前进行的。     

要回复问题请先登录注册