首页 文章

GAS将变量传递给基于时间的触发器

提问于
浏览
2

我有一个带有onEdit触发器的Google电子表格,可以创建第二个基于时间的触发器 .

简单地说:当状态列编辑为“已批准”时,会创建一个触发器,以便在提供的项目完成日期发送反馈电子邮件 .

var oneTimeOnly = ScriptApp.newTrigger("emailFeedback").timeBased().at(endDate).create();

我希望将变量传递给第二个触发器 . 我可以创建Project Property或在电子表格中添加一列 . 但是,在创建触发器时传递变量会更简单 .

当我在newTrigger引号中插入任何其他字符时,这会导致函数的全部内容存储在触发器中(随后失败) .

var oneTimeOnly = ScriptApp.newTrigger(“emailFeedback (regEmail) ”) . timeBased() . at(endDate).create();

.

有没有办法在触发器中存储变量?

5 回答

  • 2

    使用ScriptProperties.setProperty()存储可通过触发器方法访问的序列化参数 .

  • 3

    @ user2166613是对的,但有点短 . 这是怎么做的 .

    我展示了一个使用after()触发器的示例 . 这是一个非常有趣的用例,因为它允许将耗时的任务与例如时间分离 . Web应用程序调用,因此调用立即返回控件,处理在后台完成 .

    在我的示例中,我在一个延迟运行的函数中调整工作表的列宽 .

    // call this function to set a time based trigger and transfer parameters
    function setTimeTrigger_AdaptColumnWidths() {  
      var ssId = SpreadsheetApp.getActiveSpreadsheet().getId();
      var wsId = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getSheetId();
    
      var scriptProperties = PropertiesService.getScriptProperties();
      scriptProperties.setProperty('spreadsheetId', ssId);
      scriptProperties.setProperty('worksheetId', wsId);
    
      // Delay 10 secs, but real execution time may vary up to 15 min!
      ScriptApp.newTrigger('adaptColumnWidths').timeBased().after(10000).create();  
    }
    
    // this function is called by the trigger
    function adaptColumnWidths() {  
      var scriptProperties = PropertiesService.getScriptProperties();
      ssId = scriptProperties.getProperty('spreadsheetId');
      wsId = scriptProperties.getProperty('worksheetId');
    
      // getSheetById() is a custom function – see below – not yet in Spreadsheet Class!
      sheet = getSheetById(SpreadsheetApp.openById(ssId), wsId);  
    
      // now do what we want to do in the timeBased trigger
      for (var i = 1; i <= sheet.getLastColumn(); i++){
        sheet.autoResizeColumn(i);
      }
    }
    
    // -----
    
    // custom function – hopefully this will become a method of Spreadsheet Class any time soon
    function getSheetById(ss, wsId) {
      var sheets = ss.getSheets();
      for (var i=0; i<sheets.length; i++) {
        if (sheets[i].getSheetId() == wsId)  return sheets[i];
      }
    }
    

    请注意,您在此处存储的数据空间为 common to all your function calls . 因此,在短时间内多次呼叫可以覆盖彼此的参数 .

    在我的用例中,这不是问题,因为电子表格和工作表不会改变 . 但是,不要尝试传输可能因呼叫而变化的数据 .

    真正的执行时间可能长达15分钟(无论您要求的确切时间),因此有足够的空间进行多个功能调用以互相干扰!

  • 2

    使用ScriptDB和新的Function(),我能够创建一个创建动态触发器函数的方法 .

    解决方案的要点是存储您要触发的代码是带有您要传递的参数的数据库:

    "myFunction('Hello world')"
    

    然后,当脚本启动时,作为全局变量,您可以从 ScriptDB 附加新创建的函数 . (我在下面的链接中动态完成了这个 . )

    globalFunctions.callThisOne = new Function("e", "myFunction("Hello world"));
    

    最后,在创建触发器时,使用全局可访问函数创建它:

    ScriptApp.newTrigger("globalFunctions.callThisOne").timeBased().everyDay(1).create();
    

    我已经写了一篇关于此的短文并发布了消息来源 . 希望它有用 .

    你可以在这里阅读更多相关信息:http://goo.gl/wbUqH6

    或者在这里查看代码:http://goo.gl/zjUiYe

  • 1

    对不起,没有办法做到这一点 .

  • 0

    据我所知,问题是如何将数据传递给谷歌脚本项目中的时间触发功能 . Eoin描述了一种情况,但你可能面对许多人 . 当脚本处理可能长时间运行的复杂电子表格时的典型情况 . 您可能知道每个脚本有大约6分钟的运行时限制 . 这种情况下你应该破坏你的脚本较小的逻辑分区,并在每个逻辑分区的末尾可以为下一部分创建一个新的触发器 . 好的,但下一部分必须知道当前运行脚本变量的一些数据 . 由于无法通过newTrigger()传递这些数据,因此您可以创建快照并以序列化方式放入脚本属性上下文中 . 一个简单的方法ScriptProperties.setProperty() .

相关问题