Google Sheets点击按钮自动获取Gmail用户名的实现方案咨询
实现结论
该需求完全可实现,核心是调用Google Apps Script内置的用户身份接口,同时搭配并发锁解决500人同时访问的冲突问题,具体实现方案如下:
前置要求
所有学生需使用学校统一的Google Workspace账号访问系统,确保可以获取到合法的用户身份标识。
核心调整逻辑
- 替换原有从B1单元格取姓名的逻辑,改用
Session.getActiveUser().getEmail()获取当前登录用户的邮箱,可通过字符串处理提取邮箱前缀作为学生姓名,也可新增一张隐藏的「姓名映射表」存储邮箱与学生真实姓名的对应关系,避免直接展示邮箱。 - 新增并发锁机制,使用Google Apps Script内置的
LockService防止多用户同时写入数据时出现内容覆盖、记录错乱问题。 - 删掉原代码中所有和B1单元格读写、清除相关的逻辑,不再需要下拉框选择操作。
调整后可用代码示例
// 提前配置学校邮箱后缀,用于提取学生姓名,可根据实际情况修改 const SCHOOL_EMAIL_SUFFIX = "@yourschool.edu"; function clockIn() { // 加写锁,最多等待3秒避免冲突 const lock = LockService.getScriptLock(); try { lock.waitLock(3000); } catch (e) { SpreadsheetApp.getUi().alert("系统繁忙,请10秒后重试"); return; } var ss = SpreadsheetApp.getActiveSpreadsheet(); var mainSheet = ss.getSheetByName("DATASHEET"); // 获取当前用户姓名 const userEmail = Session.getActiveUser().getEmail(); const userName = userEmail.replace(SCHOOL_EMAIL_SUFFIX, ""); var lastRow = mainSheet.getLastRow(); // 检查是否已签出未返回 for (var j = 5; j <= lastRow; j++) { if(userName == mainSheet.getRange(j, 1).getValue() && mainSheet.getRange(j,3).getValue() == '') { Browser.msgBox("⚠️ 你已签出","请点击返回教室按钮后再重试",Browser.Buttons.OK); lock.releaseLock(); return; } } // 新增签出记录 mainSheet.getRange(lastRow+1,1).setValue(userName).setFontSize(12); mainSheet.getRange(lastRow+1,2).setValue(new Date()).setNumberFormat("MM/dd/yyyy hh:mm:ss A/P").setHorizontalAlignment("left").setFontSize(12); SpreadsheetApp.getUi().alert("⏰ 请尽快返回!⏰","你的老师在等你",SpreadsheetApp.getUi().ButtonSet.OK); // 释放锁 lock.releaseLock(); } function clockOut() { const lock = LockService.getScriptLock(); try { lock.waitLock(3000); } catch (e) { SpreadsheetApp.getUi().alert("系统繁忙,请10秒后重试"); return; } var ss = SpreadsheetApp.getActiveSpreadsheet(); var mainSheet = ss.getSheetByName("DATASHEET"); const userEmail = Session.getActiveUser().getEmail(); const userName = userEmail.replace(SCHOOL_EMAIL_SUFFIX, ""); var lastRow = mainSheet.getLastRow(); var foundRecord = false; for (var j = 5; j <= lastRow; j++) { if(userName == mainSheet.getRange(j, 1).getValue() && mainSheet.getRange(j,3).getValue() == '') { SpreadsheetApp.getUi().alert("🙏 感谢配合!🙏"," " ,SpreadsheetApp.getUi().ButtonSet.OK); mainSheet.getRange(j,3).setValue(new Date()).setNumberFormat("MM/dd/yyyy hh:mm:ss A/P").setHorizontalAlignment("left").setFontSize(12); // 修复原代码时间计算的数值错误 var totalTime = (mainSheet.getRange(j,3).getValue() - mainSheet.getRange(j,2).getValue()) /(60*1000); mainSheet.getRange(j,4).setValue(totalTime.toFixed(2)).setNumberFormat("#0.00").setHorizontalAlignment("left").setFontSize(12); foundRecord = true; } } if(foundRecord == false) { SpreadsheetApp.getUi().alert("⚠️ 未找到记录 ⚠️","你可能忘记点击外出签出了?" ,SpreadsheetApp.getUi().ButtonSet.OK); } TotalHours(); lock.releaseLock(); } // 以下原有函数逻辑无需改动,直接沿用即可 function TotalHours() { //DEFINE ALL ACTIVE SHEETS var ss = SpreadsheetApp.getActiveSpreadsheet(); //DEFINE MAIN SHEET var mainSheet = ss.getSheetByName("DATASHEET"); //LAST ROW ON MAIN SHEET var lastRow = mainSheet.getLastRow(); //DEFINE ARRAY var totals = []; //LOOP THROUGH ALL RATES for (var j = 5; j <= lastRow; j++) { var rate = mainSheet.getRange(j, 4).getValue(); var name = mainSheet.getRange(j, 1).getValue(); var foundRecord = false; for(var i = 0; i < totals.length; i++) { //FOUND RECORD ADD TO TOTAL if(name == totals[i][0] && rate != '') { totals[i][1] = totals[i][1] + rate; foundRecord = true; } } //ADD NEW RECORD, EXISTING RECORD NOT FOUND if(foundRecord == false && rate != '') { totals.push([name, rate]); } } //CLEAR DATA mainSheet.getRange("F5:G1000").clear(); //DISPLAY TOTALS for(var i = 0; i < totals.length; i++) { mainSheet.getRange(5+i,6).setValue(totals[i][0]).setFontSize(12); mainSheet.getRange(5+i,7).setValue(totals[i][1]).setFontSize(12); } } function ClearCells() { var sheet = SpreadsheetApp.getActive().getSheetByName('DATASHEET'); sheet.getRange('A5:G1000').clearContent(); } function clearRange() { var sheetActive = SpreadsheetApp.openById("1sjx0UAv73wiW-Jo1e8QWZuanjKK2tsjveVXjB1y_IHw").getSheetByName("DATASHEET"); sheetActive.getRange('A5:G1000').clearContent(); }
可选安全优化
如果担心给学生开放表格编辑权限会导致数据被误改,可以把整个系统部署为Web App:
- 执行身份选择「我(开发者账号)」
- 访问权限选择「你学校组织内的用户」
- 前端仅保留两个按钮分别触发签出、签入逻辑,全程不需要学生访问原始表格,数据安全性更高。
内容的提问来源于stack exchange,提问作者Rocco Barletta
相关产品推荐
相关产品推荐

