doPost(e) 不触发 onChange(e) - 在 Google 电子表格中触发更改事件
doPost(e) does not trigger onChange(e) - Trigger On Change event in Google Spreadsheet
我有一个非常简单的 doPost(e) 脚本项目,它用作 webhook 端点。它只是将接收到的 JSON 有效载荷记录到目标传播 sheet 的 A2 单元格中。在目标 spreadsheet 中,我有一个 onChange(e) 触发器,它将此有效负载传递给外部 API。虽然在运行时没有错误,但我的 onChange(e) 脚本根本没有被触发。如果我 cut/paste sheet 上的单元格内容,onChange(e) 会被正确触发。
在 Google 开发者页面 here 中提到了一些限制,但据说这些限制不适用于 doGet(e) 和 doPost(e)。
我错过了什么?
这是我的 doPost 代码:
var SHEETID = "my_sheetID_here";
function doPost(e) {
try {
var data = JSON.parse(e.postData.contents);
var sSht = SpreadsheetApp.openById(SHEETID);
var sht = sSht.getSheetByName("TEMP");
sht.getRange("A2").setValue(e.postData.contents);
return ContentService // return json success results
.createTextOutput(
JSON.stringify({"result":"success",
"data": JSON.stringify(data) }))
.setMimeType(ContentService.MimeType.JSON);
} catch (e) {
MailApp.sendEmail("xx@xx.com,yy@xx.com", "FireStation Webhook Error Occured!",
"\r\nMessage: " + e.message
+ "\r\nFile: " + e.fileName
+ "\r\nLine: " + e.lineNumber);
e = (typeof e === 'string') ? new Error(e) : e;
Logger.severe('%s: %s (line %s, file "%s"). Stack: "%s" . While processing %s.',e.name||'',
e.message||'', e.lineNumber||'', e.fileName||'', e.stack||'', processingMessage||'');
throw e;
}
}
这是我在目标中的 onChange(e) 代码 sheet:
function onChange(e) {
try {
var sheet = e.source.getActiveSheet();
var sheetname = sheet.getName();
Logger.log("Sheetname: "+sheetname);
if (sheetname === "TEMP" && sheet.getRange("A2").getValue() !== "") {
var payload = sheet.getRange("A2").getValue();
var URL = "my_external_api_URL_here";
var options =
{
"method" : "POST",
"payload" : payload,
"followRedirects" : true,
"muteHttpExceptions": true
};
var result = UrlFetchApp.fetch(URL, options);
Logger.log("HTTP Response: "+result.getResponseCode())
}
} catch (e) {
MailApp.sendEmail("xx@xx.com,yy@xx.com", "FireStation Template GAS Error Occured!",
"\r\nMessage: " + e.message
+ "\r\nFile: " + e.fileName
+ "\r\nLine: " + e.lineNumber);
e = (typeof e === 'string') ? new Error(e) : e;
Logger.severe('%s: %s (line %s, file "%s"). Stack: "%s" . While processing %s.',e.name||'',
e.message||'', e.lineNumber||'', e.fileName||'', e.stack||'', processingMessage||'');
throw e;
}
}
表格API可用于触发"On Change"事件。不要使用 setValues(array)
。删除该代码并添加一个函数以将值写入电子表格。
您可能需要在 appsscript.json 文件(清单文件)中设置范围。
清单 (appsscript.json) 文件
{
"timeZone": "America/New_York",
"dependencies": {
},
"webapp": {
"access": "MYSELF",
"executeAs": "USER_DEPLOYING"
},
"exceptionLogging": "STACKDRIVER",
"oauthScopes": ["https://www.googleapis.com/auth/drive",
"https://www.googleapis.com/auth/script.external_request"]
}
如果您正在使用其他范围,请在 "File" "Project Properties" 和范围选项卡中找到它们。将它们复制出来并放入 appsscript.json 文件中以保持相同的范围。
您修改的代码:
function doPost(e) {
try {
var data = JSON.parse(e.postData.contents);
writeToSheet({shName:"TEMP",ssFileID:SHEETID,data:data});//Write data to sheet using API
return ContentService // return json success results
.createTextOutput(
JSON.stringify({"result":"success",
"data": JSON.stringify(data) }))
.setMimeType(ContentService.MimeType.JSON);
} catch (e) {
//code . . . .
}
新功能:
使用 Sheets API v4 和 valueInputOption=USER_ENTERED
选项的函数:
function writeToSheet(po) {
var id,options,range,response,sh,targetSheetName,ss,url,values;
targetSheetName = po.shName;
id = po.ssFileID;
range = targetSheetName + "!A2:A2";
values = {values: [[po.data]]};
url = "https://sheets.googleapis.com/v4/spreadsheets/" +
id + "/values/" + range + ":append?valueInputOption=USER_ENTERED";
options = {
"method":"post",
"muteHttpExceptions": true,
"headers": {
"Authorization": "Bearer " + ScriptApp.getOAuthToken()
},
"contentType": "application/json",
"payload": JSON.stringify(values)
}
response = UrlFetchApp.fetch(url,options)
response = JSON.parse(response);
Logger.log('response ' + JSON.stringify(response))
}
解决方案
而不是使用内置的 Sheets 服务,即 SpreadsheetApp.openById(sheetid) 和 Range.setValue() ,使用 Sheets API version 4 solves the problem and triggers the onChange(e) on the target spreadsheet. Note that this solution requires Advanced Google Services/Sheet API 从开发者控制台启用。
这是我的 doPost(e) 调用的最新版本,它运行良好:
var SHEETID = "my_sheet_id_here";
function doPost(e) {
try {
var data = e.postData.contents;
var rowValues = [
[data,""],
];
var request = {
'valueInputOption': 'USER_ENTERED',
'data': [
{
"range": "TEMP!A2:B2",
"majorDimension": "ROWS",
"values": rowValues,
},
],
};
var response = Sheets.Spreadsheets.Values.batchUpdate(request, SHEETID);
return ContentService // return json success results
.createTextOutput(
JSON.stringify({"result":"success",
"data": JSON.stringify(data) }))
.setMimeType(ContentService.MimeType.JSON);
} catch (e) {
MailApp.sendEmail("levent@able3ventures.com,alkio@able3ventures.com", "FireStation Webhook Error Occured!",
"\r\nMessage: " + e.message
+ "\r\nFile: " + e.fileName
+ "\r\nLine: " + e.lineNumber);
e = (typeof e === 'string') ? new Error(e) : e;
Logger.severe('%s: %s (line %s, file "%s"). Stack: "%s" . While processing %s.',e.name||'',
e.message||'', e.lineNumber||'', e.fileName||'', e.stack||'', processingMessage||'');
throw e;
}
}
我有一个非常简单的 doPost(e) 脚本项目,它用作 webhook 端点。它只是将接收到的 JSON 有效载荷记录到目标传播 sheet 的 A2 单元格中。在目标 spreadsheet 中,我有一个 onChange(e) 触发器,它将此有效负载传递给外部 API。虽然在运行时没有错误,但我的 onChange(e) 脚本根本没有被触发。如果我 cut/paste sheet 上的单元格内容,onChange(e) 会被正确触发。
在 Google 开发者页面 here 中提到了一些限制,但据说这些限制不适用于 doGet(e) 和 doPost(e)。
我错过了什么?
这是我的 doPost 代码:
var SHEETID = "my_sheetID_here";
function doPost(e) {
try {
var data = JSON.parse(e.postData.contents);
var sSht = SpreadsheetApp.openById(SHEETID);
var sht = sSht.getSheetByName("TEMP");
sht.getRange("A2").setValue(e.postData.contents);
return ContentService // return json success results
.createTextOutput(
JSON.stringify({"result":"success",
"data": JSON.stringify(data) }))
.setMimeType(ContentService.MimeType.JSON);
} catch (e) {
MailApp.sendEmail("xx@xx.com,yy@xx.com", "FireStation Webhook Error Occured!",
"\r\nMessage: " + e.message
+ "\r\nFile: " + e.fileName
+ "\r\nLine: " + e.lineNumber);
e = (typeof e === 'string') ? new Error(e) : e;
Logger.severe('%s: %s (line %s, file "%s"). Stack: "%s" . While processing %s.',e.name||'',
e.message||'', e.lineNumber||'', e.fileName||'', e.stack||'', processingMessage||'');
throw e;
}
}
这是我在目标中的 onChange(e) 代码 sheet:
function onChange(e) {
try {
var sheet = e.source.getActiveSheet();
var sheetname = sheet.getName();
Logger.log("Sheetname: "+sheetname);
if (sheetname === "TEMP" && sheet.getRange("A2").getValue() !== "") {
var payload = sheet.getRange("A2").getValue();
var URL = "my_external_api_URL_here";
var options =
{
"method" : "POST",
"payload" : payload,
"followRedirects" : true,
"muteHttpExceptions": true
};
var result = UrlFetchApp.fetch(URL, options);
Logger.log("HTTP Response: "+result.getResponseCode())
}
} catch (e) {
MailApp.sendEmail("xx@xx.com,yy@xx.com", "FireStation Template GAS Error Occured!",
"\r\nMessage: " + e.message
+ "\r\nFile: " + e.fileName
+ "\r\nLine: " + e.lineNumber);
e = (typeof e === 'string') ? new Error(e) : e;
Logger.severe('%s: %s (line %s, file "%s"). Stack: "%s" . While processing %s.',e.name||'',
e.message||'', e.lineNumber||'', e.fileName||'', e.stack||'', processingMessage||'');
throw e;
}
}
表格API可用于触发"On Change"事件。不要使用 setValues(array)
。删除该代码并添加一个函数以将值写入电子表格。
您可能需要在 appsscript.json 文件(清单文件)中设置范围。
清单 (appsscript.json) 文件
{
"timeZone": "America/New_York",
"dependencies": {
},
"webapp": {
"access": "MYSELF",
"executeAs": "USER_DEPLOYING"
},
"exceptionLogging": "STACKDRIVER",
"oauthScopes": ["https://www.googleapis.com/auth/drive",
"https://www.googleapis.com/auth/script.external_request"]
}
如果您正在使用其他范围,请在 "File" "Project Properties" 和范围选项卡中找到它们。将它们复制出来并放入 appsscript.json 文件中以保持相同的范围。
您修改的代码:
function doPost(e) {
try {
var data = JSON.parse(e.postData.contents);
writeToSheet({shName:"TEMP",ssFileID:SHEETID,data:data});//Write data to sheet using API
return ContentService // return json success results
.createTextOutput(
JSON.stringify({"result":"success",
"data": JSON.stringify(data) }))
.setMimeType(ContentService.MimeType.JSON);
} catch (e) {
//code . . . .
}
新功能:
使用 Sheets API v4 和 valueInputOption=USER_ENTERED
选项的函数:
function writeToSheet(po) {
var id,options,range,response,sh,targetSheetName,ss,url,values;
targetSheetName = po.shName;
id = po.ssFileID;
range = targetSheetName + "!A2:A2";
values = {values: [[po.data]]};
url = "https://sheets.googleapis.com/v4/spreadsheets/" +
id + "/values/" + range + ":append?valueInputOption=USER_ENTERED";
options = {
"method":"post",
"muteHttpExceptions": true,
"headers": {
"Authorization": "Bearer " + ScriptApp.getOAuthToken()
},
"contentType": "application/json",
"payload": JSON.stringify(values)
}
response = UrlFetchApp.fetch(url,options)
response = JSON.parse(response);
Logger.log('response ' + JSON.stringify(response))
}
解决方案
而不是使用内置的 Sheets 服务,即 SpreadsheetApp.openById(sheetid) 和 Range.setValue() ,使用 Sheets API version 4 solves the problem and triggers the onChange(e) on the target spreadsheet. Note that this solution requires Advanced Google Services/Sheet API 从开发者控制台启用。
这是我的 doPost(e) 调用的最新版本,它运行良好:
var SHEETID = "my_sheet_id_here";
function doPost(e) {
try {
var data = e.postData.contents;
var rowValues = [
[data,""],
];
var request = {
'valueInputOption': 'USER_ENTERED',
'data': [
{
"range": "TEMP!A2:B2",
"majorDimension": "ROWS",
"values": rowValues,
},
],
};
var response = Sheets.Spreadsheets.Values.batchUpdate(request, SHEETID);
return ContentService // return json success results
.createTextOutput(
JSON.stringify({"result":"success",
"data": JSON.stringify(data) }))
.setMimeType(ContentService.MimeType.JSON);
} catch (e) {
MailApp.sendEmail("levent@able3ventures.com,alkio@able3ventures.com", "FireStation Webhook Error Occured!",
"\r\nMessage: " + e.message
+ "\r\nFile: " + e.fileName
+ "\r\nLine: " + e.lineNumber);
e = (typeof e === 'string') ? new Error(e) : e;
Logger.severe('%s: %s (line %s, file "%s"). Stack: "%s" . While processing %s.',e.name||'',
e.message||'', e.lineNumber||'', e.fileName||'', e.stack||'', processingMessage||'');
throw e;
}
}