我正在尝试使用Google Apps脚本在Google表格中创建动态填充的菜单。
该表格被称为“类”'。 类表中的值是8H,9p1,9p2等。 它们位于A1:A12单元格中。 在调试器中,数组menuItemArray正确地加载了来自'类'的所有预期类。片材。
我得到的错误是:
TypeError:在对象9p1中找不到函数addSubMenu。 (第13行, 文件"代码")
这是踏入行
的时候menuItemArrayClass = menuItemArray [menuCount]
如果我做错了什么或者有更好的方法,我会非常感激。
这是我的代码:
function onOpen(e) {
var ui = SpreadsheetApp.getUi();
var menuCount = 0;
ui.createMenu('Manage Timetable')
.addItem('First item', 'menuItem1')
.addSeparator()
var menuItemArray = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Classes').getDataRange().getValues();
for (menuCount=1;menuCount < menuItemArray.length;++menuCount) {
var menuItemArrayClass = []
menuItemArrayClass = menuItemArray [menuCount]
.addSubMenu(ui.createMenu('Manage Classes')
.addItem(menuItemArrayClass [menuCount] + 'Schedule Timetable', 'runBatch1'))
.addToUi();
}
}
答案 0 :(得分:2)
试试这个:
function onOpen(e) {
var ui = SpreadsheetApp.getUi();
var menuCount = 0;
var menu = ui.createMenu('Manage Timetable');
menu.addItem('First item', 'menuItem1')
menu.addSeparator()
var menuItemArray = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Лист2').getDataRange().getValues();
for (menuCount=0;menuCount < menuItemArray.length;menuCount++) {
var menuItemArrayClass = []
menuItemArrayClass = menuItemArray [menuCount];
menu.addSubMenu(ui.createMenu('Manage Classes')
.addItem(menuItemArrayClass + ' Schedule Timetable', 'runBatch1'))
menu.addToUi();
}
}
如果从1开始,你会松开第一行,所以我把它改为0.
此外,您现在需要动态分配脚本,但我不知道它们是如何在工作表中设置的,所以我保留了该部分。
也不确定您是否每次都需要添加“管理课程”菜单,但我保留以防万一。
请尝试使用此功能,因为它看起来更像您想要的内容:
function onOpen(e) {
var ui = SpreadsheetApp.getUi();
var menuCount = 0;
var menu = ui.createMenu('Manage Timetable')
.addItem('First item', 'menuItem1')
.addSeparator();
var subMenu = ui.createMenu('Manage Classes');
var menuItemArray = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Лист2').getDataRange().getValues();
for (menuCount=0;menuCount < menuItemArray.length;menuCount++) {
var menuItemArrayClass = []
menuItemArrayClass = menuItemArray [menuCount];
subMenu.addItem(menuItemArrayClass + ' Schedule Timetable', 'runBatch1');
}
menu.addSubMenu(subMenu).addToUi();
}
答案 1 :(得分:1)
myFunction()
。我理解如上。如果我的理解是正确的,那么这个答案呢?请认为这只是几个可能的答案之一。
不幸的是,在当前阶段,当使用addItem
方法向自定义菜单添加功能时,无法使用该参数。并且,当运行自定义菜单中的功能之一时,无法检索到有关运行的功能名称的信息。这样,您的目标无法直接实现。因此,需要使用替代方法。
当我看到您的问题时,出于您的目标,我认为this thread是有用的。在google.script.run,要求能够直接在脚本编辑器上运行该函数,并且该函数包含在this
中。但是在自定义菜单上,当功能包含在this
中时,即使无法直接在脚本编辑器中运行该功能,也可以运行该功能。当仅在GAS端运行该功能时,即使无法使用脚本编辑器直接运行该功能,也可以运行该功能。我认为这种情况可以用于解决方法。
通过包含此替代方法来修改脚本时,脚本将如下所示。请将其复制并粘贴到Spreadsheet的容器绑定脚本中,该脚本的第一行具有标头(“ Col1”,“ Col2”,“,”),第二行具有相应的值。并且当您运行脚本时,请打开电子表格。这样,添加了自定义菜单。并且当通过复制添加新列时,附加列也将添加到自定义菜单。并且运行自定义菜单上的功能时,将激活与该列对应的值。
function onOpen(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var headers = ss.getRange(1, 1, 1, ss.getLastColumn()).getValues()[0];
var ui = SpreadsheetApp.getUi();
var menu = ui.createMenu('Custom Menu')
.addItem('First item', 'menuItem1')
.addSeparator();
var subMenu = ui.createMenu('Sub-menu');
for (var i = 0; i < headers.length; i++) {
var dynamicMenu = headers[i];
subMenu.addItem(dynamicMenu,'dynamicItem');
}
menu.addSubMenu(subMenu).addToUi();
}
function onEdit(e) {
onOpen(e);
}
function menuItem1() {
SpreadsheetApp.getUi()
.alert('You clicked the first menu item!');
}
function dynamicItem() {
SpreadsheetApp.getUi()
.alert('You clicked the dynamic menu item!');
}
function installFunctions() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var headers = ss.getRange(1, 1, 1, ss.getLastColumn()).getValues()[0];
var ui = SpreadsheetApp.getUi();
var menu = ui.createMenu('Custom Menu')
.addItem('First item', 'menuItem1')
.addSeparator();
var subMenu = ui.createMenu('Sub-menu');
for (var i = 0; i < headers.length; i++) {
var dynamicMenu = headers[i];
this[dynamicMenu] = dynamicItem(i); // Added
subMenu.addItem(dynamicMenu,dynamicMenu); // Modified
}
menu.addSubMenu(subMenu).addToUi();
}
function dynamicItem(i) { // Added
return function() {
var sheet = SpreadsheetApp.getActiveSheet();
sheet.getRange(2, i + 1, sheet.getLastRow() - 1, 1).activate();
}
}
installFunctions(); // Added
function onOpen() {} // Modified: This can be used as the simple trigger.
function onEdit() {} // Modified: This can be used as the simple trigger.
function onChange() {} // Added: Please install OnChange event trigger to this function.
onChange()
的功能上。这样,当删除列时,将更新自定义菜单。function onEdit() {}
和function onChange() {}
的功能用于运行onOpen();
。onOpen();
一样将其放在全局位置。onOpen
。因此,当列数很大时,处理成本将很高。所以请注意这一点。答案 2 :(得分:0)
假设您要将相关的标题和函数名称分别存储在Sheet1的A和B列中,只需调用.getValues()
并遍历该数据即可。
/**
* 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'); }
在原始帖子中,发生错误是因为在值[9p1]
而不是.addSubMenu()
上调用了Menu object。此外,根据我对问题的理解,我认为应该在循环中创建菜单 item ,而不是每个类的单独子菜单。因此,这是两个需要解决的问题。
我还假定您不想为每个菜单项都运行runBatch1
,因为这样做会破坏创建不同菜单项的目的。根据{{3}},添加菜单项的方法需要两个字符串:
caption
–菜单项的标签。functionName
–用户选择项目时要调用的函数的名称。因此,可以在进行submenu.addItem()
调用时替换任何字符串。
var caption = "Caption";
var functionName = "functionName";
var subMenu = ui.createMenu('Submenu Name');
subMenu.addItem(caption, functionName);
或者,您可以定义要包含的各种子菜单项的数组(或对象图),而不是将其存储在电子表格中。在这里,我使用了一个对象数组来清楚地定义标题和functionName值。
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'); }
由于该方法接受任何字符串,因此您可以执行任何将导致有效函数名的字符串操作。在此示例中,我仅将标题存储在数组中,并根据标题值动态生成函数名称。 (您也可以从A列中提取标题名称,并应用相同的操作。)
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'); }