You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

嵌套调用的onEdit函数中onEdit3无法正常工作的问题排查

排查Google Sheets onEdit触发器中onEdit3函数失效问题

我编写了一个主onEdit(event)函数,在其中调用onEdit1、onEdit2、onEdit3三个子函数。参考相关方案实现后,onEdit1和onEdit2可正常运行,但onEdit3无法工作,怀疑是event.range相关问题,无法自行解决,以下是我的脚本:

function onEdit(event) {
  onEdit1(event);
  onEdit2(event);
  onEdit3(event);
}

//ADD COLOR MPR MASTER TAB
function onEdit1(event) {
  var sss = event.source;
  var sourceSheet = sss.getActiveSheet();
  var shName = sourceSheet.getName();
  var crange = event.range;
  var crow = crange.getRow();
  var ccol = crange.getColumn();
  
  if ((shName == "MASTER" ) && (ccol >= 38)){
    var cvalue = crange.getValue();
    var validationSheet = sss.getSheetByName("CALCULS");
    var optionColor = validationSheet.createTextFinder(cvalue).findNext().getBackground();
    crange.setBackground(optionColor);

    var sourceOptionColor = sourceSheet.getRange(crow, 38).getBackground();
    destSheet.getRange(destRow,38).setBackground(sourceOptionColor);
  }
}

//MERGE BANQUE TAB
function onEdit2(event) {
  let sh = event.source.getActiveSheet()
  let onglets = ['BANQUE']
  let shCol = event.range.getColumn()
  let shRow = event.range.getRow()
  let upRows = [25]
  let upCols = [14]
   console.log(shCol)
   console.log(shRow)
  if (onglets.indexOf(sh.getName()!=-1) && upRows.includes(shRow) && upCols.includes(shCol)){
   mergeBanque()
  }
}

//LOCK ROWS MASTER TAB
function onEdit3(event) {
  let range = event.range; //get the range of edited cell
  let row = range.getRow(); //get the row
  let col = range.getColumn(); //get the column 
  let value = event.value; //get the new value of edited cell
  let sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('MASTER'); //get the sheet where edit is made
  
  if(col == 69 && row >= 6 && value == 'TRUE'){ //check if the edited cell is BM and row is equal or greater than 5 and value is X
    let lock_range = `B${row}:BQ${row}`; //set lock range using row
    let protection = sheet.getRange(lock_range).protect() //set protection
      .setDescription(`Ligne ${row}`)  //add description
    protection.addEditor(kamaramamedia);
    protection.removeEditors(protection.getEditors()); //remove editors
  }else if(col == 69 && row >= 6 && value == 'FALSE'){ //check if the edited cell is BL and row is equal or greater than 5 and value is O
    var protectedRange = sheet.getProtections(SpreadsheetApp.ProtectionType.RANGE); //get all protection with type range
    for (var i = 0; i < protectedRange.length; i++) { //loop 
      if (protectedRange[i].getDescription() == `Ligne ${row}`) { //row matching
        protectedRange[i].remove(); //remove protection
      }
    }  
  }
}

问题排查与修复方案

onEdit3的核心问题:

  1. 缺少工作表校验:
    代码直接获取了MASTER工作表,但没判断当前编辑的是否是这个表。如果用户编辑其他工作表,col == 69的条件永远不成立,函数不会执行。需要先校验编辑操作所在工作表是否为MASTER。

  2. 布尔值判断错误:
    当编辑的是复选框时,event.value返回的是布尔类型的true/false(小写),但代码里判断的是字符串'TRUE'/'FALSE',条件完全不匹配,导致分支无法触发。

  3. 未定义变量kamaramamedia:
    代码中直接使用kamaramamedia作为添加的编辑器,但这个变量没有定义(应该是邮箱地址字符串),会导致保护设置失败,甚至报错中断函数。

  4. 保护范围获取范围错误:
    sheet.getProtections(...)应该指定从当前MASTER工作表获取保护,否则会获取整个文档的所有保护,可能无法精准匹配目标行的保护。

修复后的onEdit3代码:

//LOCK ROWS MASTER TAB
function onEdit3(event) {
  let range = event.range;
  let row = range.getRow();
  let col = range.getColumn();
  let value = event.value;
  // 获取当前编辑的工作表,而非直接指定MASTER
  let activeSheet = event.source.getActiveSheet();
  let sheet = event.source.getSheetByName('MASTER');

  // 先校验是否在MASTER表编辑,且列是69、行≥6
  if (activeSheet.getName() !== 'MASTER' || col !== 69 || row < 6) return;

  // 正确判断布尔值(复选框的value是布尔类型)
  if (value === true) {
    let lock_range = `B${row}:BQ${row}`;
    let protection = sheet.getRange(lock_range).protect()
      .setDescription(`Ligne ${row}`);
    // 替换成实际的邮箱地址字符串
    const editorEmail = 'kamaramamedia@example.com';
    protection.addEditor(editorEmail);
    // 保留所有者权限,避免自己也被移除编辑权限
    protection.removeEditors(protection.getEditors().filter(email => email !== editorEmail));
  } else if (value === false) {
    // 从MASTER工作表获取保护,而非整个文档
    let protectedRanges = sheet.getProtections(SpreadsheetApp.ProtectionType.RANGE);
    for (let i = 0; i < protectedRanges.length; i++) {
      if (protectedRanges[i].getDescription() === `Ligne ${row}`) {
        protectedRanges[i].remove();
        break; // 找到匹配项后直接跳出循环,提升效率
      }
    }
  }
}

其他函数的潜在问题提示:

  • onEdit1:代码中使用了destSheet和destRow变量,但这两个变量未定义,会导致报错,需要补充定义或删除无关代码。
  • onEdit2:onglets.indexOf(sh.getName()!=-1)括号位置错误,应该是onglets.indexOf(sh.getName()) !== -1,否则判断逻辑完全错误,导致mergeBanque()永远不会触发。

内容的提问来源于stack exchange,提问作者Savoir Apprendre

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 12:06:29