需求:仅当今日在Calendar!A2:A范围时运行Google Apps Script
出勤追踪表格脚本优化需求
我为学校制作了一款出勤追踪表格,目前可正常使用但希望进一步优化。现有逻辑为每日清晨通过Apps Script复制Template工作表并重命名,数据从数据工作表(实际版本由Google表单填充)拉取。现需优化:仅当今日日期属于Calendar工作表A2:A范围内的日期时,才执行该脚本。
当前代码如下:
//================================================================================= // Creates a copy template and renames the new sheet between 0200-0300 every day //================================================================================= function createNewSheet(){ const sh = SpreadsheetApp.getActiveSpreadsheet(); const ss = sh.getSheetByName("Template"); const prot = ss.getProtections(SpreadsheetApp.ProtectionType.RANGE); const date = Utilities.formatDate(new Date(),"America/New_York","dMMMyy") let nSheet = ss.copyTo(sh).setName(date); nSheet.showSheet() let p; for (let i in prot){ p = nSheet.getRange(prot[i].getRange().getA1Notation()).protect(); p.removeEditors(p.getEditors()); if (p.canDomainEdit()) { p.setDomainEdit(false); } } //copy and paste date const daily = sh.getSheetByName(date); daily.getRange('B1').activate(); daily.getCurrentCell().setFormula('=today()'); SpreadsheetApp.flush(); daily.getRange('B1').copyTo(daily.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_VALUES, false); }
优化后的代码实现
添加日期检查逻辑,仅在今日属于目标范围时执行工作表复制操作:
//================================================================================= // Creates a copy template and renames the new sheet between 0200-0300 every day // 仅当今日日期在Calendar!A2:A范围内时执行 //================================================================================= function createNewSheet(){ const sh = SpreadsheetApp.getActiveSpreadsheet(); // 先检查今日是否在目标日期范围内,不在则直接退出 if (!isTodayInCalendarRange(sh)) return; const ss = sh.getSheetByName("Template"); const prot = ss.getProtections(SpreadsheetApp.ProtectionType.RANGE); const date = Utilities.formatDate(new Date(),"America/New_York","dMMMyy") let nSheet = ss.copyTo(sh).setName(date); nSheet.showSheet() let p; for (let i in prot){ p = nSheet.getRange(prot[i].getRange().getA1Notation()).protect(); p.removeEditors(p.getEditors()); if (p.canDomainEdit()) p.setDomainEdit(false); } // 直接设置日期值,替代原公式转值逻辑,更高效 const daily = sh.getSheetByName(date); daily.getRange('B1').setValue(new Date()); } // 辅助函数:检查今日日期是否存在于Calendar!A2:A范围内 function isTodayInCalendarRange(spreadsheet) { const calendarSheet = spreadsheet.getSheetByName("Calendar"); if (!calendarSheet) { console.log("未找到Calendar工作表"); return false; } // 获取A列非空日期数据 const dateList = calendarSheet.getRange("A2:A").getValues().flat().filter(item => item instanceof Date); const today = new Date(); // 统一日期格式(仅保留年月日,消除时分秒差异) const todayNormalized = new Date(today.getFullYear(), today.getMonth(), today.getDate()); // 遍历匹配日期 for (const targetDate of dateList) { const targetNormalized = new Date(targetDate.getFullYear(), targetDate.getMonth(), targetDate.getDate()); if (targetNormalized.getTime() === todayNormalized.getTime()) { return true; } } return false; }
关键优化点说明
- 新增
isTodayInCalendarRange辅助函数,专门处理日期匹配逻辑,代码职责更清晰 - 日期对比时统一格式化(去掉时分秒),避免因时间部分差异导致的匹配失败
- 简化日期设置逻辑:直接通过
setValue写入日期值,替代原公式转值的冗余步骤 - 主函数开头优先执行检查,不符合条件时直接终止,减少不必要的资源消耗
内容的提问来源于stack exchange,提问作者Anthony Saunders
相关产品推荐
相关产品推荐

