Создал пункты меню в 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 именно таким хитрым способом
leonrom написал: Узнать бы еще - почему Microsoft сделал обработчик событий для VBA именно таким хитрым способом
CommandBarEvents Интерфейс наверно, захотели привязать это к Visual Studio SDK и дать возможность только разработчикам в VS колдовать с этим... p.s. у меня в Win10 Office2016 работает только так (как во вложении) - только в VBE window видно - пример отсюда, - и при включённых: Центр управления безопасностью - Параметры макросов - Доверять доступ к объектной модели VBA
чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок - обратитесь к собеседнику на ВЫ - ответ на ваш вопрос получите - а остальное вас не касается (п.п.п. на форумах)
чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок - обратитесь к собеседнику на ВЫ - ответ на ваш вопрос получите - а остальное вас не касается (п.п.п. на форумах)