10

I have looked at the question "Is it possible to 'prefill' a google form using data from a google spreadsheet?" and the code provided in the answer (thanks Mogsdad) works well for text type Google form questions. My question is: Is it possible to prefill a checkbox type Google form question?

For example, if I have an existing spreadsheet with an entry for "Names" and one of the entries is "Fred, Barney" would it be possible, via coding, to have a form prefill with the checkboxes ticked for "Fred" and "Barney" under a "Names" checkbox type Google form question?

Thanks, Greig

Community
  • 1
  • 1
Greig
  • 115
  • 1
  • 1
  • 7

4 Answers4

20

The basic pattern for each response can be repeated for most other types. For example, this works for multiple choice:

            item = items[i].asMultipleChoiceItem();
            var respItem = item.createResponse(resp);

However, a checkbox can be tricky, as it may have one item, multiple items, and even "other" responses. When the response is recorded to your spreadsheet, it will appear as a comma-separated string; when received in a form submission event (e.g. in a trigger function), we get an array (... where all responses are in the first item in the array, in a comma-separated string). The createResponse() method for a checkboxItem expects an array of valid choices... so we can provide that with a little javascript magic:

            item = items[i].asCheckboxItem();
            // Response is a CSV string, need array
            var respArray = resp.split(/ *, */);
            var respItem = item.createResponse(respArray);

EDIT: Google has a bug with CheckboxItems and MultipleChoiceItems, when used with "Other" options enabled. Those "other" options are allowed, but get rendered incorrectly in the pre-filled URL, and as a result they don't appear in the displayed form. Please see and star Issue 4454.

Here's an updated version of the function from Is it possible to 'prefill' a google form using data from a google spreadsheet?, updated to handle lists, multiple choice, and checkbox responses. This version is more general, it can adapt to the headings in your spreadsheet. BONUS: if you add a column labeled "Prefilled URL", the script will write its generated URLs there.

screenshot

/**
 * Use Form API to generate pre-filled form URLs
 * 
 * https://stackoverflow.com/a/26395487/1677912
 */
function evenBetterBuildUrls() {
  var ss = SpreadsheetApp.getActive();
  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);
    // 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 );
          resp.setDate(resp.getDate()+1);
          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) {
      // Checking if there is any value
        if(resp[0].length != 0){
          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);
    }
    // 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);
    }
  }
};
Mogsdad
  • 44,709
  • 21
  • 151
  • 275
  • Thanks for your response Mogsdad. I have tried the code by running it as a script on the spreadsheet and got an error: "Invalid response submitted to item" applying to line 64 (var respItem = item.createResponse(resp);) which is two lines below the comment "// Add this answer to our pre-filled URL". Any thoughts? – Greig Oct 16 '14 at 03:40
  • 1
    I have tried this on a smaller spreadsheet similar to the example given by Mogsdad and it worked fine. It would seem the problem is in my existing form and spreadsheet. I have an entry in the csv cell that matches to a checkbox but no corresponding check box for it to select when it is going into the form. – Greig Oct 16 '14 at 05:00
  • @Greig - the documentation for [CheckboxItem.createResponse()](https://developers.google.com/apps-script/reference/forms/checkbox-item#createResponse(String)) explains this behavior; it "Throws an exception if any value does not match a valid choice for this item", unless your question includes "Other" options. – Mogsdad Oct 16 '14 at 13:02
  • Added note about a google bug with CheckboxItem and MultipleChoiceItem, related to "Other". – Mogsdad Oct 16 '14 at 13:36
  • Is there a way of skipping blank entries? – Greig Oct 17 '14 at 03:21
  • `if (item && resp !== '')...` – Mogsdad Oct 17 '14 at 09:44
  • Is it possible to make an HTTP call and get values from there instead of spreadsheet and fill up the form ? – Kartik Domadiya Jul 13 '15 at 07:18
  • @Kartik - are you referring to [Pre-populate form answers](https://support.google.com/docs/answer/160000?hl=en)? – Greig Oct 16 '15 at 01:09
  • @Mogsdad - I have dates in my pre-filled data and when looking at the logs the resp variable for a date is showing up in the format "Day MMM DD YYY HH:mm:ss Time Zone". I read [elsewhere](http://stackoverflow.com/questions/20108511/is-it-possible-to-prefill-a-google-form-using-data-from-a-google-spreadsheet) that the date should be in YYYY-MM-DD format. When I toggled out the 'resp = new Date( resp );' the log didn't change. Does the date format need adjusting in this code or am I just confused (as usual)? Thanks. – Greig Oct 16 '15 at 01:16
  • @Greig: Slightly different topic; that other question is constructing a pre-filled URL as a string, while this one is using the Forms service to generate the same from JavaScript objects. There's no need to format the date here, it gets taken care of for you. – Mogsdad Oct 16 '15 at 01:34
  • @Mogsdad - Thanks Mogsdad. Indeed it does. Regardless of how the date looked in the logs it worked just fine when it came to prefilling. (I wasn't seeing this as I had yet another issue with a null response in a checkbox field - which has nothing to do with the code provided). – Greig Oct 16 '15 at 01:40
  • Mogsdad: I'm adapting the evenBetterBuildUrls() and in the process I found some changes that could improve it by making it more easy to adopt by newbies. I.E. A very minor change: 'var data = ss.getDataRange().getValues();' could (should?) be changed to 'var data = sheet.getDataRange().getValues();' I'll be bold and edit your code. Other changes that I'm doing is to add Duration, Time and Grid, adding a "switch" and some lines of code to add the capability of import the responses to the form. Also I'm translating the comments to Spanish. P.S. Obviously I will give you the proper attribution :) – Rubén Dec 08 '15 at 13:27
  • Ups, the change is too small and SO doesn't allow those. – Rubén Dec 08 '15 at 13:33
1

When you edit the form, fill in the values that you want to be pre-filled.

Then get the pre-filled URL

enter image description here

Jack
  • 5,680
  • 10
  • 49
  • 74
0

This is the last Script i have developped it work great for me.

Update and prefield link for google Form.

This script will not turn off as we know the runtime is 6 minute i have make this script work with google form submit trigger and a manual trigger in the function to get the lastrow.

note :

  1. you must change all number with your specific cell
  2. Specially you must change you form entry in the last row of the script with your own (Take a look at the pic evry input have a fixed unique entry)

0

There is a small issue in the script provided as the answer.

var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName("Form Responses 1");
var data = ss.getDataRange().getValues();  // Data for pre-fill

The variable data is referencing the active sheet (ss), not the "Form Responses 1" sheet (sheet). This could be intentional but I thought I should highlight it if anyone else is using the same sheet for pre-filling and responses.