从Google电子表格中填充Google表单的响应

3
我正在尝试(目前没有成功)使用这个网站和Mogsdad在此处提供的非常有用的答案中选择的项目,从Google电子表格中填充Google表单。理想情况下,我想要:
  1. Logger.log(URL)记录电子表格中存储的所有数据的URL,是否可能仅记录最后一条记录并使用它来生成URL?

  2. 填写了预填充的URL后,是否可以自动提交?我在这里找到了这篇有用的文章here,表明这可以做到?

  3. 存储在Google电子表格中的数据是从另一个Google表单中捕获的数据。这是由于需要使用Excel(缺乏互联网连接)并使用合并公式将所有具有数据的单元格合并成一个。然后将其提交到另一个Google表单上,该表单具有脚本,以通过列将数据拆分出来,准备回答问题。这会影响需要在提交时自动提交的触发器吗?

我想补充一句,由于我的理解能力有限,因此如果这似乎很容易做到,请不要过于苛刻。
2个回答

2
第二个问题是,一旦填充了数据,预先填充的URL是否可以自动提交?我在这里找到了一篇有用的文章here,它建议可以这样做?
正如Mogsdad所说,
“有一个更好的起点。我们能否从电子表格中以编程方式将信息提交到Google表单中?当然可以!”
根据对Use App Scripts to open form and make a selection进行的编辑,负载/后置方法现在已经过时。替代方法是使用Form App服务。下面是我对evenBetterBuilURLs1进行的适应,由Mogsdad提交响应而不是创建预先填充的URL,并用于独立的Google脚本项目文件。
原始代码行已被注释掉。此外,我插入了一些换行符以避免水平滚动条。
/**
 * Use Form API to populate form
 * 
 * Addapted from https://dev59.com/PV8d5IYBdhLWcg3w1FB0#26395487
 */
function populateFormResponses() {
  //var ss = SpreadsheetApp.getActive();
  var id = '11KDxp1C6jAZaTMNlGHke8zEzQ7aZrFSFGABdwUHEV80';
  var ss = SpreadsheetApp.openById(id);
  var sheet = ss.getSheetByName("Form Responses 1");
  var data = ss.getDataRange().getValues();  // Data for pre-fill
  var headers = data[0];                     // Sheet headers == form titles (questions)

  var formUrl = ss.getFormUrl();             // Use form attached to sheet
  var form = FormApp.openByUrl(formUrl);
  var items = form.getItems();
  //var urlCol = headers.indexOf("Prefilled URL");   // If there is a column labeled this
                                                     // way, we'll update it

  // Skip headers, then build URLs for each row in Sheet1.
  for (var row = 1; row < data.length; row++ ) {
    //Logger.log("Generating pre-filled URL from spreadsheet for row="+row);
    Logger.log("Generating response from spreadsheet for row="+row);
    // build a response from spreadsheet info.
    var response = form.createResponse();
    for (var i=0; i<items.length; i++) {
      var ques = items[i].getTitle();           // Get text of question for item
      var quesCol = headers.indexOf(ques);      // Get col index that contains this 
                                                // question
      var resp = ques ? data[row][quesCol] : "";
      var type = items[i].getType().toString();
      Logger.log("Question='"+ques+"', resp='"+resp+"' type:"+type);
      // Need to treat every type of answer as its specific type.
      switch (items[i].getType()) {
        case FormApp.ItemType.TEXT:
          var item = items[i].asTextItem();
          break;
        case FormApp.ItemType.PARAGRAPH_TEXT: 
          item = items[i].asParagraphTextItem();
          break;
        case FormApp.ItemType.LIST:
          item = items[i].asListItem();
          break;
        case FormApp.ItemType.MULTIPLE_CHOICE:
          item = items[i].asMultipleChoiceItem();
          break;
        case FormApp.ItemType.CHECKBOX:
          item = items[i].asCheckboxItem();
          // In a form submission event, resp is an array, containing CSV strings. Join 
          // into 1 string.
          // In spreadsheet, just CSV string. Convert to array of separate choices, ready 
          // for createResponse().
          if (typeof resp !== 'string')
            resp = resp.join(',');      // Convert array to CSV
          resp = resp.split(/ *, */);   // Convert CSV to array
          break;
        case FormApp.ItemType.DATE:
          item = items[i].asDateItem();
          resp = new Date( resp );
          break;
        case FormApp.ItemType.DATETIME:
          item = items[i].asDateTimeItem();
          resp = new Date( resp );
          break;
        default:
          item = null;  // Not handling DURATION, GRID, IMAGE, PAGE_BREAK, SCALE, 
                        // SECTION_HEADER, TIME
          break;
      }
      // Add this answer to our pre-filled URL
      if (item) {
        var respItem = item.createResponse(resp);
        response.withItemResponse(respItem);
      }
      // else if we have any other type of response, we'll skip it
      else Logger.log("Skipping i="+i+", question="+ques+" type:"+type);
    }

    // Submit response
    response.submit();

    // Generate the pre-filled URL for this row
    //var editResponseUrl = response.toPrefilledUrl();

    // If there is a "Prefilled URL" column, update it
    //if (urlCol >= 0) {
    //  var urlRange = sheet.getRange(row+1,urlCol+1).setValue(editResponseUrl);
    //}
  }
};

1
谢谢!这对我想要批量上传的9/10列起作用了。在剩下的1/10中,Apps Script不喜欢用户在CHECKBOX中使用“其他”时提交的文本字符串。我不得不手动从表格中删除该数据,然后在脚本完成后将其粘贴回结果中。 - Avid
var data = ss.getDataRange().getValues(); should be var data = sheet.getDataRange().getValues(); - Francis Saa-Dittoh
1
@masoftheund 请查看 https://developers.google.com/apps-script/reference/spreadsheet/spreadsheet#getdatarange。您建议的代码仅在表单响应工作表不是第一个工作表时才需要。 - Rubén
我觉得那个替代方案更好,可以避免错误。但是我理解,谢谢。还有感谢你提供的代码,经过一些小修改后完美运行(以处理空白的多选响应)。 - Francis Saa-Dittoh

2
有可能只记录最后一次输入并使用它来生成URL吗?
我不确定你的意思 - 在另一个答案中,Logger.log()语句仅是为了演示如果您想要分发它,您可以生成正确的URL。您将使用变量url的内容,而不是记录它。
但让我们继续,因为我认为这有点偏离了你的方向。
那么,填充的URL是否可以在填充数据后自动提交?
有更好的起点。我们可以通过编程方式将电子表格中的信息提交到Google表单中吗?当然!请参见使用应用程序脚本打开表单并进行选择。这比“URL技巧”文章中看到的方法更可靠。
对于“自动提交”或模拟表单提交,您根本不需要担心填充的URL。这是烦人的人类的快捷方式。相反,您想要组合一个POST请求的有效负载,并使计算机完全绕过表单UI。
关于Excel的某些内容...这会影响需要的触发器以在提交时自动提交吗?
(听起来像...)您正在使用Form1将数据放入Spreadsheet1,然后期望在分解Form1的数据后,通过机器提交Form2来响应(人类?)提交Form1。
是的,您需要小心在尝试读取信息以提交Form2之前进行列拆分。
我建议您最好使用表格提交触发器函数来处理Spreadsheet1中从Form1接收到的字符串,然后立即发送POST到Form2。然后,我会记录这个操作已发生,使用电子表格电子邮件触发器中的技术。

谢谢Mogsdad - 这真的帮助我回答了这个问题,通过你的建议,我已经能够让它工作了!非常感谢。 - John Woodward
第二个问题的答案目前已经过时。 - Rubén

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接