Google Apps 脚本:动态创建电子表格菜单项

joc*_*ter 4 google-sheets google-apps-script

我正在尝试使用 Google Apps 脚本在 Google 表格中创建一个动态填充的菜单。

  1. 我有一张表,“班级”,我在上面列出了我教的班级。
  2. 在运行我的脚本时,我让我的脚本读取这些类并将其加载到数组中。
  3. 为了只对原始“类”表中的值进行硬编码,我想为每个类创建一个子菜单项。

该表称为“类”。类表中的值是 8H、9p1、9p2 等。它们位于单元格 A1:A12 中。在调试器中,数组 menuItemArray 正确加载了“类”表中所有预期的类。

我得到的错误是:

类型错误:在对象 9p1 中找不到函数 addSubMenu。(第 13 行,文件“代码”)

这是踏入队伍的时候

menuItemArrayClass =  menuItemArray [menuCount]
Run Code Online (Sandbox Code Playgroud)

对于我做错了什么或有什么更好的方法可以提供任何帮助,我将不胜感激。

这是我的代码:

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();
    }     
}
Run Code Online (Sandbox Code Playgroud)

Tan*_*ike 8

  • 您想创建自定义菜单。
  • 您想通过编辑电子表格来更新自定义函数。
  • 您想对myFunction()自定义菜单中的多个功能使用一个功能名称。
  • 当从自定义菜单运行函数时,您希望将每个值作为参数提供给函数。
  • 示例情况如下。
    • “A”到“I”列中有值。
    • 自定义菜单中有 9 个功能。自定义菜单是在电子表格打开时创建的。函数名称与每个列名称相对应。
    • 当点击“A”列的功能时,“A”列的值被激活。
    • 当“I”列复制到“H”列时,新功能被添加到自定义菜单中。

我理解如上。如果我的理解是正确的,这个答案怎么样?请将此视为几种可能的答案之一。

问题和解决方法:

不幸的是,在现阶段,当一个函数添加到带有addItem方法的自定义菜单中时,该参数无法使用。并且当自定义菜单中的功能之一运行时,无法检索有关运行的功能名称的信息。这样,您的目标就无法直接实现。所以需要使用变通方法。

当我看到你的问题时,为了你的目标,我认为这个线程很有用。在 google.script.run 中,需要能够在脚本编辑器中直接运行该函数,并且该函数包含在this. 但是在自定义菜单中,当函数包含在 中时this,即使函数不能直接在脚本编辑器中运行,也可以运行该函数。当函数仅在 GAS 端运行时,即使无法直接使用脚本编辑器运行该函数,也可以运行该函数。我认为这种情况可以用于解决方法。

修改后的脚本:

通过包含此解决方法来修改您的脚本后,它会变成如下所示。请将其复制并粘贴到电子表格的容器绑定脚本中,该脚本在第一行具有标题(“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!');
}
Run Code Online (Sandbox Code Playgroud)

到:

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.
Run Code Online (Sandbox Code Playgroud)
  • 在您使用这个脚本之前,请先安装 OnChange 事件触发器到onChange(). 这样,当列被删除时,自定义菜单被更新。
  • 的功能function onEdit() {}function onChange() {}用于运行onOpen();

结果:

在此处输入图片说明

笔记:

  • 为了动态创建自定义菜单,该脚本需要在函数运行的初始阶段运行。所以需要把它作为全局 like onOpen();
  • 在此解决方法中,当函数运行时,onOpen每次都会运行。所以当列数很大时,工艺成本会很高。所以请注意这一点。
  • 这是一个简单的示例脚本,用于解释变通方法的一种方法。所以请根据您的情况修改它。

参考: