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

时间:2019-07-02 11:35:03

标签: google-apps-script google-sheets

我有一个脚本,在过去的几个星期中一直运行良好,直到今天早上由于该项目上有太多可安装的触发器而开始失败。

主电子表格上的脚本从模板生成新的电子表格。这些新的电子表格需要一个可安装的onEdit触发器,才能将值编辑回原始(主)电子表格。我有一个可以在生成新的可安装触发器之前使用的函数,但是该函数已添加到主电子表格中,而不是新的电子表格中。显然,问题在于,可以绑定到一个电子表格的可安装触发器的数量受到严格限制,因此我希望有一种方法使它们与新生成的电子表格相关联。

我之前没有提出太多解决方案就问过这个问题,首先是在评论here中,然后是问题here。我还发现四年前问过一个very similar question(对此的回答说没有解决方案,我只想看看四年内是否有任何变化)。

当我在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;
    }       

这是整个脚本:

   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;
            }
          }
        }
      }
    }

谢谢大家的建议。我只是一个暑期实习生,在我离开这里后不让我的工作崩溃:)

0 个答案:

没有答案