首页 文章

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

提问于
浏览
1

我的客户有大约150个Google电子表格,每个电子表格都有一个用于“供应商” . 电子表格基于模板电子表格,其中我设置了自定义函数的触发器 . 但是,将模板复制并设置为新的供应商电子表格时,触发器将丢失 .

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

使用引用为“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();

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

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

2 回答

  • 0

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

    肯定是:

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

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

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

    就在昨天,宣布了新的Apps Script API . 您需要更新项目 . 请参阅“更新项目内容”

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

  • 2

    如果我将更改的代码放入库中,它会在库本身中创建触发器,这不是我需要的 .

    事实证明该位不正确,并且通过库添加触发器会在工作表本身中创建触发器 . 示例代码:

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

相关问题