Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/google-apps-script/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/google-sheets/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Google apps script 在单独的电子表格中自动生成可安装的触发器_Google Apps Script_Google Sheets - Fatal编程技术网

Google apps script 在单独的电子表格中自动生成可安装的触发器

Google apps script 在单独的电子表格中自动生成可安装的触发器,google-apps-script,google-sheets,Google Apps Script,Google Sheets,我有一个脚本,在过去的几周里一直工作得很好,直到今天早上,由于项目上有太多可安装的触发器,它开始失败 主电子表格上的脚本根据模板生成新的电子表格。这些新的电子表格需要一个可安装的OneEdit触发器来编辑原始(主)电子表格上的值。我有一个函数,用于生成一个新的可安装触发器,但是这是添加到主电子表格中的,而不是新的。问题很明显是,对于可以绑定到一个电子表格的可安装触发器的数量有一个硬限制,因此我想用一种方法将它们与新生成的电子表格关联起来 我以前问过这个问题,没有太大的决心,先是在评论中,然后是在

我有一个脚本,在过去的几周里一直工作得很好,直到今天早上,由于项目上有太多可安装的触发器,它开始失败

主电子表格上的脚本根据模板生成新的电子表格。这些新的电子表格需要一个可安装的OneEdit触发器来编辑原始(主)电子表格上的值。我有一个函数,用于生成一个新的可安装触发器,但是这是添加到主电子表格中的,而不是新的。问题很明显是,对于可以绑定到一个电子表格的可安装触发器的数量有一个硬限制,因此我想用一种方法将它们与新生成的电子表格关联起来

我以前问过这个问题,没有太大的决心,先是在评论中,然后是在一个问题中。四年前我还发现了一个问题(这个问题的答案是没有解决方案,我只是想看看四年后有没有什么变化)

当我尝试在createInstallableTrigger函数中使用新电子表格的ID时,它仍然在主电子表格中生成触发器

我需要知道我所要求的是否可能,但如果不可能,我需要一个新的解决方案来解决这个问题。我在下面展示的代码确实有效,但只在达到触发器的限制之前有效

这些是相关的功能:

 function createInstallableTrigger(funcName,ssId) {
      if(!isTrigger()) {
        ScriptApp.newTrigger(funcName).forSpreadsheet(ssId).onEdit().create();
      }
    }

    function isTrigger(funcName){
      var r=false;
      if(funcName){
        var allTriggers=ScriptApp.getProjectTriggers();
        for(var i=0;i<allTriggers.length;i++){
          if(funcName==allTriggers[i].getHandlerFunction()){
            r=true;
            break;
          }
        }
      }
      return r;
    }       
