Страницы: 1
RSS
Макрос создания дополнительного меню для перехода по листам
 
Доброго времени суток, уважаемые форумчане. Натолкнулся на нашем форуме на вопрос: https://www.planetaexcel.ru/forum/index.php?PAGE_NAME=read&FID=1&TID=137602&... и попробовал переделать под свои нужды, а именно создание доп. меню для перехода между листами. Получилось следующее:
Код
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
...
В принципе все работает, но хочется сделать более универсальнее. Ведь если этот код вставить в рабочий файл, где номера листов уже не идут в строгом порядке, придется тщательно проверять соответствие имени и индекса листа. А задумывалось следующее: либо сразу делать соответствие пункта меню и команды на переход, вроде
Код
Cap(i) = Split(Arr_ws)(UBound(Split(Arr_ws)) - i)
Mac(i) = Sheets(Split(Arr_ws)(UBound(Split(Arr_ws)) - i)).Activate
Либо пытаться передать в  переменную (например 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

Строка 39 из #4:
Код
Item.OnAction = "'MyMacro(" & i & ")'"
Владимир
 
ЗдОрово, Sokol92! Спасибо за помощь
Изменено: OlegO - 23.02.2021 15:48:46
 
Успехов!
Владимир
 
OlegO, гляньте, может тоже чем поможет:
Список листов книги - Надстройка добавляет на панель выпадающий список со всеми листами активной книги:
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
Страницы: 1
Наверх