Страницы: 1
RSS
Пользовательское меню VBA IDE, Не запускается выполнение пунктов созданного меню в VBA IDE
 
Создал пункты меню в VBA. Именно в панели VBA а не панели Excel'я. Создавал вот так:
Код
  Public Sub Ro_AddMenuVBE()
  Dim mnuName As String, u As String
  Dim N As Integer, i As Integer, c As Integer
      u = "&Moё"
      N = Application.VBE.CommandBars.Count
      For i = 1 To N
          With Application.VBE.CommandBars.Item(i)
              If .Type = msoBarTypeMenuBar Then
                  For c = 1 To .Controls.Count
                      If .Controls.Item(c).Caption = u Then
                          .Controls(u).Delete
                          Exit For                          
                      End If
                  Next

                  With .Controls.add(Type:=msoControlPopup)
                      .Caption = u
                      With .Controls.add(Type:=msoControlButton, ID:=107)
  ' изменил на "латинское" название    .OnAction = "a_Bосстановить_Обработку_Событий"
                          .OnAction = "RestoreAlertsEvents"
                          .Caption = "Bосстановить события 2"
                          .TooltipText = "Bосстановить обработку событий"
                      End With
                      With .Controls.add(Type:=msoControlButton, ID:=107)
                          .OnAction = "a_Bыровнить_Код_Активного_Модуля"
                          .Caption = "Bыровнить код"
                          .TooltipText = "Bыровнить код активного модуля"
                      End With
                      With .Controls.add(Type:=msoControlPopup)
                          .Caption = "Работа с проектом"
                          With .Controls.add(Type:=msoControlButton, ID:=107)
                              .OnAction = "a_Cохранить_все_Модули_в_Архив"
                              .Caption = "Cохранение"
                              .TooltipText = "Cохранить все модули в архив"
                          End With
' и т.д., и т.п.
                      End With
                      
                      With .Controls.add(Type:=msoControlButton, ID:=107)
                          .OnAction = "a_Справка_по_Подключаемой_Библиотеке"
                          .Caption = "Справка"
                          .TooltipText = "Справка по Подключаемой Библиотеке"
                      End With                      
                  End With                 
                  Exit For                  
              End If
          End With
      Next
  End Sub
В результате получается красивая картинка , но пункты .OnAction - не работают.
Подпрограммы просто не вызываются и ничего не происходит.

На этой картинке показан момент остановки отладчика и видно, что обработчик присваивается (слева внизу выделено синим).  
А почему потом не обрабатывает? не сохраняет, что ли?
При повторном входе в этот (или иной) модуль для Item 12 (со второй картинки) будет уже OnAction=""  - почему?
Изменено: leonrom - 15.11.2017 13:49:32 (не могу вставить рисунок)
 
VBE не обрабатывает OnAction. Чтобы все это заработало надо подключить библиотеку "Microsoft Visual Basic For Applications Extensibility".
Далее по шагам:
создаете свой класс(Insert -ClassModule). Называете его CBarEvents.
В нем создаете такой код:
Код
Option Explicit
'объявляем кнопку с возможностью отслеживать события
Public WithEvents cBarC_Event As CommandBarEvents
'это событие срабатывает при клике мышью на кнопке
'   собственно, оно единственное доступное
Private Sub cBarC_Event_Click(ByVal CommandBarControl As Object, handled As Boolean, CancelDefault As Boolean)
    MsgBox "Нажали кнопку: " & CommandBarControl.Caption
    handled = True
    CancelDefault = True
End Sub
теперь в стандартном модуле непосредственно создание меню:
Код
'эта коллекция будет хранить все контролы с обработкой событий
Public oVBE_BarEvents As New Collection

Sub CreateVBEMenu()
    Dim CBarE As CBarEvents
    Dim cBarC As Object

    'Создаем кнопку
    Set cBarC = Application.VBE.CommandBars(1).Controls.Add(Type:=msoControlButton, ID:=107)
    With cBarC
        .Caption = "Bосстановить события 2"
        .TooltipText = "Bосстановить обработку событий"
        .OnAction = "RestoreAlertsEvents"
    End With
    
    'инициализируем класс
    Set CBarE = New CBarEvents
    'добавляем в класс, чтобы события обрабатывались
    Set CBarE.cBarC_Event = Application.VBE.Events.CommandBarEvents(cBarC)
    'добавляем в обработчики
    oVBE_BarEvents.Add CBarE
End Sub

Можно в классе вместо MsgBox "Нажали кнопку: " & CommandBarControl.Caption, записать нечто вроде Application.Run, который будет вызывать процедуру, записанную в OnAction:
Код
Private Sub cBarC_Event_Click(ByVal CommandBarControl As Object, handled As Boolean, CancelDefault As Boolean)
    Application.Run CommandBarControl.OnAction
    handled = True
    CancelDefault = True
End Sub
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
Спасибо за ответ, The_Prist  - так работает! К сожалению пришлось задействовать классы, но, похоже, иначе никак.
Спасибо!
С Вашими дополнениями работающий модуль теперь выглядит так (а вдруг еще кому понадобится;) :
Код
Option Explicit

'эта коллекция будет хранить все контролы с обработкой событий
Public oVBE_BarEvents As New Collection

Private Sub Ro_AddEvent(ctrl As CommandBarButton)
Dim CBarE As CBarEvents
    If ctrl.Type = msoControlButton Then            ' проверка - защита от собственной невнимательности (надо бы еще дать Else...)
    'инициализируем класс
        Set CBarE = New CBarEvents
    'добавляем в класс, чтобы события обрабатывались
        Set CBarE.cBarC_Event = Application.VBE.Events.CommandBarEvents(ctrl)
    'добавляем в обработчики
        oVBE_BarEvents.Add CBarE
    End If
End Sub

 Public Sub Ro_AddMenuVBE()
 Dim mnuName As String, u As String
 Dim N As Integer, i As Integer, c As Integer
      u = "&Moё"
      N = Application.VBE.CommandBars.Count
      For i = 1 To N
          With Application.VBE.CommandBars.Item(i)
              If .Type = msoBarTypeMenuBar Then       ' ищется меню-бар (д.б. под №1, но на всяк случай)
                  For c = 1 To .Controls.Count        ' удаляется предыдущая установка моего меню
                      If .Controls.Item(c).caption = u Then
                          .Controls(u).Delete
                          Exit For
                      End If
                  Next
 
                  With .Controls.Add(Type:=msoControlPopup)
                      .caption = u
                      With .Controls.Add(Type:=msoControlButton, ID:=107)
                          .OnAction = "a_Bосстановить_Обработку_Событий"
                          .caption = "Bосстановить события"
                          .TooltipText = "Bосстановить обработку событий"
                      End With
                      Ro_AddEvent .Controls(.Controls.Count)          ' тут каждый раз будет последний добавленный пункт меню
                      
                      With .Controls.Add(Type:=msoControlButton, ID:=107)
                          .OnAction = "a_другие_обработчики"
                          .caption = "Bыровнить код"
                          .TooltipText = "Bыровнить код активного модуля"
                      End With
                      Ro_AddEvent .Controls(.Controls.Count)
                      
                      With .Controls.Add(Type:=msoControlPopup)
                          .caption = "Работа с проектом"
                          With .Controls.Add(Type:=msoControlButton, ID:=107)
                              .OnAction = "a_другие_обработчики"
                              .caption = "Cохранение"
                              .TooltipText = "Cохранить все модули в архив"
                          End With
                          Ro_AddEvent .Controls(.Controls.Count)
' и т.д., и т.п.
                      End With
                       
                      With .Controls.Add(Type:=msoControlButton, ID:=107)
                          .OnAction = "a_другие_обработчики"
                          .caption = "Справка"
                          .TooltipText = "Справка по Подключаемой Библиотеке"
                      End With
                      Ro_AddEvent .Controls(.Controls.Count)
                  End With
                  Exit For
              End If
          End With
      Next
  End Sub

Private Sub a_Bосстановить_Обработку_Событий(caption As String)
    MsgBox "Bосстановить Обработку Событий - сработало!"
End Sub

Private Sub a_другие_обработчики(caption As String)         ' общее название - чтобы сократить текст примера
    MsgBox "сработало " & caption
End Sub
Здесь предложенные дополнения модуля просто скопированы в отдельную подпрограмму, а в мою часть внесены косметические изменения.

Предложенный же код для класса CBarEvents теперь выглядит так:
Код
Option Explicit
'объявляем кнопку с возможностью отслеживать события это событие срабатывает при клике мышью на кнопке собственно, оно единственное доступное
Public WithEvents cBarC_Event As CommandBarEvents

Private Sub cBarC_Event_Click(ByVal CommandBarControl As Object, handled As Boolean, CancelDefault As Boolean)
    handled = True
    CancelDefault = True
    Application.Run CommandBarControl.OnAction, CommandBarControl.caption
End Sub
Узнать бы еще - почему Microsoft сделал обработчик событий для VBA именно таким хитрым способом  :oops:  
Изменено: leonrom - 15.11.2017 23:43:16
 
Цитата
leonrom написал:
Узнать бы еще - почему Microsoft сделал обработчик событий для VBA именно таким хитрым способом    
CommandBarEvents Интерфейс
наверно, захотели привязать это к Visual Studio SDK и дать возможность только разработчикам в VS колдовать с этим...
p.s.
у меня в Win10 Office2016 работает только так (как во вложении) - только в VBE window видно - пример отсюда, - и при включённых: Центр управления безопасностью - Параметры макросов - Доверять доступ к объектной модели VBA
Изменено: JeyCi - 02.08.2021 17:17:13
чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок - обратитесь к собеседнику на ВЫ - ответ на ваш вопрос получите - а остальное вас не касается (п.п.п. на форумах)
 
Цитата
JeyCi написал:
у меня в Win10 Office2016 работает только так
действительно не заметила сразу - вариант от The_Prist тоже работает - появляется справа от Help сверху в VBEditor...
Изменено: JeyCi - 03.08.2021 09:27:05
чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок - обратитесь к собеседнику на ВЫ - ответ на ваш вопрос получите - а остальное вас не касается (п.п.п. на форумах)
Страницы: 1
Наверх