Google Forms are powerful tools for collecting information, but their real magic unfolds when you integrate them with Google Apps Script. Apps Script allows you to automatically process form responses, send custom emails, update spreadsheets, and much more, transforming raw data into actionable insights and streamlined workflows. This section will guide you through the fundamental steps of accessing and manipulating form responses using Apps Script.
The first step in working with form responses is to link your Google Form to a Google Sheet. This is typically done within the Google Forms interface itself. Navigate to your form, click on the 'Responses' tab, and then click the green 'Link to Sheets' icon. Choose to create a new spreadsheet or link to an existing one. This spreadsheet will serve as the destination for all your form submissions, and it's what Apps Script will primarily interact with.
Once your form is linked to a spreadsheet, you can access this spreadsheet from your Apps Script project. You'll use the SpreadsheetApp service to get the active spreadsheet and then locate the specific sheet containing your form responses. Usually, the responses are in a sheet named 'Form Responses 1'.
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formSheet = ss.getSheetByName('Form Responses 1');Now that you have a reference to your form's response sheet, you can retrieve the data. The getDataRange() method gets all the data in the sheet, and getValues() converts it into a 2D array, where each inner array represents a row of data.
var data = formSheet.getDataRange().getValues();The first row of this data array typically contains the headers (the questions from your form). The subsequent rows contain the actual form responses. You'll often want to skip the header row when processing responses.
var headers = data[0]; // The first row is headers
var responses = data.slice(1); // Slice from the second row onwards to get just the responsesIterating through the responses array allows you to access each submission individually. Within the loop, you can access specific answers by their column index. Remember that arrays are zero-indexed, so the first column is index 0, the second is index 1, and so on.
for (var i = 0; i < responses.length; i++) {
var row = responses[i];
var email = row[1]; // Assuming email is the second column
var feedback = row[3]; // Assuming feedback is the fourth column
Logger.log('Email: ' + email + ', Feedback: ' + feedback);
}You can also map the column index to the actual question using the headers array. This makes your code more readable and less prone to errors if the column order changes.
var questionIndexMap = {};
for (var j = 0; j < headers.length; j++) {
questionIndexMap[headers[j]] = j;
}
for (var i = 0; i < responses.length; i++) {
var row = responses[i];
var email = row[questionIndexMap['Your Email Question']];
var feedback = row[questionIndexMap['Feedback Question']];
Logger.log('Email: ' + email + ', Feedback: ' + feedback);
}This mapping approach is particularly useful when dealing with forms that have many questions or when you need to maintain your script's robustness against changes in the form structure. By treating the headers as keys, you can abstract away the exact column positions.
graph TD;
A[Google Form] --> B(Responses Tab);
B --> C(Link to Sheets);
C --> D(Google Sheet);
D --> E{Apps Script Project};
E --> F(SpreadsheetApp.getActiveSpreadsheet);
F --> G(getSheetByName('Form Responses 1'));
G --> H(getDataRange);
H --> I(getValues);
I --> J(Process Responses);
J --> K{Perform Actions};
K --> L(Send Email);
K --> M(Update Calendar);
K --> N(Other Automation);
Beyond simply reading responses, Apps Script allows you to manipulate them. You can filter responses based on certain criteria, sort them, or even append new data to the response sheet. For instance, you might want to add a 'Processed' timestamp to each row after you've handled a response.
var currentRowNumber = i + 2; // +1 for 0-index, +1 for header row
formSheet.getRange(currentRowNumber, questionIndexMap['Processed Timestamp'] + 1).setValue(new Date());Remember that the getRange() method uses 1-based indexing for rows and columns. So, if you are processing the i-th response in your responses array (which is 0-indexed), and the 'Processed Timestamp' column is at index questionIndexMap['Processed Timestamp'] (also 0-indexed), you'll need to adjust the row and column numbers accordingly when writing back to the sheet. This gives you the power to keep track of the status of each submission.