Dynamic Menu creation

395 views
Skip to first unread message

Jacob Jan Tuinstra

unread,
Mar 29, 2020, 10:15:41 AM3/29/20
to Google Apps Script Community
Hi Y'all,

Trying to apply the techniques that Bruce posted a while ago and want to dynamically create a menu, with corresponding script names attached to it. This is the post that got me started: menu with callback

const createMenu = (e) => {


 
// get the menu items and script names
 
const itemnames = Settings.menu.item
 
 
// create the menu
 
const ui = SpreadsheetApp.getUi()
 
const menu = ui.createAddonMenu()
 
 
// create Map
 
const menuObj = new Map()
 
 
// create the items based on the data
 
for (let key in itemnames) {
    menu
.addItem(itemnames[key], 'menu.item'+key)
    menuObj
.set('item'+key, dynamicFunction = (key) => () => ui.alert('You clicked: item ' + key))
 
}
 
 
// add the items to the spreadsheet
  menu
.addToUi()
}

Can somebody explain me what I'm doing wrong? This is a scope thingy most probably....

Regards from Holland,
Jacob Jan

Alex

unread,
Apr 9, 2020, 5:06:35 AM4/9/20
to Google Apps Script Community
Hi!

I'm not sure that is working. You have to init 

/**
 * @file Pass ars to the menu item
 * @url
 */


var MENU = [
 
{
    caption
: 'Menu item 1',
    functionName
: 'itemMenu',
 
},
 
{
    caption
: 'Menu item 2',
    functionName
: 'itemMenu',
 
},
 
{
    caption
: 'Menu item 3',
    functionName
: 'itemMenu',
 
},
 
{
    caption
: 'Anoher function',
    functionName
: 'someAnotherFunction'
 
}
];


/**
 *
 */

function onOpen() {
 
var ui = SpreadsheetApp.getUi();


 
var menu = ui.createMenu('Test');


  MENU
.forEach(function(item, i) {
    menu
.addItem(item.caption, item.functionName + i);
 
});


  menu
.addToUi();
}


/**
 *
 * @param {{
 *   item: string,
 *   order: number
 * }} e
 */

function itemMenu(e) {
 
var caption = e.item.caption;
 
var order = e.order;
 
Browser.msgBox(
   
Utilities.formatString('%sth of the menu was clicked: %s', order + 1, caption)
 
);
}


/**
 *
 * @param {{
 *   item: string,
 *   order: number
 * }} e
 */

function someAnotherFunction(e) {
 
var caption = e.item.caption;
 
var order = e.order;
 
SpreadsheetApp.getActive().toast(
   
Utilities.formatString('%sth of the menu was clicked: %s', order + 1, caption)
 
);
}
 
(function(self) {
  MENU
.forEach(function(item, i) {
   
self[item.functionName + i] = function() {
     
return self[item.functionName]({ item: item, order: i });
   
};
 
});
})(this);

You should always have an Immediately invoked function to fill the global space with certain variables. So that the environment always knows about their existence. Therefore it is just a hack. It doesn't matter which runtime you use.

The last iife makes all magic.


Best, Alex.
Reply all
Reply to author
Forward
0 new messages