Run onEdit script on a protected sheet as an editor, not an owner error TypeError: Cannot read property 'activeSheet' of undefined

Run onEdit script on a protected sheet as an editor, not an owner error TypeError: Cannot read property 'activeSheet' of undefined

我有一个复杂的任务列表sheet,它跟踪已完成的任务。由于这些设置,我需要保护一些公式和范围,以避免 sheet 的用户意外删除它们。问题是某些脚本需要 运行 在 sheet 的受保护部分。在所有者帐户下一切正常。当其他用户使用 sheet 时,他们会收到受保护范围的脚本错误。在网上搜索后,我设置了以下内容:

function doGet(e) {
  this[e.parameter.run](e.parameter.sheetName || null);
  return ContentService.createTextOutput();
}

function atEdit() {
  const activeSheet = SpreadsheetApp.getActiveSheet();
  const url = ScriptApp.getService().getUrl();
  UrlFetchApp.fetch(url + "?run=script_atEdit&sheetName=" + activeSheet.getSheetName(), {headers: {authorization: "Bearer " + ScriptApp.getOAuthToken()}});

// DriveApp.getFiles()  // This is used for automatically detecting the scope of "https://www.googleapis.com/auth/drive.readonly". This scope is used for the access token.
}


function readdTask() {
  const activeSheet = SpreadsheetApp.getActiveSheet();
  const url = ScriptApp.getService().getUrl();
  UrlFetchApp.fetch(url + "?run=script_readdTask&sheetName=" + activeSheet.getSheetName(), {headers: {authorization: "Bearer " + ScriptApp.getOAuthToken()}});

// DriveApp.getFiles()  // This is used for automatically detecting the scope of "https://www.googleapis.com/auth/drive.readonly". This scope is used for the access token.
}

基本上,在脚本作为 Web 应用程序发布后,即使其他用户 运行 它来自共享 sheet,它也会在所有者帐户下 运行。

但是我在 onEdit 脚本中遇到以下错误
(请注意,由于 onEdit 无法访问 Auth 调用,onEdit 已重命名为 atEdit)。

TypeError: 无法读取未定义的 属性 'activeSheet' 在 script_atEdit(sysW.1:57:34) 在 doGet(sysW.1:2:24)

这是我的 atEdit 脚本:

function script_atEdit(e) {
  
  var ss              = SpreadsheetApp.getActiveSpreadsheet();                                // → gets the spreadsheet we will use to get individual sheets from
  var activeSheet     = e.source.getActiveSheet();                                            // → gets the information and the active sheet  
  var globalsSheet    = ss.getSheetByName("Admin");                                           // → gets the sheet where we store our global values, GAS handles globals a bit differently therfore declaring a dynamic global is inconvenient
  
    if (activeSheet.getName() == 'Tasks') {                                                   // → specifies on what sheet within the worksheet the action below will happen
        var aCell = e.source.getActiveCell(), col = aCell.getColumn();                        // → gets the active cell and column the user clicks on and puts the info into aCell variable
                                                                                            
        if (col == 2) {                                                                    
            var dateCell = aCell.offset(0,1);                                                 // → offset, specifies what row and colum hold / will hold the date (- is up, + is down) and number of columns away (- is left, + is right)
            var aRow     = aCell.getRow();                                                 
                                                                                            
            if (aCell.getValue() === true) {                                               
                var newDate   = new Date();                                                   // → gets the current timestamp; the current date and the current time the user checked the cell
                var taskID    = activeSheet.getRange(aRow,7).getValue();
                var taskDate  = activeSheet.getRange(aRow,5).getValue();
                                globalsSheet.getRange(1, 2).setValue(taskID)                  // → sets the global value in the Admin sheet so that it becomes accessible to other functions, IE. other functions copy the value from Admin sheet
                                globalsSheet.getRange(2, 2).setValue(taskDate)
                var everyNth  = activeSheet.getRange(aRow,8).getValue();
                                globalsSheet.getRange(3, 2).setValue(everyNth)
                                dateCell.setValue(newDate);                                   // → puts the above information into the actual cell the user checked
                                activeSheet.getRange(aRow,1,1,6).setBackground("#87868c");    // → changes the background color of the row in which the user checked the cell                                                                                    
                                script_readdTask() }                                                 // → calls readdTask function which will repeat the task and set its date to whatever repeat frequency it is set in the setTasks sheet
           
           
            else {                                                                         
                   dateCell.setValue("");                                                     // → clears the date when the cell is unchecked     
                   activeSheet.getRange(aRow,1,1,6).setBackground("#ffffff"); }}}            // → restores the color of the row to what it was, white, if the cell is unchecked


  var sheetName  = activeSheet.getRange(1,15).getValue();
  var nameCheck1 = activeSheet.getRange(1,1).getValue();
  var nameCheck2 = activeSheet.getRange(1,6).getValue();
  var currentSheet = "" + nameCheck1 + nameCheck2

         if (sheetName == currentSheet){
         var bCell = e.source.getActiveCell()
    
         if (bCell.getValue() === true){
             bCell.setBackground("green")
    
 }  else if (bCell.getValue() === false){ 
             bCell.setBackground("#f3f3f3");
    }
   }

}

我认为您的问题是由于尽管 script_atEdit(e) 是从 doGet(e) 调用的,但您正试图将 script_atEdit(e) 用作 OnEdit 触发器调用的函数。

在你的情况下,从你的回复中,我了解到 script_atEdit(e) 是由 doGet(e)atEdit() 调用的 运行。 atEdit() 由 OnEdit 触发器 运行。

这种情况下,请修改script_atEdit(e)如下。在您的脚本中,script_atEdit(e)e 是 sheet 名称。

发件人:

var activeSheet     = e.source.getActiveSheet();  

收件人:

var activeSheet = SpreadsheetApp.getActive().getSheetByName(e) || SpreadsheetApp.getActiveSheet();

还有,

发件人:

var aCell = e.source.getActiveCell(), col = aCell.getColumn();   

收件人:

var aCell = activeSheet.getActiveCell(), col = aCell.getColumn();

还有,

发件人:

var bCell = e.source.getActiveCell()

收件人:

var bCell = activeSheet.getActiveCell();

注: