使用谷歌应用程序脚本Web应用程序轮询谷歌工作表以获取更改的最佳方法



我正在开发一个谷歌应用程序脚本web应用程序,让它在谷歌工作表中轮询更改/更新。目前,这可以是";内容";或者简单地说是在该表最后一次更新的时候。我不能使用gui/浏览器进行交互,所以请考虑运行web应用程序的命令来自命令行上的curl,并将文本内容返回到该命令行。用户将根据需要重新启动web应用程序,该应用程序设置为运行@3分钟。

我有一个有效的基本例程:

  1. 应用程序启动时检查/获取原始状态(日期/内容(
  2. 运行一个计数器(针对每个(和一个计时器(睡眠(,并在每次迭代中检查/获取当前状态(日期/内容(
  3. 在每次迭代中,对照当前状态测试原始状态。如果这些不同,则通过ContentService发送文本输出(消息、日期或当前内容(

我已经找到了三种方法来应用于上述基本例程:

A。获取工作表dataRange值作为数组(sh.getDataRange().getValues();(

B。获取DriveApp上次更新的值(DriveApp.getFileById(fileId).getLastUpdated();(

C。获取修订列表上次修改日期(revisions = Drive.Revisions.list(fileId)(

方法A效果良好,可以针对电子表格上的特定网格(表(,但对于大型数据集可能会有问题?

function doGet() {
var ss = SpreadsheetApp.openById(fileId);
var sh = ss.getSheetByName('SheetName');
var rng = sh.getDataRange().getValues();
var msg = '';
for (var i = 0; i < 20; i++) {
SpreadsheetApp.flush();
var cur = sh.getDataRange().getValues();
i = i + 1;
if (JSON.stringify(rng) !== JSON.stringify(cur)) {
msg = JSON.stringify(cur);
return ContentService.createTextOutput(msg);
}
Utilities.sleep(10000);
}
return ContentService.createTextOutput(msg);
}

方法B确实有效,但您似乎需要等待1到5分钟才能报告工作表的更新。这个";可以";可以,但对于用户来说,进行更改的不够快

function doGet() {
var lastUpdated = DriveApp.getFileById(fileId).getLastUpdated();
var ss = SpreadsheetApp.openById(fileId);
var sh = ss.getSheetByName('Sheet2');
var rng = sh.getDataRange().getValues();
var msg = '';
for (var i = 0; i < 20; i++) {
SpreadsheetApp.flush();
var curUpdate = DriveApp.getFileById(fileId).getLastUpdated();
i = i + 1;
if (lastUpdated.toString() !== curUpdate.toString()) {
msg = lastUpdated.toString() + "n" + curUpdate.toString();
return ContentService.createTextOutput(msg);
}
Utilities.sleep(10000);
}
return ContentService.createTextOutput(msg);
}

方法C运行良好,几乎可以立即报告日期更改。不过,我有点担心,读到1000次修订后需要一个新的代币?

function doGet() {

var msg = '';
var revisions = Drive.Revisions.list(fileId);
var revision = revisions.items[revisions.items.length - 1];
var date = new Date(revision.modifiedDate);

for (var i = 0; i < 20; i++) {

var currevs = Drive.Revisions.list(fileId);
var currev = currevs.items[currevs.items.length - 1];
var curdate = new Date(currev.modifiedDate);

i = i + 1;

if ( date.toString() !== curdate.toString() ) {
msg = date.toString() + "n" + curdate.toString();
return ContentService.createTextOutput(msg);
}
Utilities.sleep(10000);
}
return ContentService.createTextOutput(msg);
}

使用B是有意义的,但我找不到一种方法使getLastupdated的响应更即时,也许C,使用修订是可行的吗?我错过了一个";转到";方法,或者我的web应用程序例程需要改进吗?

除了@Diego的建议,我还尝试了;modifiedDate";通过高级驱动器服务。这是一种治疗

function doGet() {
var lastUpdated = Drive.getFileById(fileId).modifiedDate;
var msg = '';
for (var i = 0; i < 20; i++) {
var curUpdate = Drive.getFileById(fileId).modifiedDate;
i = i + 1;
if (lastUpdated.toString() !== curUpdate.toString()) {
msg = lastUpdated.toString() + "n" + curUpdate.toString();
return ContentService.createTextOutput(msg);
}
Utilities.sleep(10000);
}
return ContentService.createTextOutput(msg);
}

我在文件中使用修改日期与最新修订版本之间的区别在于,文件还将报告绑定脚本的更改。修订将仅限于电子表格上的更改,不包括脚本更改。这可以从我下面的测试中看出,两者之间有几分钟的差距。

如果要将范围特别限制为仅电子表格更改,则将使用修订报告最准确的值。

function test() {
const fileId = FILE_ID;
console.log(getLastRevision(fileId)); // 2021-01-12T15:32:43.175Z
console.log(getLastUpdated(fileId)); // Tue Jan 12 2021 15:53:53 GMT+0000 (Greenwich Mean Time)
console.log(getLastUpdatedAdvanced(fileId)); // 2021-01-12T15:53:53.941Z
}
function getLastRevision(fileId) {
let response;
do {
response = Drive.Revisions.list(fileId, { maxResults: 1000 });
} while (response.nextPageToken);
return response.items[response.items.length - 1].modifiedDate;
}
function getLastUpdated(fileId) {
return DriveApp.getFileById(fileId).getLastUpdated();
}
function getLastUpdatedAdvanced(fileId) {
return Drive.Files.get(fileId).modifiedDate;
}

我不知道你希望电子表格有多少修订,但使用nextPageToken是非常直接的。然而,如果电子表格会有成千上万的修订,并且你会经常对此进行轮询,那么它可能不是最有效的方法。

我无法用DriveApp.getFileById(fileId).getLastUpdated()复制延迟,但我觉得这并不罕见。您可以尝试使用Advanced Drive服务,就像您在Revisions中所做的那样,来获得modifiedDate。我不会期望它返回延迟值。正如您所指出的,这可能是您的最佳选择,因为您不需要担心修订的数量,但请记住,它也反映了非电子表格更新。

最新更新