Excel VBA CommandBar. Действие с параметрами затруднено / не работает должным образом - PullRequest
5 голосов
/ 14 апреля 2011

Итак, у меня есть Google, и кажется, что при создании пользовательских всплывающих меню, если кто-то хочет передать параметры, тогда это возможно , но для меня есть 2 основные проблемы:

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.Это быстрый макет, поэтому я не раскрываю проприетарный код и т. Д.

Ответы [ 3 ]

8 голосов
/ 17 апреля 2012

Вы можете использовать свойство .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
8 голосов
/ 15 апреля 2011

Не спрашивайте меня, почему это работает, но это работает.Источник этой информации - Использование процедур с аргументами в неочевидных случаях

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, окруженном одиночные кавычки. Кроме того, вам нужно избегать двойных кавычек с двойными кавычками.Числовые параметры не должны быть экранированы.

0 голосов
/ 03 мая 2016

Причина двойных вызовов и отсутствия точек останова заключается в том, что круглые скобки («()») окружают аргументы в вызове .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 для двойных кавычек («). Все типы данных (целые, длинные, строковые и т. Д.) И кавычки должны начинаться с 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 & "'"). Указатели объектов могут быть переданы (ref: http://www.access -programmers.co.uk / forums / showthread.php? T = 225415 ). Но мне не удалось передать указатели на массивы.

4) .OnAction, используемый в исходном примере, не заключен в кавычки, поэтому вызов .OnAction выполняется при вызове AssignIt (), но до появления всплывающего меню.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...