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

所以,我已经谷歌search,似乎在自定义popup菜单,如果有人想传递参数,那么这是可能的,但对我来说有两个主要问题:

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。 这是一个快速的模型,所以我不暴露专有代码等

您可以使用.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 

不要问我为什么这个工作,但它确实。 此信息的来源是在非显而易见的实例中使用具有参数的过程

 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事件中的过程。 此外,你需要用双引号来避免你的双引号。 数字参数不需要转义。

双重调用和没有中断点的原因是因为在.OnAction调用中围绕参数的括号(“()”):

  .OnAction = BuildProcArgString("MyProc", "A", "B", "C") 

最佳猜测:当使用这些圆括号时,.OnAction扼stream器的parsing器。

这应该工作:

  .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字符。 所有数据types(整数,长整数,string等)和逗号需要以一个Chr(34)作为前缀。 一个例外是结尾sinlge报价(“'”)。 例:

  .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不包含引号,因此在AssignIt()被调用时popup菜单popup菜单之前调用.OnAction。