Apps 脚本 - 以编程方式将答案从 Google Sheet 提交到 Google 表单 - 错误 - "Sorry, this response has already been submitted."
Apps Script - Programmatically submit answers from Google Sheet to Google Form - ERROR - "Sorry, this response has already been submitted."
我有一个 Google 表格和一个 Google Spreadsheet。
timestamp | name | email | revenue | Edit Url
2015-2-2 02:22:22 | David | | |
2015-2-2 07:22:22 | Paul | | |
2015-2-2 09:22:22 | Olive | | |
我想要完成的事情:
- 根据电子表格中的信息(姓名、电子邮件、收入),我想以编程方式遍历每一行,根据每一行中的信息填充表格,然后提交表格,并为提交的每个表格生成将存储在编辑 Url 列中的编辑 URL。
到目前为止这是我的 Google 应用程序脚本:
function myFunction() {
createSurveyResponses();
}
function createSurveyResponses() {
// Open a form by ID and add a new text item.
var form = FormApp.openById('form_id');
var response = form.createResponse();
var sheet = SpreadsheetApp.openById('spreadsheet_id');
var getAct = sheet.getActiveSheet();
var data = sheet.getDataRange().getValues();
// Access the text item as a generic item.
var items = form.getItems();
var item = items[0];
var urls = [];
var resultUrls = [];
for (var j = 1; j < data.length; j++) {
var dop = data[j][0]
if (item.getType() == 'TEXT') {
var textItem = item.asTextItem();
var itemResponse = textItem.createResponse(data[j][0]);
var another = response.withItemResponse(itemResponse);
response.submit();
}
}
// get the responses from the spreadsheet
var fresponses = form.getResponses();
for (var i = 0; i < fresponses.length; i++) {
var resp = [fresponses[i]];
urls.push([shortenUrl(fresponses[i].getEditResponseUrl())]);
}
var getdata = getAct.getRange(2,5,fresponses.length)
getdata.setValues(urls);
}
function shortenUrl(longUrl) {
// google url shortener api key
var key = "AIzaSyBVG4Q5i1mNI0YAO0XVGZ3suZU8etTvK34";
var serviceUrl="https://www.googleapis.com/urlshortener/v1/url?key="+key;
var options={
muteHttpExceptions:true,
method:"post",
contentType: "application/json",
payload : JSON.stringify({'longUrl': longUrl })
};
var response = UrlFetchApp.fetch(serviceUrl, options);
if(response.getResponseCode() == 200) {
var content = JSON.parse(response.getContentText());
if ( (content != null) && (content["id"] != null) )
return content["id"];
}
return longUrl;
}
但是,当我 运行 代码时,在第一次迭代(第一行)之后,我收到一个错误 Sorry, this response has already been submitted. (line 34, file "")
,这是在我提交响应时 response.submit();
。
我做错了什么?
我的最终目标是为每一行生成一个唯一的 URL,以便我的收件人可以使用该 URL 随时更新他们的回复 (getEditResponseUrl()
)。
此答案解释了如何将 Google Sheet 的答案提交到 Google 表单。
您需要了解的第一件事是表单响应和项目响应之间的区别。
- 表单回复 - 表单中所有问题的所有答案。
- 项目响应 - 一个问题的一个答案。
要以编程方式提交对 Google 表单的响应,代码必须创建表单响应,然后将项目响应添加到表单响应,然后提交表单响应。一个常见的错误是尝试提交项目响应。
为了向表单响应添加多个项目响应,您可能会使用循环。如果代码添加了多个表单响应,则可能会使用循环。所以,你需要在另一个循环中有一个循环。
有很多地方可能出错。但基本上,代码需要同时创建一个 Form Response,然后需要将多个 Item Response 添加到 Form Response 中。如果混淆了表单和项目响应,就会出错。
在提供的代码示例中,外部 for
循环遍历电子表格行数。内部 for
循环,循环遍历单个表单响应中的项目。
submit
方法不能在内循环中使用。每个表单项(问题)必须添加一个带有 createResponse()
的答案,然后必须将 Item 响应添加到 Form 响应. response 一词可用于整个表单响应,也可用于单个问题的响应(答案)。
项目响应添加到表单响应中:
newResponse.withItemResponse(itemResponse);
方法withItemResponse
可能令人困惑。您无需将其他方法链接到它即可添加答案。
代码如下:
function createSurveyResponses(ss_ID) {
if (ss_ID === undefined) {
ss_ID = '';
};
var ss = SpreadsheetApp.openById(ss_ID);
var sheet = ss.getSheetByName('Sheet1');
//Get data starting in row 2, column 2
var data = sheet.getRange(2, 2, sheet.getLastRow()-1, sheet.getLastColumn()-1).getValues();
var i = 0,
j = 0,
form,
items,
thisRow,
Name = "",
Email = "",
Revenue,
FormURL = "",
formID,
thisItem,
itemTypeIs,
response,
arraySS_Values = [],
editURL;
var arrayItemNames = ['Name','Email','Revenue'];
for (i=0;i<data.length;i+=1) {
thisRow = data[i];
Name = thisRow[0];
Email = thisRow[1];
Revenue = thisRow[2];
FormURL = thisRow[3];
arraySS_Values = [];
arraySS_Values.push(Name);//Fill an array with the cell values of one row from the spreadsheet
arraySS_Values.push(Email);
arraySS_Values.push(Revenue);
Logger.log('Name: ' + Name);
if (FormURL === "" || FormURL === undefined) { //If there is no form, create one
form = FormApp.create(Name);
formID = form.getId();
items = addItemsToForm(form, arrayItemNames);
} else {
form = FormApp.openByUrl(FormURL);
items = form.getItems(FormApp.ItemType.TEXT);
if (items.length === 0) { //If there are no form items, you must add them
items = addItemsToForm(form, arrayItemNames);
};
};
var newResponse = form.createResponse();
for (j=0;j<items.length;j+=1) {
thisItem = items[j];
itemTypeIs = thisItem.getType();
if (itemTypeIs===FormApp.ItemType.IMAGE || itemTypeIs===FormApp.ItemType.PAGE_BREAK || itemTypeIs===FormApp.ItemType.SECTION_HEADER) {
continue; //quit this loop, and loop again if the form item is an image, page break or section header
};
if (itemTypeIs === FormApp.ItemType.TEXT) {
var textItem = thisItem.asTextItem();
var itemResponse = textItem.createResponse(arraySS_Values[j]);
newResponse.withItemResponse(itemResponse);
Logger.log('itemResponse: ' + itemResponse.getResponse());
};
};
newResponse.submit();
var preFill_url = newResponse.toPrefilledUrl();
Logger.log('preFill_url: ' + preFill_url);
sheet.getRange(i+2, 5).setValue(preFill_url);
};
};
function addItemsToForm(form, arrayItemNames) {
var i=0;
for (i=0;i<arrayItemNames.length;i+=1) {
form.addTextItem().setTitle(arrayItemNames[i]);
};
return form.getItems();
};
代码试图处理表单是否已经存在的情况。如果电子表格没有表单 URL,则会创建一个新表单。我不知道您是否可以在这段代码中使用缩短的 URL,因为它可能需要使用 URL.
打开表单
我有一个 Google 表格和一个 Google Spreadsheet。
timestamp | name | email | revenue | Edit Url
2015-2-2 02:22:22 | David | | |
2015-2-2 07:22:22 | Paul | | |
2015-2-2 09:22:22 | Olive | | |
我想要完成的事情:
- 根据电子表格中的信息(姓名、电子邮件、收入),我想以编程方式遍历每一行,根据每一行中的信息填充表格,然后提交表格,并为提交的每个表格生成将存储在编辑 Url 列中的编辑 URL。
到目前为止这是我的 Google 应用程序脚本:
function myFunction() {
createSurveyResponses();
}
function createSurveyResponses() {
// Open a form by ID and add a new text item.
var form = FormApp.openById('form_id');
var response = form.createResponse();
var sheet = SpreadsheetApp.openById('spreadsheet_id');
var getAct = sheet.getActiveSheet();
var data = sheet.getDataRange().getValues();
// Access the text item as a generic item.
var items = form.getItems();
var item = items[0];
var urls = [];
var resultUrls = [];
for (var j = 1; j < data.length; j++) {
var dop = data[j][0]
if (item.getType() == 'TEXT') {
var textItem = item.asTextItem();
var itemResponse = textItem.createResponse(data[j][0]);
var another = response.withItemResponse(itemResponse);
response.submit();
}
}
// get the responses from the spreadsheet
var fresponses = form.getResponses();
for (var i = 0; i < fresponses.length; i++) {
var resp = [fresponses[i]];
urls.push([shortenUrl(fresponses[i].getEditResponseUrl())]);
}
var getdata = getAct.getRange(2,5,fresponses.length)
getdata.setValues(urls);
}
function shortenUrl(longUrl) {
// google url shortener api key
var key = "AIzaSyBVG4Q5i1mNI0YAO0XVGZ3suZU8etTvK34";
var serviceUrl="https://www.googleapis.com/urlshortener/v1/url?key="+key;
var options={
muteHttpExceptions:true,
method:"post",
contentType: "application/json",
payload : JSON.stringify({'longUrl': longUrl })
};
var response = UrlFetchApp.fetch(serviceUrl, options);
if(response.getResponseCode() == 200) {
var content = JSON.parse(response.getContentText());
if ( (content != null) && (content["id"] != null) )
return content["id"];
}
return longUrl;
}
但是,当我 运行 代码时,在第一次迭代(第一行)之后,我收到一个错误 Sorry, this response has already been submitted. (line 34, file "")
,这是在我提交响应时 response.submit();
。
我做错了什么?
我的最终目标是为每一行生成一个唯一的 URL,以便我的收件人可以使用该 URL 随时更新他们的回复 (getEditResponseUrl()
)。
此答案解释了如何将 Google Sheet 的答案提交到 Google 表单。 您需要了解的第一件事是表单响应和项目响应之间的区别。
- 表单回复 - 表单中所有问题的所有答案。
- 项目响应 - 一个问题的一个答案。
要以编程方式提交对 Google 表单的响应,代码必须创建表单响应,然后将项目响应添加到表单响应,然后提交表单响应。一个常见的错误是尝试提交项目响应。
为了向表单响应添加多个项目响应,您可能会使用循环。如果代码添加了多个表单响应,则可能会使用循环。所以,你需要在另一个循环中有一个循环。
有很多地方可能出错。但基本上,代码需要同时创建一个 Form Response,然后需要将多个 Item Response 添加到 Form Response 中。如果混淆了表单和项目响应,就会出错。
在提供的代码示例中,外部 for
循环遍历电子表格行数。内部 for
循环,循环遍历单个表单响应中的项目。
submit
方法不能在内循环中使用。每个表单项(问题)必须添加一个带有 createResponse()
的答案,然后必须将 Item 响应添加到 Form 响应. response 一词可用于整个表单响应,也可用于单个问题的响应(答案)。
项目响应添加到表单响应中:
newResponse.withItemResponse(itemResponse);
方法withItemResponse
可能令人困惑。您无需将其他方法链接到它即可添加答案。
代码如下:
function createSurveyResponses(ss_ID) {
if (ss_ID === undefined) {
ss_ID = '';
};
var ss = SpreadsheetApp.openById(ss_ID);
var sheet = ss.getSheetByName('Sheet1');
//Get data starting in row 2, column 2
var data = sheet.getRange(2, 2, sheet.getLastRow()-1, sheet.getLastColumn()-1).getValues();
var i = 0,
j = 0,
form,
items,
thisRow,
Name = "",
Email = "",
Revenue,
FormURL = "",
formID,
thisItem,
itemTypeIs,
response,
arraySS_Values = [],
editURL;
var arrayItemNames = ['Name','Email','Revenue'];
for (i=0;i<data.length;i+=1) {
thisRow = data[i];
Name = thisRow[0];
Email = thisRow[1];
Revenue = thisRow[2];
FormURL = thisRow[3];
arraySS_Values = [];
arraySS_Values.push(Name);//Fill an array with the cell values of one row from the spreadsheet
arraySS_Values.push(Email);
arraySS_Values.push(Revenue);
Logger.log('Name: ' + Name);
if (FormURL === "" || FormURL === undefined) { //If there is no form, create one
form = FormApp.create(Name);
formID = form.getId();
items = addItemsToForm(form, arrayItemNames);
} else {
form = FormApp.openByUrl(FormURL);
items = form.getItems(FormApp.ItemType.TEXT);
if (items.length === 0) { //If there are no form items, you must add them
items = addItemsToForm(form, arrayItemNames);
};
};
var newResponse = form.createResponse();
for (j=0;j<items.length;j+=1) {
thisItem = items[j];
itemTypeIs = thisItem.getType();
if (itemTypeIs===FormApp.ItemType.IMAGE || itemTypeIs===FormApp.ItemType.PAGE_BREAK || itemTypeIs===FormApp.ItemType.SECTION_HEADER) {
continue; //quit this loop, and loop again if the form item is an image, page break or section header
};
if (itemTypeIs === FormApp.ItemType.TEXT) {
var textItem = thisItem.asTextItem();
var itemResponse = textItem.createResponse(arraySS_Values[j]);
newResponse.withItemResponse(itemResponse);
Logger.log('itemResponse: ' + itemResponse.getResponse());
};
};
newResponse.submit();
var preFill_url = newResponse.toPrefilledUrl();
Logger.log('preFill_url: ' + preFill_url);
sheet.getRange(i+2, 5).setValue(preFill_url);
};
};
function addItemsToForm(form, arrayItemNames) {
var i=0;
for (i=0;i<arrayItemNames.length;i+=1) {
form.addTextItem().setTitle(arrayItemNames[i]);
};
return form.getItems();
};
代码试图处理表单是否已经存在的情况。如果电子表格没有表单 URL,则会创建一个新表单。我不知道您是否可以在这段代码中使用缩短的 URL,因为它可能需要使用 URL.
打开表单