Javascript 动态创建函数并将其传递到Google文档产品(文档、表单等)的自定义菜单中

Javascript 动态创建函数并将其传递到Google文档产品(文档、表单等)的自定义菜单中,javascript,google-apps-script,Javascript,Google Apps Script,我想在我的Google工作表中创建一个自定义菜单,其中包含工作表中所有患者账号的列表。为了测试这是否可行,我创建了一个对象并在该对象中存储了一个基本函数,只是一个带有帐户名的警报,每个函数都被分配了一个帐户号本身的键 我有一个帐号数组,我循环遍历该数组,在对象中为每个帐号创建一个键,并在每个键中存储一个基本函数。obj[acctNum]=函数(){SpreadsheetApp.getUi().alert(acctNum)}。现在我有了一个用于每个帐号的函数,我想动态地将该帐号和函数传递到我的Go

我想在我的Google工作表中创建一个自定义菜单,其中包含工作表中所有患者账号的列表。为了测试这是否可行,我创建了一个对象并在该对象中存储了一个基本函数,只是一个带有帐户名的警报,每个函数都被分配了一个帐户号本身的键

我有一个帐号数组,我循环遍历该数组,在对象中为每个帐号创建一个键,并在每个键中存储一个基本函数。obj[acctNum]=函数(){SpreadsheetApp.getUi().alert(acctNum)}。现在我有了一个用于每个帐号的函数,我想动态地将该帐号和函数传递到我的Google工作表中自定义菜单的子菜单中

除了调用函数外,我还记下了所有内容。我可以动态创建菜单和子菜单,以包含电子表格上的每个帐号。我用函数创建了对象。我甚至可以通过键入
obj[acctNum]()来显式地调用函数本身。

当我将函数名作为字符串传递到.addItem(string,string)方法中时,我传递的正是它需要的方式。您将在下面的代码中看到

我的假设是,我不了解.getUi().createMenu()方法如何调用函数和/或“服务器端”概念。我是一个自学成才的程序员,所以我对代码编译以及所有这些工作几乎一无所知。我在下面提供了与此问题相关的所有代码。不幸的是,我无法共享我的文件,因为它有HIPPA保护的信息。如果归结起来,我可以创建一个带有假帐号的虚拟文件来演示问题/过程

我的问题是:如何动态创建函数并将其传递到Google自定义菜单中,从而能够调用这些动态创建的函数

这部分代码循环通过我创建的两个单独的对象,它们有一个键(AcctNums),这个键是一个数组,用于计算帐号列表。我的工作表上有已结清账户和未结清账户

var functions = {};
openFiles.AcctNums.forEach(function (accNum) {
  functions[accNum] = function () {
    SpreadsheetApp.getUi().alert(accNum); 
  }
});
closedFiles.AcctNums.forEach(function (accNum) {
  functions[accNum] = function () {
    SpreadsheetApp.getUi().alert(accNum); 
  }
});
下面是我创建自定义菜单的代码,在上面相同的两个对象中循环,我为每个帐号创建一个项目,并根据对象中的键名传递函数名(函数[accNum])。 所有这些代码都编译正确,我在工作表上得到了一个自定义菜单,其中列出了选项,所有帐号都作为项目填充

function onOpen(e) {
  var ui = SpreadsheetApp.getUi()
  var parentMenu = ui.createMenu("Claim Path Tools")
  var oACF = ui.createMenu("Open a closed file");
  openFiles.AcctNums.forEach(function (accNum) {
    oACF.addItem(accNum,"functions[\"" + accNum + "\"]");
  })
  var cAOF = ui.createMenu("Close an open file");
  closedFiles.AcctNums.forEach(function (accNum) {
    cAOF.addItem(accNum,"functions[\"" + accNum + "\"]");
  })
  parentMenu.addSubMenu(oACF).addSubMenu(cAOF).addToUi()
}
预期结果:每当我单击自定义菜单中的一个项目时,就会收到一个带有相对帐号的警报

实际结果:我得到一个错误,说:

找不到脚本函数:函数[“COOC2018-71”]有关详细信息,请参阅


注:“COOC2018-71”是页面上众多账号之一。此外,如果我在代码
functions[“COOC2018-71”]()
中的任意位置键入,它会正确调用该函数,并向我发出带有帐号的警报。这也是我期望菜单也能做到的,但当我从菜单调用它时,它找不到函数。

我找到了!您可以使用'this'关键字向服务器端添加函数(我不确定我说的是否正确)这是用于访问所有函数的对象的关键字。因为它是一个对象,所以您还可以动态地向它添加函数!因此,我遍历了我所有的账号,创建了一个以每个账号命名的函数,如下所示:

openFiles.AcctNums.forEach(function (accNum) {
  this[accNum] = function () {
    SpreadsheetApp.getUi().alert(accNum); 
  }
});

我在全局范围内完成了这项工作,因此服务器端实例现在为每个帐号都包含了一个新的密钥,该帐号是每次调用代码时都将重新运行的函数。这是完整的解决方案。我在菜单中循环并执行了一个.addItem(accNum,accNum),它能够调用存储在this属性中的函数,甚至不需要在字符串前面加上“this”。成功

我想得越多,现在我猜这与编译代码后,函数对象本身不会持久化这一事实有关。我猜这就是为什么我可以在编译时调用它,但在代码编译完成后不能调用它。它没有存储在内存或类似的东西中。我想知道您是否可以将它们写入项目中的另一个文件中。我不知道这是否可以做到,我从来没有认真学习过,所以这可能是一场白费力气的追逐。这是一个非常有趣的方法。我喜欢它,但据我所知,没有办法将代码动态写入DE本身的文件中。我也考虑过,只是不在不同的文件中。就像我可以告诉代码动态编写新代码一样。这里还有其他志愿者知道的比我多得多,所以他们可能会留下评论让我知道这是一个完全荒谬的想法。我没有点击你提供的链接,但我应该点击。我从未调查过汽油的API。我现在要回顾一下,因为我看到它确实提到了创建和修改应用程序脚本项目。从根本上说,这就是我需要做的。让我们看看我能不能做到!我会更新你:)。