如何在Google Sheets App Script中循环定位数组符合条件的下一项
问题:Google Script垃圾值日轮换功能跳过休假用户的实现
需求背景
- 开发每周六自动轮换垃圾值日的功能
- 已实现功能:点击按钮可跳过当前轮次,自动分配列表下一位用户
- 待解决问题:当用户状态标记为
⛔ Vacation(休假)时,轮换需自动跳过该类用户
现有代码
var housemates = [ ["User 1","✅ Active",false], ["User 2","⛔ Vacation",false], ["User 3","⛔ Vacation",true], ["User 4","✅ Active",false], ["User 5","✅ Active",false], ["User 6","✅ Active",false] ]
// 0. 获取所有用户列表 function getUsers(){ var sheet = SpreadsheetApp.getActive(); var range = sheet.getRangeByName("housemates"); var values = range.getValues(); return values; } // 1. 查找当前值日用户 function getCurrentUser(){ var values = getUsers(); // 完整用户列表 const columnIndex = 2; // 标记当前用户的列索引 const matchText = true; let currentUser = values.findIndex(row => row[columnIndex] === matchText); return currentUser; } //2. 计算下一位值日用户 function getNextUser(){ var values = getUsers(); // 未过滤的用户列表 var currentUser = getCurrentUser(); // 当前值日用户索引 if (currentUser < values.length - 1){ var nextUser = currentUser + 1; } else { var nextUser = 0; } return nextUser; } //3. 提交按钮点击事件 function onSubmit() { var sheet = SpreadsheetApp.getActive(); var range = sheet.getRangeByName("housemates"); var values = getUsers(); // 未过滤的用户列表 var currentUser = getCurrentUser(); // 当前值日用户索引 var nextUser = getNextUser(); // 下一位值日用户索引 values.forEach(function (row, index) { if(index != nextUser) { values[index][2] = false; } else{ values[index][2] = true; } }); range.setValues(values); } // 4. 确认弹窗 function confirm() { var range = SpreadsheetApp.getActive().getRangeByName("housemates"); var values = range.getValues(); const currentUser = getCurrentUser(); const currentUserName = values[currentUser][0]; const nextUser = getNextUser(); // 下一位值日用户索引 const nextUserName = values[nextUser][0]; var ui = SpreadsheetApp.getUi(); const title = `⚠️ 确认切换?`; const description = `确认后,${nextUserName} 将成为下一位值日用户。`; var response = ui.alert(title, description, ui.ButtonSet.YES_NO); if (response == ui.Button.YES){ onSubmit(); } else if (response == ui.Button.NO){ return; } }
解决方案
核心修改getNextUser函数,实现循环查找有效用户的逻辑,同时补充边界异常处理,避免所有用户休假时的程序错误。
1. 修改getNextUser函数
//2. 计算下一位值日用户 function getNextUser(){ var values = getUsers(); var currentUser = getCurrentUser(); var totalUsers = values.length; var nextUser = currentUser; // 循环查找下一位Active用户,最多遍历所有用户一次避免死循环 do { nextUser = (nextUser + 1) % totalUsers; // 检查当前用户状态是否为Active if (values[nextUser][1] === "✅ Active") { return nextUser; } } while (nextUser !== currentUser); // 遍历一圈未找到有效用户,返回-1标记异常 return -1; }
2. 优化confirm函数,增加异常提示
// 4. 确认弹窗 function confirm() { var values = getUsers(); const currentUser = getCurrentUser(); const currentUserName = values[currentUser][0]; const nextUser = getNextUser(); var ui = SpreadsheetApp.getUi(); // 处理所有用户都休假的异常情况 if (nextUser === -1) { ui.alert("⚠️ 错误", "所有用户都处于休假状态,无法分配值日!", ui.ButtonSet.OK); return; } const nextUserName = values[nextUser][0]; const title = `⚠️ 确认切换?`; const description = `确认后,${nextUserName} 将成为下一位值日用户。`; var response = ui.alert(title, description, ui.ButtonSet.YES_NO); if (response == ui.Button.YES){ onSubmit(); } }
3. 优化onSubmit函数,适配异常情况
//3. 提交按钮点击事件 function onSubmit() { var sheet = SpreadsheetApp.getActive(); var range = sheet.getRangeByName("housemates"); var values = getUsers(); var nextUser = getNextUser(); // 异常情况直接终止并提示 if (nextUser === -1) { SpreadsheetApp.getUi().alert("⚠️ 错误", "所有用户都处于休假状态,无法分配值日!", ui.ButtonSet.OK); return; } values.forEach(function (row, index) { values[index][2] = index === nextUser; }); range.setValues(values); }
功能说明
- 修改后的
getNextUser会从当前用户的下一位开始循环遍历,直到找到第一个状态为✅ Active的用户 - 增加遍历次数限制,避免出现死循环
- 当所有用户都处于休假状态时,会弹出提示告知无法分配值日,避免程序出错
- 简化
onSubmit中的赋值逻辑,代码更简洁高效
内容的提问来源于stack exchange,提问作者Designying
相关产品推荐
相关产品推荐

