google-apps-script - Google Apps 脚本 : Dynamically creating spreadsheet menu items

标签 google-apps-script google-sheets

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

  • 我有一张“类(class)”表,其中列出了我教的类(class)。
  • 在运行我的脚本时,我让我的脚本读取这些类并将其加载到一个数组中。
  • 为了仅对原始“类”表中的值进行硬编码,我想为这些类中的每一个创建一个子菜单项。

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

    我得到的错误是:

    TypeError: Cannot find function addSubMenu in object 9p1. (line 13, file "Code")



    这是进入队列的时候
    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();
        }     
    }
    

    最佳答案

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

  • 我理解如上。如果我的理解是正确的,这个答案怎么样?请认为这只是几个可能的答案之一。

    问题和解决方法:

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

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

    修改后的脚本:

    通过包含此解决方法修改您的脚本时,它变为如下。请将其复制并粘贴到电子表格的容器绑定(bind)脚本中,其中第一行的标题(“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 事件触发器安装到 onChange() 的函数中。 .这样,当列被删除时,自定义菜单被更新。
  • function onEdit() {}的功能和 function onChange() {}用于运行 onOpen(); .

  • 结果:

    enter image description here

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

  • 引用:
  • Custom Menus
  • Different output in 3 anonymous function in GAS
  • 我认为这个线程对于思考 OP 的目标很有用。
  • 关于google-apps-script - Google Apps 脚本 : Dynamically creating spreadsheet menu items,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31539911/

    相关文章:

    javascript - 如何在 Google 应用程序脚本中引用数组中的元素

    javascript - 在谷歌表格中,您可以将字符串拆分为子字符串,对子字符串执行计算并将结果连接到不同的单元格中吗

    google-apps-script - 如何只删除部分工作表?

    google-apps-script - 接受来自用户的多个输入并添加到新行中的某些单元格

    javascript - 为什么 ScriptDb 查询结果对象不同

    javascript - 单元格最后修改日期的函数

    javascript - Session.getActiveUser().getEmail() 不返回任何值

    javascript - 将包含不同 PDF 的电子邮件发送到不同的电子邮件附件

    javascript - 单个 onEdit 函数有效 - 多个相同的函数不起作用

    javascript - 这个 Google 脚本有什么问题?