Assuming you wanted to store the relevant captions and function names in Sheet1 columns A & B, respectively, you could simply call .getValues()
and iterate through that data.
/**
* SHEET1 VALUES
* --------------------------------------
* Column A Column B
* Row 1 Class One functionOne
* Row 2 Class Two functionTwo
* Row 3 Class Three functionThree
*/
function onOpen(e) {
// Initialize the menu & submenu
var ui = SpreadsheetApp.getUi();
var menu = ui.createMenu('Menu Name').addItem('First label', 'menuItem1').addSeparator();
var subMenu = ui.createMenu('Submenu Name');
// Get the submenu item data from Sheet1
// Values in column A represent the captions that will appear in the submenu
// Values in column B represent the name of the function to be called
var values = SpreadsheetApp.getActive().getSheetByName('Sheet1').getRange('A:B').getValues();
for (var rowIndex = 0; rowIndex < values.length; ++rowIndex) {
var rowData = values[rowIndex];
var caption = rowData[0]; // Column A value
var functionName = rowData[1]; // Column B value
if (caption != '' && functionName != '') { // Exclude empty strings
subMenu.addItem(caption, functionName);
}
}
// Add the submenu to the menu, and finally to the UI
menu.addSubMenu(subMenu).addToUi();
}
function menuItem1() { Browser.msgBox('menuItem1'); }
function functionOne() { Browser.msgBox('functionOne'); }
function functionTwo() { Browser.msgBox('functionTwo'); }
function functionThree() { Browser.msgBox('functionThree'); }
In the original post, the error was happening because .addSubMenu()
was being called on the value [9p1]
instead of a Menu object. Further, from my understanding of the question, I think a menu item is intended to be created in the loop, not an individual submenu for each class. So those are two problems that needed to be resolved.
I also assume that you don't want to run runBatch1
for every single menu item as that would defeat the purpose of creating different menu items. According to the documentation, the method for adding a menu item expects two strings:
caption
– The label for the menu item.
functionName
– The name of the function to invoke when the user selects the item.
So it follows that you can substitute any string when making your submenu.addItem()
call.
var caption = "Caption";
var functionName = "functionName";
var subMenu = ui.createMenu('Submenu Name');
subMenu.addItem(caption, functionName);
Other Scenarios
Array of Item Objects
Alternatively, you could define an array (or object map) of the various submenu items you want to include, rather than storing them in the spreadsheet. Here, I've used an array of objects to clearly define the caption & functionName values.
function onOpen(e) {
// Initialize the menu & submenu
var ui = SpreadsheetApp.getUi();
var menu = ui.createMenu('Menu Name').addItem('First label', 'menuItem1').addSeparator();
var subMenu = ui.createMenu('Submenu Name');
// Array of items to include in the submenu
var items = [
{ caption: 'Class One', functionName: 'functionOne' },
{ caption: 'Class Two', functionName: 'functionTwo' },
{ caption: 'Class Three', functionName: 'functionThree' }
];
for (var i = 0; i < items.length; ++i) {
var item = items[i];
subMenu.addItem(item.caption, item.functionName);
}
// Add the submenu to the menu, and finally to the UI
menu.addSubMenu(subMenu).addToUi();
}
function menuItem1() { Browser.msgBox('menuItem1'); }
function functionOne() { Browser.msgBox('functionOne'); }
function functionTwo() { Browser.msgBox('functionTwo'); }
function functionThree() { Browser.msgBox('functionThree'); }
Caption String Manipulation
Since the method accepts any string, you can perform any string manipulation that will result in a valid function name. In this example, I'm only storing the captions in an array and I dynamically generate the function names based on the caption values. (You could also pull the caption names from column A and apply the same manipulation.)
function onOpen(e) {
// Initialize the menu & submenu
var ui = SpreadsheetApp.getUi();
var menu = ui.createMenu('Menu Name').addItem('First label', 'menuItem1').addSeparator();
var subMenu = ui.createMenu('Submenu Name');
// Array of captions to include in the submenu.
// Will generate function names from this.
var captions = ['Class One', 'Class Two', 'Class Three'];
for (var i = 0; i < captions.length; ++i) {
var caption = captions[i];
subMenu.addItem(caption, 'function' + caption.split(' ')[1]);
}
// Add the submenu to the menu, and finally to the UI
menu.addSubMenu(subMenu).addToUi();
}
function menuItem1() { Browser.msgBox('menuItem1'); }
function functionOne() { Browser.msgBox('functionOne'); }
function functionTwo() { Browser.msgBox('functionTwo'); }
function functionThree() { Browser.msgBox('functionThree'); }