如何获取Google Sheets时钟触发器关联的对应电子表格文档
解决方法
Google Apps Script的时间触发器确实存在getTriggerSourceId()返回null的原生限制,该接口仅对表单提交、表格编辑等事件类触发器有效,无法直接获取时间触发器关联的电子表格ID,你可以通过自行维护映射关系的方式实现需求,具体实现逻辑如下:
- 创建触发器时,将生成的触发器唯一ID与当前电子表格ID的映射关系存入用户属性中,全局可读取
- 可同时将触发器ID存入对应电子表格的文档属性,既可以校验「单电子表格仅1个触发器」的限制,也支持从表格侧反查关联触发器
- 遍历项目触发器列表时,直接用触发器ID从预先存储的映射表中匹配,即可获取对应的关联电子表格ID
修改后的示例代码
触发器创建逻辑
function setTrigger(form) { const props = PropertiesService.getDocumentProperties(); // 先校验当前表格是否已创建触发器,避免重复创建 const existingTriggerId = props.getProperty('boundTriggerId'); if (existingTriggerId) { throw new Error('当前电子表格已创建过触发器'); } const currentSpreadsheetId = SpreadsheetApp.getActiveSpreadsheet().getId(); // 存入文档属性 props.setProperty('backupSpreadsheet', currentSpreadsheetId); props.setProperty('triggerValue1', form.t1); props.setProperty('triggerValue2', form.t2); props.setProperty('triggerValue3', form.t3); // 创建时钟触发器 const triggerId = ScriptApp.newTrigger('getData') .timeBased() .atHour(8) .everyDays(1) .create() .getUniqueId(); // 存储触发器ID与表格ID的映射到用户属性 const userProps = PropertiesService.getUserProperties(); const triggerMap = JSON.parse(userProps.getProperty('triggerSpreadsheetMap') || '{}'); triggerMap[triggerId] = currentSpreadsheetId; userProps.setProperty('triggerSpreadsheetMap', JSON.stringify(triggerMap)); // 把触发器ID存入当前文档属性 props.setProperty('boundTriggerId', triggerId); }
遍历触发器查询关联表格的逻辑
function getAllTriggersWithSpreadsheet() { const userProps = PropertiesService.getUserProperties(); const triggerMap = JSON.parse(userProps.getProperty('triggerSpreadsheetMap') || '{}'); const allTriggers = ScriptApp.getProjectTriggers(); const triggerList = []; allTriggers.forEach(trigger => { // 仅筛选时间类型触发器 if (trigger.getEventType() === ScriptApp.EventType.CLOCK) { const tid = trigger.getUniqueId(); triggerList.push({ triggerId: tid, relatedSpreadsheetId: triggerMap[tid] || '无匹配关联表格' }); } }); return triggerList; }
注意事项
删除触发器时需要同步清理映射关系,避免产生脏数据:
function deleteTrigger(triggerId) { const allTriggers = ScriptApp.getProjectTriggers(); const targetTrigger = allTriggers.find(t => t.getUniqueId() === triggerId); if (!targetTrigger) return; // 删除用户属性中的映射记录 const userProps = PropertiesService.getUserProperties(); const triggerMap = JSON.parse(userProps.getProperty('triggerSpreadsheetMap') || '{}'); const relatedSpreadsheetId = triggerMap[triggerId]; delete triggerMap[triggerId]; userProps.setProperty('triggerSpreadsheetMap', JSON.stringify(triggerMap)); // 删除对应文档属性中的触发器ID记录 if (relatedSpreadsheetId) { const ss = SpreadsheetApp.openById(relatedSpreadsheetId); const docProps = PropertiesService.getDocumentProperties(); docProps.deleteProperty('boundTriggerId'); } // 最后删除触发器本身 ScriptApp.deleteTrigger(targetTrigger); }
内容的提问来源于stack exchange,提问作者Mihai A
相关产品推荐
相关产品推荐

