使用库为 Google 个工作表创建可安装的触发器

Use a library to create installable triggers for Google sheets

我的客户有大约 150 个 Google 个电子表格,每个 "vendors" 个。电子表格基于模板电子表格,我在其中设置了自定义函数的触发器。但是,当模板被复制并设置为新的供应商电子表格时,触发器将丢失。

我编写了一个与电子表格共享的库来合并代码。我一直在尝试添加一种方法来在电子表格中安装触发器(使用库),一旦它们被打开以更正从模板复制时的缺失,但是,我没有取得任何成功。我相信图书馆可能无法为除自身以外的任何东西创建可安装的触发器。

有了引用为 "SheetNames" 的库,正确链接并正常运行,我在每个电子表格中都有:

function onOpen(){
  SheetNames.manageTimers();
}

在库"SheetNames"中,我有这个代码:

function deleteAllTriggers(workbook) {
  // Loop over all triggers and delete them
  var allTriggers = ScriptApp.getUserTriggers(workbook);
  for (var i = 0; i < allTriggers.length; i++) {
    ScriptApp.deleteTrigger(allTriggers[i]);
  }
}

function manageTimers(){
  // code to install timers if not present
  // and remove them from terminated vendors' sheets named "Vendor 2xxx..."
  var workbook = SpreadsheetApp.getActiveSpreadsheet();
  var workbookName = workbook.getName();

  //Assumes workbookName is formatted as "Vendor XXXX..."
  var vendorNumber = ""+workbookName.substr(7, 256);
  if ((vendorNumber.length >= 4) && (vendorNumber.substr(0,1) == "2")) {
    //this is a 2xxx vendor and all timers need to be deleted
    Logger.log("Deleted all timers for "+workbookName);
    deleteAllTriggers(workbook);
    return;
  }

  var allTriggers = ScriptApp.getUserTriggers(workbook);
  for (var i = 0; i < allTriggers.length; i++) {
    if (allTriggers[i].getHandlerFunction() == "maintenance") {

      //delete old version of trigger if not timeBased
      if (allTriggers[i].getEventType()=="CLOCK") {
        var maintexists=1;
      } else {
        ScriptApp.deleteTrigger(allTriggers[i]);
      }
    }

    if (allTriggers[i].getHandlerFunction() == "incrementDummyValueToForceUpdate") {

     //delete old version of trigger if not timeBased
      if (allTriggers[i].getEventType()=="CLOCK") {
        var counterexists=1;
      } else {
        ScriptApp.deleteTrigger(allTriggers[i]);
      }
    }
  }

  //create triggers if they don't exist
  if (!maintexists) {    
    ScriptApp.newTrigger('maintenance')
      .forSpreadsheet(workbook)
      .timeBased()
      .onMonthDay(27)
      .create();
  }

  if (!counterexists) {    
    ScriptApp.newTrigger('incrementDummyValueToForceUpdate')
      .forSpreadsheet(workbook)
      .timeBased()
      .everyMinutes(5)
      .create();
  }
} 

具体来说,代码在 .timeBased() 上阻塞并出现错误 TypeError: Cannot find function timeBased in object SpreadsheetTriggerBuilder. (line 104, file "Sheets", project

这似乎很合适,因为 .forSpreadsheet() 参数似乎只适用于 onOpenonEditonChange

如果我从

更改引用
var allTriggers = ScriptApp.getUserTriggers(workbook);

var allTriggers = ScriptApp.getProjectTriggers();

并改变这个

ScriptApp.newTrigger('incrementDummyValueToForceUpdate')
  .forSpreadsheet(workbook)
  .timeBased()
  .everyMinutes(5)
  .create();

至此

ScriptApp.newTrigger('incrementDummyValueToForceUpdate')
  .timeBased()
  .everyMinutes(5)
  .create();

然后手动将代码放入每个电子表格中,它工作正常,但这违背了图书馆的目的。如果我将更改后的代码放入库中,它会在库本身中创建触发器,这不是我需要的。

所以,基本上,我正在寻找有关如何使用库创建可安装触发器的解决方案,这样我就不必将所有这些代码复制到数百个电子表格中,也不必手动设置触发器。

您不能使用:.forSpreadsheet(workbook) 创建基于时间的触发器。

必须是:

ScriptApp.newTrigger('incrementDummyValueToForceUpdate')
  .timeBased()
  .everyMinutes(5)
  .create();

我不确定函数 incrementDummyValueToForceUpdate 是否可以访问活动电子表格。在附加组件中它可以,但你没有使用附加组件。

您可以发布一个插件,让客户在每个电子表格中使用该插件。如果您不想这样做并且每个电子表格都有一个绑定项目,则可以通过编程方式更新绑定项目。

就在昨天,新的 Apps 脚本 API 发布了。您将需要更新项目。参见 "Update project content"

https://developers.google.com/apps-script/api/how-tos/manage-projects

If I put the changed code into the library, it creates triggers in the library itself, which isn't what I need.

事实证明该位不正确,通过库添加触发器会在 sheet 本身中创建触发器。示例代码:

   ScriptApp.newTrigger('maintenance')
  .timeBased()
  .onMonthDay(27)
  .create();