Sub MakeMenu() 'Добавление пунктов контекстного меню
Dim NewMenu As CommandBarControl, Item As CommandBarControl, ws As Worksheet, MenuCount As Long, i As Long, Arr_ws As String
For Each ws In Worksheets
If ws.Visible = True Then Arr_ws = Join(Array(ws.Name, Arr_ws))
Next ws
ReDim Cap(1 To UBound(Split(Arr_ws)))
ReDim Mac(1 To UBound(Split(Arr_ws)))
For i = 1 To UBound(Split(Arr_ws))
Cap(i) = Split(Arr_ws)(UBound(Split(Arr_ws)) - i)
Mac(i) = "Sw_Sh" & i
Next i
On Error Resume Next
Application.CommandBars("Cell").Controls("&Переход на лист").Delete 'Удалить меню, если оно уже существует
On Error GoTo 0
' Добавление меню
MenuCount = Application.CommandBars("Cell").Controls.Count
Set NewMenu = Application.CommandBars("Cell").Controls.Add(Type:=msoControlPopup, Before:=MenuCount, temporary:=True)
NewMenu.Caption = "&Переход на лист"
For i = 1 To UBound(Split(Arr_ws)) 'Добавление пунктов меню
Set Item = NewMenu.Controls.Add(Type:=msocontrolbutton, temporary:=True)
Item.Caption = Cap(i)
Item.OnAction = Mac(i)
Next i
End Sub
Sub DeleteMenu() 'Удаление меню перед закрытием
On Error Resume Next
Application.CommandBars(1).Controls("Переход на лист").Delete
End Sub
ну и соответственно макросы перехода на лист:
Код
Sub Sw_Sh1()
Sheets(1).Activate
End Sub
Sub Sw_Sh2()
Sheets(2).Activate
End Sub
...
В принципе все работает, но хочется сделать более универсальнее. Ведь если этот код вставить в рабочий файл, где номера листов уже не идут в строгом порядке, придется тщательно проверять соответствие имени и индекса листа. А задумывалось следующее: либо сразу делать соответствие пункта меню и команды на переход, вроде
Либо пытаться передать в переменную (например wh) имя выбранного листа и далее в одном универсальном макросе:
Код
Sub Univ()
Sheets(wk).Activate
End Sub
но не смог разобраться в каком месте кода переменой следует присваивать значение . Можно ли сделать так? (или иначе, самое главное результат). P.S. Заранее спасибо всем откликнувшимся
OlegO, Что можно понять из такого названия темы? В чём универсальность? Что должен делать макрос? Предложите новое название, из которого будет понятна ЗАДАЧА - модераторы поменяют.
Мой итоговый вариант, доработанный с учетом дополнения от Sokol92, может пригодится кому:
Код
Sub MakeMenu() '
Dim cmdBar As CommandBar, cmdBar1 As CommandBar, cmdBar2 As CommandBar
For Each cmdBar In Application.CommandBars
If cmdBar.Name = "Cell" Then
If cmdBar1 Is Nothing Then
Set cmdBar1 = cmdBar
MakeMenu_2 cmdBar
Else
Set cmdBar2 = cmdBar
MakeMenu_2 cmdBar: Exit For
End If
End If
Next cmdBar
End Sub
Sub MakeMenu_2(ByVal cmdBar) 'Добавление пунктов контекстного меню
Dim NewMenu As CommandBarControl, Item As CommandBarControl, ws As Worksheet, MenuCount As Long, i As Long, Arr_ws As String, SheetCount As Variant
For Each ws In Worksheets
If ws.Visible = True Then Arr_ws = Join(Array(ws.Name, Arr_ws), ",")
Next ws
SheetCount = Split(Arr_ws, ",")
ReDim Cap(1 To UBound(SheetCount))
ReDim Mac(1 To UBound(SheetCount))
For i = 1 To UBound(SheetCount)
Cap(i) = SheetCount(UBound(SheetCount) - i)
Mac(i) = "Sw_Sh" & Sheets(SheetCount(UBound(SheetCount) - i)).Index
Next i
' Добавление меню
MenuCount = cmdBar.Controls.Count
Set NewMenu = cmdBar.Controls.Add(Type:=msoControlPopup, temporary:=True)
NewMenu.Caption = "&Переход на лист"
For i = 1 To UBound(SheetCount) 'Добавление пунктов меню
Set Item = NewMenu.Controls.Add(Type:=msocontrolbutton, temporary:=True)
Item.Caption = Cap(i)
Item.OnAction = Mac(i)
Next i
End Sub
Sub DeleteMenu() 'Удаление меню перед закрытием
On Error Resume Next
cmdBar1.Controls("&Переход на лист").Delete
cmdBar2.Controls("&М").Delete
End Sub
И все-таки жаль, что не смог разобраться как можно перехватить значение ВЫВБРАННОГО пункта меню для передачи его в макрос. А так пришлось сформировать несколько десятков практически идентичных: Sw_Sh1() , Sw_Sh2(), Sw_Sh3() и т.д. Если кто-нибудь предложит свой вариант, буду только рад
Свойство Action допускает вызов макросов с параметрами, для этого нужно значение свойства заключить в апострофы. В Вашем случае передаем макросу MyMacro номер листа.
Код
Sub MyMacro(ByVal i As Long)
Debug.Print "MyMacro", i
End Sub