请求修改工时表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
相关产品推荐
相关产品推荐

