如何通过Google App Script获取Google表格单元格编辑历史?
获取Google Sheets单元格编辑历史的脚本方案
你观察到的那个POST请求确实是Google Sheets加载单元格编辑历史的核心接口,不过直接模拟这个请求需要处理几个关键参数和权限问题——毕竟Google并没有把这个接口开放为正式的公开API。下面是一步步的可行方案:
一、关键参数的获取方式
你已经识别了大部分参数的含义,这里补充如何在Google Apps Script中直接获取它们:
- Spreadsheet ID:从表格URL里提取,或者用
SpreadsheetApp.getActiveSpreadsheet().getId()在脚本中自动获取。 - Sheet ID:当前工作表的ID,通过
SpreadsheetApp.getActiveSheet().getSheetId()就能拿到,和你在请求里看到的"629843311"格式完全一致。 - 单元格位置参数:请求里的
selection数组是0索引的:- 单个单元格(比如B10,即第10行第2列)对应的核心参数是:
[null, SHEET_ID, 9, 1](行号-1=9,列号-1=1),范围部分写成[[null, SHEET_ID, 9, 10, 1, 2]](起始行9,结束行10;起始列1,结束列2)
- 单个单元格(比如B10,即第10行第2列)对应的核心参数是:
- clientRevision:表格的当前修订版本号,用
SpreadsheetApp.getActiveSpreadsheet().getLastRevisionId()获取即可,或者直接留空(部分场景下Google会自动兼容)。 - token:这是最麻烦的临时会话令牌,不过在Google Apps Script中可以利用
UrlFetchApp的内置身份验证跳过手动获取步骤——脚本运行时会自动使用当前用户的权限发送请求。
二、示例脚本:发送请求并解析编辑历史
下面是一个简化的脚本,模拟POST请求并提取编辑者和时间戳,最终写入表格:
function getCellEditHistory() { const ss = SpreadsheetApp.getActiveSpreadsheet(); const spreadsheetId = ss.getId(); const sheet = ss.getActiveSheet(); const sheetId = sheet.getSheetId(); // 目标单元格:这里以B10为例(第10行,第2列),可自行修改 const targetRow = 10; const targetCol = 2; // 构造selection参数(严格对应抓包的格式) const selection = JSON.stringify([ ss.getId(), // 替换为抓包时的第一个数字参数,若无效可尝试留空 [null, [null, sheetId.toString(), targetRow - 1, targetCol - 1], [[null, sheetId.toString(), targetRow - 1, targetRow, targetCol - 1, targetCol]]] ]); // 构造多部分表单请求体 const boundary = "----WebKitFormBoundaryFpwmP3acru2z5xQc"; const payload = [ `--${boundary}`, 'Content-Disposition: form-data; name="selection"', '', selection, `--${boundary}`, 'Content-Disposition: form-data; name="clientRevision"', '', ss.getLastRevisionId(), `--${boundary}`, 'Content-Disposition: form-data; name="includeDiffs"', '', 'true', `--${boundary}--` ].join("\r\n"); // 请求配置 const options = { method: "POST", headers: { "accept": "*/*", "content-type": `multipart/form-data; boundary=${boundary}`, "x-same-domain": "1" }, payload: payload, followRedirects: true, muteHttpExceptions: true // 方便查看错误信息 }; // 发送请求并解析响应 const url = `https://docs.google.com/spreadsheets/d/${spreadsheetId}/blame?includes_info_params=true`; const response = UrlFetchApp.fetch(url, options); const responseText = response.getContentText(); try { const data = JSON.parse(responseText); // 注意:实际响应的JSON结构可能需要调整索引,建议先打印responseText查看 const editRecord = data[1][1][0][2]; if (editRecord) { const editorName = editRecord[0][0]; const editTime = new Date(editRecord[1] * 1000); // 转换秒级时间戳为日期 // 将结果写入表格(示例写入D1-E2区域) sheet.getRange("D1").setValue("最后编辑者"); sheet.getRange("D2").setValue(editorName); sheet.getRange("E1").setValue("编辑时间"); sheet.getRange("E2").setValue(editTime); } else { SpreadsheetApp.getUi().alert("未找到该单元格的编辑历史"); } } catch (e) { SpreadsheetApp.getUi().alert(`解析出错:${e.message}\n响应内容:${responseText}`); } }
三、注意事项和可能的坑
- 权限授权:运行脚本时需要授权
https://www.googleapis.com/auth/spreadsheets和https://www.googleapis.com/auth/script.external_request权限,确保脚本能访问表格和发送外部请求。 - 接口稳定性:这个是Google内部接口,没有官方文档,参数或响应格式可能随时变更。如果脚本失效,需要重新抓包分析新的请求结构。
- 响应解析:示例中的
data[1][1][0][2]是基于你提供的请求推测的路径,实际运行时建议先打印responseText查看JSON结构,再调整解析索引。
你可以先运行脚本查看响应内容,再根据实际的JSON结构修改解析逻辑,就能顺利提取编辑历史并写入表格了。
内容的提问来源于stack exchange,提问作者Timogavk




