如何在Google Apps Script中实现按行的条件式单元格保护?
修正后的条件性单元格保护脚本
原代码存在的问题
- 函数定义语法错误,缺少起始大括号
- 仅固定处理第2行,未遍历所有数据行
- 字符串比较未加引号,
Done被当作变量而非字符串处理 - 移除保护逻辑会删除所有范围保护,而非仅对应行的目标保护
- 未设置保护权限,默认会限制所有用户(包括脚本执行者)
修正后的完整代码
function protectRowsOnEdit(e) { // 定位到目标工作表,替换成你的表名 const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SheetName"); if (!sheet) return; // 工作表不存在则直接退出 // 支持两种触发场景:编辑F列时处理当前行,手动运行时处理所有行 let targetRows; if (e && e.range) { // 编辑触发时,仅处理F列的编辑行,跳过表头 const editedRow = e.range.getRow(); if (editedRow === 1 || e.range.getColumn() !== 6) return; targetRows = [editedRow]; } else { // 手动运行时,处理所有有数据的行(从第2行开始) const lastRow = sheet.getLastRow(); if (lastRow < 2) return; targetRows = Array.from({length: lastRow - 1}, (_, i) => i + 2); } // 获取当前工作表的所有范围保护 const allProtections = sheet.getProtections(SpreadsheetApp.ProtectionType.RANGE); targetRows.forEach(row => { const status = sheet.getRange(row, 6).getValue().toString().trim(); const targetRange = sheet.getRange(row, 1, 1, 5); // 当前行的A-E列 // 移除当前行已有的A-E列保护(如果存在) allProtections.forEach(protection => { const protectedRange = protection.getRange(); if (protectedRange.getRow() === row && protectedRange.getColumn() === 1 && protectedRange.getNumColumns() === 5) { protection.remove(); } }); // 状态为Done时添加保护,并设置权限 if (status === "Done") { const protection = targetRange.protect().setDescription(`Protected Row ${row}`); // 保留脚本执行者的编辑权限,可按需调整 const currentUser = Session.getEffectiveUser(); protection.addEditor(currentUser); protection.removeEditors(protection.getEditors().filter(editor => editor.getEmail() !== currentUser.getEmail())); if (protection.canDomainEdit()) { protection.setDomainEdit(false); } } }); }
关键逻辑说明
- 触发方式:编辑F列单元格时自动处理当前行;手动运行脚本可批量处理所有数据行
- 保护清理:添加新保护前先移除当前行已有的A-E列保护,避免重复保护
- 权限控制:默认保留脚本执行者的编辑权限,防止自己被锁无法修改
- 容错处理:跳过表头行,对F列值做去空格处理,避免因空格导致的判断错误
内容的提问来源于stack exchange,提问作者shivashankar G
相关产品推荐
相关产品推荐

