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

请求修改工时表Google Apps Script:打卡下班计算时长并锁定数值

工时表脚本功能修改请求

我想给我的工时表脚本加两个功能:

  • 执行下班打卡(punchOut)时,自动算出上班打卡时间(Time In)到下班打卡时间(Time Out)的时长
  • 打完下班卡后,把Time In、Time Out和总时长这三个单元格的数值锁定,不能再修改

我没有编程基础,下面是我现在用的Google Apps Script代码,希望修改后能实现类似示例图的效果,麻烦帮忙改一下代码。

当前使用的代码

function setValue(cellName, value) {
  SpreadsheetApp.getActiveSpreadsheet().getRange(cellName).setValue(value);
}

function getValue(cellName) {
  return SpreadsheetApp.getActiveSpreadsheet().getRange(cellName).getValue();
}

function getNextRow() {
  return SpreadsheetApp.getActiveSpreadsheet().getLastRow() + 1;
}

function getNextRow2() {
  return SpreadsheetApp.getActiveSpreadsheet().getLastRow() + 2;
}

function setUser1(x) {
  setValue('I1', 'User 1');
}

function setUser2() {
  setValue('I1', 'User 2');
} 

function addRecord(a, b, c) {
  var row = getNextRow();
  setValue('A' + row, a);
  setValue('B' + row, b);
  setValue('C' + row, c);
}

function isUserIn(user) {
  var lastRow = SpreadsheetApp.getActiveSheet().getLastRow();
  for (var i = lastRow; i >= 1; i--) {
    if (getValue("A" + i) == user) {
      if (getValue("C" + i) > getValue("B" + i)) {
        return false;
      }
      return true;
    }
  }
}

function punchIN() {
  var user = getValue("I1");
  var lastRow = SpreadsheetApp.getActiveSheet().getLastRow();
  addRecord(getValue('I1'), new Date());
}

function punchOut() {
  var user = getValue("I1");
  var lastRow = SpreadsheetApp.getActiveSheet().getLastRow();
  if (isUserIn(user)) {
    for (var i = lastRow; i >= 1; i--) {
      if (getValue("A" + i) == user) {
        if (getValue("C" + i) == "") {
          setValue("C" + i, new Date(), "IN");
        }
      }
    }
  }
}

修改后的代码

function setValue(cellName, value) {
  SpreadsheetApp.getActiveSpreadsheet().getRange(cellName).setValue(value);
}

function getValue(cellName) {
  return SpreadsheetApp.getActiveSpreadsheet().getRange(cellName).getValue();
}

function getNextRow() {
  return SpreadsheetApp.getActiveSpreadsheet().getLastRow() + 1;
}

function setUser1() {
  setValue('I1', 'User 1');
}

function setUser2() {
  setValue('I1', 'User 2');
} 

function addRecord(a, b) {
  var row = getNextRow();
  setValue('A' + row, a);
  setValue('B' + row, b);
}

function isUserIn(user) {
  var lastRow = SpreadsheetApp.getActiveSheet().getLastRow();
  for (var i = lastRow; i >= 1; i--) {
    if (getValue("A" + i) == user) {
      // 检查用户是否未下班
      return getValue("C" + i) === "";
    }
  }
  return false;
}

function calculateDuration(timeIn, timeOut) {
  // 计算时间差并转换为小时,保留两位小数
  var diffMs = timeOut.getTime() - timeIn.getTime();
  var diffHrs = diffMs / (1000 * 60 * 60);
  return Math.round(diffHrs * 100) / 100;
}

function punchIN() {
  var user = getValue("I1");
  if (!user) {
    SpreadsheetApp.getUi().alert("请先选择用户!");
    return;
  }
  if (isUserIn(user)) {
    SpreadsheetApp.getUi().alert(user + "已经上班打卡,未下班不能重复打卡!");
    return;
  }
  addRecord(user, new Date());
}

function punchOut() {
  var user = getValue("I1");
  if (!user) {
    SpreadsheetApp.getUi().alert("请先选择用户!");
    return;
  }
  if (!isUserIn(user)) {
    SpreadsheetApp.getUi().alert(user + "还没上班打卡,无法下班!");
    return;
  }

  var sheet = SpreadsheetApp.getActiveSheet();
  var lastRow = sheet.getLastRow();
  var targetRow = -1;

  // 找到用户最近的未下班记录
  for (var i = lastRow; i >= 1; i--) {
    if (getValue("A" + i) == user && getValue("C" + i) === "") {
      targetRow = i;
      break;
    }
  }

  if (targetRow === -1) return;

  // 设置下班时间
  var timeOut = new Date();
  setValue("C" + targetRow, timeOut);

  // 计算时长并写入D列
  var timeIn = getValue("B" + targetRow);
  var duration = calculateDuration(timeIn, timeOut);
  setValue("D" + targetRow, duration);

  // 锁定打卡记录单元格,禁止编辑
  var range = sheet.getRange("B" + targetRow + ":D" + targetRow);
  var protection = range.protect().setDescription("锁定打卡记录");
  // 仅保留脚本运行者的编辑权限(可根据需求调整)
  var me = Session.getEffectiveUser();
  protection.addEditor(me);
  protection.removeEditors(protection.getEditors());
  if (protection.canDomainEdit()) {
    protection.setDomainEdit(false);
  }

  SpreadsheetApp.getUi().alert(user + "下班打卡完成,时长:" + duration + "小时");
}

新增功能说明

  • 自动计算时长:下班打卡时,自动算出上班到下班的小时数,保留两位小数后写入D列
  • 锁定打卡记录:打完下班卡后,对应行的Time In(B列)、Time Out(C列)、时长(D列)会被锁定,无法手动修改
  • 操作提示弹窗:未选用户、重复打卡等错误操作时,会弹出直观提示
  • 修复原代码问题:修正了setUser1的多余参数,优化了isUserIn的判断逻辑

内容的提问来源于stack exchange,提问作者Mhonz Regis

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 22:40:57