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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 18:06:04