Create custom menu based on a text list

Tested in Excel 365 (16.0.11601.20184) 64-bit. 

When you have a bunch of macros that you use frequently, a menu containing all of them, structured by functionality, would be a great help.

Here is some code that would read any text file (txt, csv etc) and will build your menu when you open Excel. This code needs to be called either on Workbook_Open or in Auto_Open subs.

Also a piece of code will delete the menu when you close Excel. This one needs to be called in either Workbook_BeforeClose or Auto_Close.

While Auto_Open and Auto_Close can be put anywhere, the other two need to be placed on ThisWorkbook (above Modules, expand Microsoft Excel Objects and double-click ThisWorkbook.

 
 
  1. Private Sub Workbook_BeforeClose(Cancel As Boolean)
  2.     DeleteMenu
  3. End Sub
  4. Private Sub Workbook_Open()
  5.     CreateMenu
  6. End Sub

Main code:

 
 
  1. Option Explicit
  2. Public Const TopLevelMenuName = "MyMacros"
  3. Public Const ConfigComment = "#"
  4. Public Const MenuFile = "MyMenu.csv"
  5. Public Const xlsMenuBar = "Worksheet Menu Bar"
  6. Sub CreateMenu()
  7.     ' inspired from https://sitestory.dk/excel_vba/user-defined-menu.htm
  8.     ' needs reference to Microsoft Scripting Runtime
  9.     Dim cbMainMenu As CommandBar
  10.     Dim TopLevelMenu As CommandBarControl
  11.     Dim SubMenu As CommandBarControl, tempMenu As CommandBarControl
  12.     Dim MySettings As New Dictionary
  13.     Dim dKey, arrTemp, i
  14.    
  15.     Set MySettings = GetMenuSettings
  16.    
  17.     ' Delete the menu if it exists
  18.    On Error Resume Next
  19.     Application.CommandBars(xlsMenuBar).Controls(TopLevelMenuName).Delete
  20.     On Error GoTo 0
  21.      
  22.     'Set a CommandBar variable as a Worksheet menu bar
  23.    Set cbMainMenu = Application.CommandBars(xlsMenuBar)
  24.    
  25.     ' add top level menu
  26.    Set TopLevelMenu = cbMainMenu.Controls.Add(Type:=msoControlPopup)
  27.     TopLevelMenu.Caption = TopLevelMenuName
  28.    
  29.     ' open the csv settings files and build the menu
  30.    For Each dKey In MySettings
  31.         arrTemp = Split(dKey, ",")
  32.         If dKey <> "Submenu,Caption,OnAction,FaceID" Then
  33.             ' check if submenu exists and add it if not
  34.            On Error Resume Next
  35.             tempMenu = Nothing
  36.             Set tempMenu = TopLevelMenu.Controls(arrTemp(0))
  37.             On Error GoTo 0
  38.             If tempMenu Is Nothing Then
  39.                 Set SubMenu = TopLevelMenu.Controls.Add(Type:=msoControlPopup)
  40.                 SubMenu.Caption = arrTemp(0)
  41.                 Set SubMenu = TopLevelMenu.Controls(arrTemp(0))
  42.             End If
  43.             ' add macro
  44.            With SubMenu.Controls.Add(Type:=msoControlButton)
  45.                .Caption = arrTemp(1)
  46.                .OnAction = arrTemp(2)
  47.                .FaceId = arrTemp(3)
  48.             End With
  49.             Set tempMenu = Nothing
  50.         End If
  51.    
  52.     Next
  53.    
  54.     Set TopLevelMenu = Nothing
  55.     Set SubMenu = Nothing
  56.     Set cbMainMenu = Nothing
  57.     Set MySettings = Nothing
  58.     Set tempMenu = Nothing
  59.    
  60. End Sub
  61. Sub DeleteMenu()
  62.     'Deletes the user defined menu
  63. '    Application.CommandBars("Worksheet Menu Bar").Reset
  64.    On Error Resume Next
  65.     Application.CommandBars(xlsMenuBar).Controls(TopLevelMenuName).Delete
  66. End Sub
  67. Function GetMenuSettings() As Dictionary
  68.     ' needs reference to Microsoft Scripting Runtime
  69.    Dim f, MyDoc
  70.     Dim strFile
  71.     Dim dSettings As New Dictionary
  72.    
  73.     f = FreeFile
  74.     strFile = ""
  75.     MyDoc = Environ("USERPROFILE") & "\Documents\"
  76.     Open MyDoc & MenuFile For Input As #f
  77.     ' parse the file
  78.    Do Until EOF(f)
  79.         Line Input #f, strFile
  80.         If Left(strFile, 1) <> ConfigComment Then
  81.             ' add to dictionary
  82.            If Not dSettings.Exists(strFile) Then _
  83.                 dSettings.Add Trim(strFile), Trim(strFile)
  84.         End If
  85.     Loop
  86.    
  87.     Close #f
  88.    
  89.     Set GetMenuSettings = dSettings
  90.     ' discard the dictionary
  91.    Set dSettings = Nothing
  92.    
  93. End Function

Settings file example:

 
 
  1. Submenu,Caption,OnAction,FaceID
  2. # This is a comment
  3. Main subs,Stats,not_yet,0001
  4. Grooming,Unhide All Cols And Rows,UnhideAllColsAndRows,0164
  5. Grooming,Extract URL From Shape,ExtractURLFromShape,0098
  6. Grooming,Extract URL From Text,ExtractURLFromText,0099
  7. Grooming,Create Summary sheet,CreateSheetNameLinks,0247
  8. Tools,Excel Functionalities ON,ExcelFunctionalitiesON,0156
  9. Tools,List all comments,ListComments,0170
  10. Tools,List files or folders,ListFilesOrFolders,0085
  11. Tools,List File properties (no subfolders),ListFileProperties,0188
  12. Tools,Merge files,MergeExcelTextFiles,1642
  13. Tools,Copy Files,CopyFiles,0053