可安装的触发器因测试加载项而失败 [英] Installable Trigger Failing with Test Add-On

查看:27
本文介绍了可安装的触发器因测试加载项而失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

几天来,我一直在努力解决可安装的触发器问题.我的所有研究表明,附加组件应该允许在电子表格中安装 onEdit() 触发器,但我的尝试不断出错.我已经稍微简化了我的项目代码来举例说明我的问题.

I have been wrestling with an installable trigger issue for a couple of days now. All of my research indicates that an add-on should allow for an installable onEdit() trigger within a spreadsheet, but my attempts keep erroring out. I have simplified my project code a bit to exemplify my issue.

错误信息:

执行失败:测试插件试图执行不允许的操作.

Execution failed: Test add-on attempted to perform an action that is not allowed.

我的代码(列出函数是调用它们的顺序):

My code (listing functions is the order that they are called):

   function onOpen() //creates custom menu for the evaluation tool ***FOR ADMININSTRATORS ONLY***
{ 

  var ui = SpreadsheetApp.getUi();

  if(!PropertiesService.getDocumentProperties().getProperty('initialized'))
  {
    ui.createMenu('Evaluation Menu') // Menu Title
      .addItem('Create Installable OnEdit Trigger', 'createInstallableOnEditTrigger')
    .addToUi();
  }
  else
  {
    ui.createMenu('Evaluation Menu') // Menu Title
      .addSubMenu(ui.createMenu('Manage Observations & Evidence')
           .addSubMenu(ui.createMenu('Create New Observation')
               .addItem('Formal', 'createNewFormalObservation')
               .addItem('Informal', 'createNewInformalObservation')
            )          
      .addToUi();    
  }
}


function createInstallableOnEditTrigger() { // installable trigger to create employee look-up listener when user edits the EIN fields on the Documentation Sheet.
  var ss = SpreadsheetApp.getActive();
  ScriptApp.newTrigger('onEditListener')
      .forSpreadsheet(ss)
      .onOpen()
      .create();

  PropertiesService.getDocumentProperties().setProperty('initialized','true');
}

function onEditListener(event) //this function conitnually listens to all edit, but only engages only certain conditions such as when a timestamp is determined to be needed or the Documentation Sheet needs to be auto-populated
{
  //Determine whether or not the conditions are correct for continuing this function
  var sheetName = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getName(); //determines the name of the currently active sheet

  if (sheetName.indexOf("Evidence") > -1) // if the active sheet is an evidence collection sheet, a timestamp may be needed
  {
    populateEvidenceTimeStamp(event, sheetName);
  }
  else if (sheetName == "Documentation Sheet") //if the active sheet is the "Documentation Sheet" than auto-population and EIN lookups may be needed
  {
    employeeLookup(event, sheetName);
  }
}

我错过了什么?非常感谢任何帮助!!

What am I missing? Any help is greatly appreciated!!

以下代码已根据@Mogsdad 的要求添加.

populateEvidenceTimeStamp() 依赖于 generateTimeStamp(),它也包含在下面:

populateEvidenceTimeStamp() is dependent upon generateTimeStamp() which is also included below:

function populateEvidenceTimeStamp(event, sheetName)
{
  var evidenceColumnName = "Evidence"; 
  var timeStampColumnName = "Timestamp";
  var sheet = event.source.getSheetByName(sheetName);

  var actRng = event.source.getActiveRange();
  var indexOfColumnBeingEdited = actRng.getColumn();
  var indexOfRowBeingEdited = actRng.getRowIndex();
  var columnHeadersArr = sheet.getRange(3, 1, 1, sheet.getLastColumn()).getValues(); // grabs the column headers found in the 3rd row of the evidence sheet

  var timeStampColumnIndex = columnHeadersArr[0].indexOf(timeStampColumnName); //determines the index of the Timestamp column based on its title
  var evidenceColumnIndex = columnHeadersArr[0].indexOf(evidenceColumnName); evidenceColumnIndex = evidenceColumnIndex+1; //determines the index of the evidence column based on its title
  var cell = sheet.getRange(indexOfRowBeingEdited, timeStampColumnIndex + 1); //determines the individual timestap cell that will be updated

  if (timeStampColumnIndex > -1 && indexOfRowBeingEdited > 3 && indexOfColumnBeingEdited == evidenceColumnIndex && cell.getValue() == "") // only create a timestamp if 1) the timeStampColumn exists, 2) you are not actually editing the row containing the column headers and 3) there isn't already a timestamp in the Timestamp column for that row
  {
    cell.setValue(generateTimeStamp());
  }
}

function generateTimeStamp()
{
  var timezone = "GMT-7"; // Arizona's time zone
  var timestamp_format = "MM.dd.yyyy  hh:mm:ss a"; // timestamp format based on the Java SE SimpleDateFormat class. http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html 
  var currTimeStamp = Utilities.formatDate(new Date(), timezone, timestamp_format);  
  return currTimeStamp;  
}

下面是依赖于lookupEIN()的employeeLookup()函数

Below is the employeeLookup() function which is dependent upon lookupEIN()

function employeeLookup(event, sheetName)
{
  if(sheetName == "Documentation Sheet" && !PropertiesService.getDocumentProperties().getProperty('initialized')) // if the activeSheet is "Documentation Sheet" and the sheet has not yet been initialized
  {
    var actRng = event.source.getActiveRange();
    Logger.log("employeeLookup(): actRng: "+actRng.getRow()+" , "+actRng.getColumn());
    if(actRng.getRow() == 4 && actRng.getColumn() == 9 && event.source.getActiveRange().getValue() != "") //if the "Teacher EIN" cell is the active range and it's not empty
    { 
      var ein = actRng.getValue();
      clearDocumentationSheetTeacherProfile(); //first clear the teacher profile information to avoid the possibility of EIN/Teacher Info mismatch if previous search did not yield results
      var teacherDataArr = lookupEIN(ein, "Teachers");
      if(teacherDataArr)
      {
        //write retrieved teacher data to Documentation Spreadsheet
        var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Documentation Sheet");
        sheet.getRange(5, 9, 1, 1).setValue(teacherDataArr[1]); // Teacher First Name
        sheet.getRange(6, 9, 1, 1).setValue(teacherDataArr[2]); // Teacher Last Name
        sheet.getRange(7, 9, 1, 1).setValue(teacherDataArr[3]); // Teacher Email 

        sheet.getRange(11, 9, 1, 1).setValue(teacherDataArr[4]); // School Name
        sheet.getRange(11, 39, 1, 1).setValue(teacherDataArr[5]); // Site Code
        sheet.getRange(10, 30, 1, 1).setValue(calculateSchoolYear()); //School Year
      }
      else
      {
        Logger.log("employeeLookup(): type:Teachers 'died. lookupEIN() did not return a valid array'"); //alert message already sent by lookUpEIN
      }
    }
    else if (actRng.getRow() == 4 && actRng.getColumn() == 30 && actRng.getValue() != "" && !PropertiesService.getDocumentProperties().getProperty('initialized')) //if the "Observer EIN" cell is the active range
    {
      Logger.log("employeeLookup(): 'active range is Observer EIN'");
      var ein = actRng.getValue();
      clearDocumentationSheetObserverProfile(); //first clear the teacher profile information to avoid the possibility of EIN/Observer Info mismatch if previous search did not yield results
      var observerDataArr = lookupEIN(ein, "Observers");
      if(observerDataArr)
      {
        //write retrieved observer data to Documentation Spreadsheet
        var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Documentation Sheet");
        sheet.getRange(5, 30, 1, 1).setValue(observerDataArr[1]); // Observer First Name
        sheet.getRange(6, 30, 1, 1).setValue(observerDataArr[2]); // Observer Last Name
        sheet.getRange(7, 30, 1, 1).setValue(observerDataArr[3]); // Observer Email 
      }
      else
      {
        Logger.log("employeeLookup(): type:Observers 'died. lookupEIN() did not return a valid array'"); //alert message already sent by lookUpEIN
      }
    }
    else
    {
      Logger.log("employeeLookup(): 'active range is not a trigger'");
      //do nothing (not the right cell)
    }
  }
  else
  {
    //Observer log has already been initialized and documentation cannot be altered. notify user
    Logger.log("employeeLookup(): 'log already saved.... alerting user'");
    logAlreadyInitializedDialogue();
    restoreDocumentationSheetData();
  }
}

function lookupEIN(ein, type)
{
  Logger.log ("lookUpEIN(): 'engaged'");
  var ss = SpreadsheetApp.openById(teacherObserverIndex_GID);
  var sheet = ss.getSheetByName(type); //lookup type aligns with the individual sheet names on the teacherObserverIndex_GID document
  var values = sheet.getDataRange().getValues();
  var val = sheet.getDataRange();

  for (var i = 1; i < values.length; i++)
  {
     if(values[i][0] == ein)
    {
      Logger.log ("lookUpEIN(): values[i]: "+values[i]);
      return values[i];
    }
    else
    { 
      Logger.log ("lookUpEIN(): 'no match found'");
    }
  }
  //a match could not be found 
  Logger.log("An EIN match could not be found"); // create a feedback pop-up
  einNotFoundDialogue(type); //alert user that there is a problem with the provided ein
}

推荐答案

将脚本作为测试作为插件运行时,无法创建触发器.

Triggers can't be created when running a script as Test as add-on.

来自 https://developers.google.com/apps-script/附加组件/测试:

在测试附加组件时需要牢记以下几点:

There are a number of things to keep in mind while testing add-ons:

  • 测试时当前不支持可安装触发器.依赖于可安装触发器的功能将不会可测试.

一些可能的解决方法

  • 对于打开和编辑可安装触发器,临时添加简单触发器以调用可安装触发器的功能.这可能仅在 的执行时间小于简单触发器限制时才有效.
  • 从创建模拟相应事件对象的对象的函数调用可安装触发器中的函数
  • 不要使用独立项目,而是使用有界项目.您可以使用 CLASP 或像 Google Apps Script GitHub Assistant Chrome 扩展程序 以便更轻松地复制从独立项目到有界项目的代码.
  • For on open and on edit installable triggers, temporally add simple triggers to call the functions of the installable triggers. This might only work if the execution time of is less than the simple triggers limit.
  • Call the functions from the installable triggers from functions that create object that emulates the corresponding event object
  • Instead of using a stand-alone project use bounded projects. You might use CLASP or an extension like Google Apps Script GitHub Assistant Chrome extension to make it easier to copy the code from the stand-alone project to a bounded project.

相关

这篇关于可安装的触发器因测试加载项而失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