Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Single Google Form for multiple Sheets [duplicate]

Due to ongoing development versioning, plus seemingly insurmountable problems implementing user permissions workarounds, I need to capture form data linked to a sheet which is not exposd to the users. Instead I want to launch the form from a separate spreadsheet app using a custom menu. Yet despite thorough Google searches, and the tantalizingly named 'FormApp.openById' method, I can't find a way to accomplish this.

I know I'm off track here; could anyone please point me to the way back?

like image 372
Tim Avatar asked Dec 08 '22 14:12

Tim


1 Answers

Step 1: Create Form

Normal operating procedure - create your form either through a script or using the Forms UI. Capture the ID of the form. For instance, from the URL when in the editor:

https://docs.google.com/forms/d/1-AWccGNgdJ7_5Isjer5K816UKNSaUPSlvlkY3dGJ1UQ/edit
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Attach a spreadsheet to capture responses. (We're not going to do anything more with that here.)

Step 2: Client Script

In the user-accessible spreadsheet, create a container-bound script (so it has access to the Spreadsheet UI). The following script produces a custom menu with a selection that launches a form in a Ui popup.

/**
 * Uses the Forms service to get a handle on an existing form, then retrieve its published URL.
 * Uses the UrlFetch Service to get a copy of the HTML for the form.
 * Uses the HtmlService to embed the form's HTML in a Spreadsheet UI.
 * ... which is finally shown using Spreadsheet.show().
 */
function launchForm() {
  var formID = '1-AWccGNgdJ7_5Isjer5K816UKNSaUPSlvlkY3dGJ1UQ';
  var form = FormApp.openById(formID);
  var formUrl = form.getPublishedUrl();

  var response = UrlFetchApp.fetch(formUrl);
  var formHtml = response.getContentText();

  var htmlApp = HtmlService
      .createHtmlOutput(formHtml)
      .setSandboxMode(HtmlService.SandboxMode.IFRAME)
      .setTitle('Ta Daaa!')
      .setWidth(500) 
      .setHeight(450);

  SpreadsheetApp.getActiveSpreadsheet().show(htmlApp);
}

function onOpen() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet();
  var entries = [{
    name : "Launch Form",
    functionName : "launchForm"
  }];
  sheet.addMenu("Custom Menu", entries);
};

Demo

Here's what you see when you select "Launch Form" from the "Custom Menu". One little annoyance, though - when the form is submitted, the user is taken to another browser window or tab. In the spreadsheet, the UI remains open, and needs to be manually closed. That problem is gone with IFRAME sandboxing!

Screenshot - embedded form


EDIT: Changes in the ECMA sandbox defaults were introduced recently, which require that the sandbox mode be explicitly set to NATIVE for this technique to work. Code has been updated.

EDIT Again: The newer IFRAME sandbox mode keeps the whole form experience inside the dialog.

like image 172
Mogsdad Avatar answered Dec 28 '22 05:12

Mogsdad