函数createInstallableTrigger(funcName,ssId){
如果(!isTrigger()){
ScriptApp.newTrigger(funcName).forSpreadsheet(ssId).OneEdit().create();
}
}
函数isTrigger(funcName){
var r=假;
如果(名称){
var allTriggers=ScriptApp.getProjectTriggers();

对于(var i=0;i您拥有哪种帐户?您可以检查不同帐户的当前配额,因此您可能有兴趣升级它。所有选项都有20/用户/脚本触发器限制。这是Google想要的限制,无法绕过。我理解。我想找到一种在新的排列上生成触发器的方法工作表(如果是这样的话,我会将它们触发的函数放在模板上)。遗憾的是,只有用户操作才能激活触发器,这是从脚本执行开始的。你拥有什么样的帐户?你可以检查不同帐户的当前配额,因此你可能有兴趣升级它。所有选项都有20个/用户/脚本触发器限制。这是谷歌想要的限制,不能绕过。我明白。我会的ike希望找到一种在新的电子表格上生成触发器的方法(如果是这样的话,我会将触发器触发的函数放在模板上)。遗憾的是,只有用户操作可以激活触发器,这是从脚本执行开始的。
   function main(e) {
      var ss = SpreadsheetApp.getActiveSpreadsheet();
      var sheet = ss.getActiveSheet();
      var range = e.range;
      var newId;
      var newName;
      var hyperlinkString;
      var isJob;
      var i;
      if(sheet.getRange('L1').getValue() == 10) return;
      //Check if edit occurred in relevant range
      if((range.getColumn() !== 1) && (range.getColumn() !== 2)) return;
      if((range.getRow() == 1) || (range.getRow() == 2)) return;

      //Check if both columns were filled after edit
      if((range.getColumn() == 1) && (range.offset(0,1).isBlank() == true)) return;
      if((range.getColumn() == 2) && (range.offset(0,-1).isBlank() == true)) return;

      //Get new document name from concatenate formula in column H
      if(range.getColumn() == 1) newName = range.offset(0,7).getValue();
      if(range.getColumn() == 2) newName = range.offset(0,6).getValue();

      //Check whether the edits occurred on the jobs list or deliveries list (indicated by '4' or '5' in L1)
      //Calls function to create new job sheet or delivery sheet from template, gets ID of new spreadsheet
      if(((range.getColumn() == 1) && (range.offset(0,3).isBlank() == true)) || ((range.getColumn() == 2) && (range.offset(0,2).isBlank() == true))) { 
        if(sheet.getRange('L1').getValue() == 4) {
          if(range.getColumn() == 1) range.offset(0,3).setValue("Please wait");
          if(range.getColumn() == 2) range.offset(0,2).setValue("Please wait");
          newId = newJob();
          isJob = 1;
        }
        if(sheet.getRange('L1').getValue() == 5) {
          if(range.getColumn() == 1) range.offset(0,3).setValue("Please wait");
          if(range.getColumn() == 2) range.offset(0,2).setValue("Please wait");
          newId = newdelivery();
          isJob = 0;
        }
      }
      //Updates hyperlink if sheet already exists
      else {
        if(range.getColumn() == 1) {
          hyperlinkString = range.offset(0,3).getFormula();
          newId = hyperlinkString.substring(77,121);
        }
        if(range.getColumn() == 2) {
          hyperlinkString = range.offset(0,2).getFormula();
          newId = hyperlinkString.substring(77,121);
        }
        return;
      }

      //Set the name of the new spreadsheet
      SpreadsheetApp.openById(newId).rename(newName);

      //Enter name and date information onto new spreadsheet
      if((sheet.getRange('L1').getValue() == 4) || (sheet.getRange('L1').getValue() == 0) ||  (sheet.getRange('L1').getValue() == 1)) isJob = 1;
      else isJob = 0;
      //If it's on a job, update all sheets on itemization spreadsheet (rooftop/electrical pick/return)
      if(isJob == 1) {
        //If name is entered, update name first then date
        if(range.getColumn() == 1) {
          for(i=0;i<4;i++) {
            SpreadsheetApp.openById(newId).getSheets()[i].getRange('B1').setValue(range.getValue());
            SpreadsheetApp.openById(newId).getSheets()[i].getRange('B2').setValue(range.offset(0,1).getValue());
            }
        }
        //If date is entered, update date first then name
        if(range.getColumn() == 2) {
          for(i=0;i<4;i++) {
            SpreadsheetApp.openById(newId).getSheets()[i].getRange('B2').setValue(range.getValue());
            SpreadsheetApp.openById(newId).getSheets()[i].getRange('B1').setValue(range.offset(0,-1).getValue());
            }
        }

      }
      //If it's on an incoming delivery, just update the main (only) sheet
      if(isJob == 0) {
        //If name is entered, update name first then date
        if(range.getColumn() == 1) {
            SpreadsheetApp.openById(newId).getSheets()[0].getRange('B1').setValue(range.getValue());
            SpreadsheetApp.openById(newId).getSheets()[0].getRange('B2').setValue(range.offset(0,1).getValue());   
        }
        //If date is entered, update date first then name
        if(range.getColumn() == 2) {
            SpreadsheetApp.openById(newId).getSheets()[0].getRange('B2').setValue(range.getValue());
            SpreadsheetApp.openById(newId).getSheets()[0].getRange('B1').setValue(range.offset(0,-1).getValue());
        }
      }


      //Creates hyperlink to new spreadsheet
      if (range.getColumn() == 1) range.offset(0,3).setFormula("=HYPERLINK(\"" + SpreadsheetApp.openById(newId).getUrl() +"\",\"Click here for itemization\")");
      if (range.getColumn() == 2) range.offset(0,2).setFormula("=HYPERLINK(\"" + SpreadsheetApp.openById(newId).getUrl() +"\",\"Click here for itemization\")");

      //Sort list descending from most recent date
      sheet.getRange("A3:D1000").sort({column: 2, ascending: false});
    }

    function newJob() {
      //Open template
      var jobTemplateSS = SpreadsheetApp.openById("ID Redacted");
      //Create new spreadsheet from copy of template spreadsheet
      var newSS = jobTemplateSS.copy("Untitled Job");
      //Get folder
      var jobFolder = DriveApp.getFolderById("ID Redacted");
      //Get ID of new file
      var newSSFile = DriveApp.getFileById(newSS.getId());
      //Copy file to the correct directory and delete the instance created in root
      jobFolder.addFile(newSSFile);
      DriveApp.getRootFolder().removeFile(newSSFile);
      //Automatically generate an installable trigger on new SS that detects edits
      createInstallableTrigger('IncrementDecrement',newSS.getId());
      //Pass ID of new spreadsheet back to calling function
      return(newSS.getId());
    } 

    function newdelivery() {
      //Open template
      var deliveryTemplateSS = SpreadsheetApp.openById("ID Redacted");

      //Create new spreadsheet from copy of template spreadsheet
      var newSS = deliveryTemplateSS.copy("Untitled Delivery");

      //Get folder
      var deliveryFolder = DriveApp.getFolderById("ID Redacted");

      //Get ID of new file
      var newSSFile = DriveApp.getFileById(newSS.getId());

      //Copy file to the correct directory and delete the instance created in root
      deliveryFolder.addFile(newSSFile);
      DriveApp.getRootFolder().removeFile(newSSFile);
      createInstallableTrigger('IncrementDecrement',newSS.getId());

      //Pass ID of new spreadsheet back to calling function
      return(newSS.getId());
    }

    function createInstallableTrigger(funcName,ssId) {
      if(!isTrigger()) {
        ScriptApp.newTrigger(funcName).forSpreadsheet(ssId).onEdit().create();
      }
    }

    function isTrigger(funcName){
      var r=false;
      if(funcName){
        var allTriggers=ScriptApp.getProjectTriggers();
        for(var i=0;i<allTriggers.length;i++){
          if(funcName==allTriggers[i].getHandlerFunction()){
            r=true;
            break;
          }
        }
      }
      return r;
    }

    function  IncrementDecrement(e) {
      var ss = SpreadsheetApp.getActiveSpreadsheet();
      var sheet = ss.getActiveSheet();
      var range = e.range;

      //Check if edit occurred in valid range, and whether the edit occurred on a job or delivery sheet (indicated by a 0,1,or 2 in L1)
      if ((range.getColumn() !== 1) && (range.getColumn() !== 3) && (range.getColumn() !== 4) && (range.getColumn() !== 5) && (range.getColumn() !== 6)) return;
      if(range.getRow() < 4) return;
      if ((sheet.getRange('L1').getValue() !== 0) && (sheet.getRange('L1').getValue() !== 1) && (sheet.getRange('L1').getValue() !==2)) return;

      //Wait to declare all variables until checks occur to maximize efficiency
      var masterSS = SpreadsheetApp.openById("ID Redacted");
      var invsheet = masterSS.getSheetByName("Inventory");
      var q;
      var deltaQ;
      var sku;
      var nextCell;
      var currentCell;
      var cellLink;
      var total;
      var desc;
      var i;

      //Set current cell to work on as the edited cell
      currentCell = range;

      //If edit occurred in first column (SKU) fetch description & value from inventory
      if(range.getColumn() == 1) {
        //Save SKU
        sku = currentCell.getValue();

        //Save current cell
        cellLink = currentCell;

        //Scan through inventory sheet and find matching SKU line, fetch info
        currentCell = invsheet.getRange('A3');
        while (currentCell.isBlank()==false) {
          if(currentCell.getValue() == sku) {
            desc = currentCell.offset(0,1).getValue();
            q = currentCell.offset(0,2).getValue();
            currentCell = cellLink;
            break;
          }
          currentCell = currentCell.offset(1,0);
        }
        //Return to saved cell
        currentCell = cellLink;

        //Enter description and value on itemization sheet
        currentCell.offset(0,1).setValue(desc);
        currentCell.offset(0,3).setValue(q);
      }

      //If edit occurred in third column (quantity)
      if(range.getColumn() == 3) {
        //Save quantity and SKU
        q = currentCell.getValue();
        sku = currentCell.offset(0,-2).getValue();

        //Saving prior quantity value. If no value, set to 0.
        currentCell = currentCell.offset(0,8);
        if (currentCell.isBlank() == true) currentCell.setValue(0);

        //Find and save the change in quantity by subtracting new quantity by prior quantity
        currentCell = currentCell.offset(0,1);
        currentCell.setValue(q - currentCell.offset(0,-1).getValue());
        deltaQ = currentCell.getValue();

        //Save current cell
        cellLink = currentCell;

        //Search through inventory sheet and find matching SKU line
        currentCell = invsheet.getRange('A3');
        while (currentCell.isBlank()==false) {
          if(currentCell.getValue() == sku) {
            //If it's a pick ticket, subtract the quantity used from inventory quantity
            if (sheet.getRange('L1').getValue() == 0) {
              currentCell.offset(0,3).setValue(currentCell.offset(0,3).getValue() - deltaQ);
              currentCell.offset(0,4).setValue(currentCell.offset(0,4).getValue() - deltaQ);

              //Update total price on job list
              for(i=3; i<1000; i++) {
                if(masterSS.getSheetByName("Job List").getRange(i,1).getValue() == sheet.getRange(1,2).getValue()) {
                  masterSS.getSheetByName("Job List").getRange(i,1).offset(0,2).setValue(sheet.getRange(1,15).getValue());
                  break;
                }
              }
            }
            //If it's a return ticket or inbound delivery, add the quantity returned/received to the inventory quantity 
            if ((sheet.getRange('L1').getValue() == 1) || (sheet.getRange('L1').getValue() == 2)) {
              Logger.log(q);
              Logger.log(currentCell.offset(0,3).getValue());
              Logger.log(deltaQ);
              Logger.log(currentCell.offset(0,3).getValue() + deltaQ);
              currentCell.offset(0,3).setValue(+(currentCell.offset(0,3).getValue()) + +deltaQ);
              currentCell.offset(0,4).setValue(+(currentCell.offset(0,4).getValue()) + +deltaQ);

              //If it's a return ticket, update total price on job list
              if(sheet.getRange('L1').getValue() == 1) {
                for(i=3; i<1000; i++) {
                  if(masterSS.getSheetByName("Job List").getRange(i,1).getValue() == sheet.getRange(1,2).getValue()) {
                    masterSS.getSheetByName("Job List").getRange(i,1).offset(0,2).setValue(sheet.getRange(1,15).getValue());
                    break;
                  }
                }
              }
              //If it's an inbound delivery, update total price on delivery list.
              if(sheet.getRange('L1').getValue() == 2){ 
                for(i=3; i<1000; i++) {
                  if(masterSS.getSheetByName("Delivery List").getRange(i,1).getValue() == sheet.getRange(1,2).getValue()) {
                    masterSS.getSheetByName("Delivery List").getRange(i,1).offset(0,2).setValue(sheet.getRange(4,7).getValue());
                    break;
                  }
                }
              }
            }
          }
          //Increment for the 'while loop' that searches for SKU in inventory
          nextCell = currentCell.offset(1,0);
          currentCell = nextCell;
        }

        //Return to saved cell
        currentCell = cellLink;
        //Change value of 'prior quantity' to new quantity in case of further changes
        currentCell = currentCell.offset(0,-1);
        currentCell.setValue(q);

        //Return to orginally edited cell
        currentCell = currentCell.offset(0,-8);
      }

      //If edit occurred in fourth, fifth, sixth columns (value, ext. value, total cost)
      if((range.getColumn() == 4) || (range.getColumn() == 5) || (range.getColumn() == 6)) {
        //If on job sheet, update total price on job list
        if ((sheet.getRange('L1').getValue() == 0) || (sheet.getRange('L1').getValue()== 1)) {
            for(i=3; i<1000; i++) {
              if(masterSS.getSheetByName("Job List").getRange(i,1).getValue() == sheet.getRange(1,2).getValue()) {
                masterSS.getSheetByName("Job List").getRange(i,1).offset(0,2).setValue(sheet.getRange(4,6).getValue());
                break;
              }
            }
          }
        //If on delivery sheet, udate total price on delivery list
        if (sheet.getRange('L1').getValue() == 2) {
          for(i=3; i<1000; i++) {
            if(masterSS.getSheetByName("Delivery List").getRange(i,1).getValue() == sheet.getRange(1,2).getValue()) {
              masterSS.getSheetByName("Delivery List").getRange(i,1).offset(0,2).setValue(sheet.getRange(4,7).getValue())
              break;
            }
          }
        }
      }
    }