listFormNonResponders(form, rosterEmails) compares a roster to people who already submitted and returns the emails that have not. Both sides are trimmed and lowercased before the compare.
When to use
- Nudging only the people who have not filled in a form
- A weekly reminder that must not re-mail people who already responded
- Attendance or RSVP tracking against a known list
How to use this snippet
/**
* Return roster emails that have not yet submitted the form.
* Emails are trimmed and lowercased; roster duplicates are dropped.
* Relies on FormResponse.getRespondentEmail(), which is only populated
* when the form collects email addresses.
*
* @param {GoogleAppsScript.Forms.Form} form
* @param {string[]} rosterEmails
* @return {string[]}
*/
function listFormNonResponders(form, rosterEmails) {
function norm(e) {
return String(e == null ? '' : e).trim().toLowerCase();
}
var seen = {};
form.getResponses().forEach(function (r) {
var email = norm(r.getRespondentEmail());
if (email) seen[email] = true;
});
var out = [];
var used = {};
(rosterEmails || []).forEach(function (raw) {
var email = norm(raw);
if (!email || used[email]) return;
used[email] = true;
if (!seen[email]) out.push(email);
});
return out;
}
Example
function whoHasNotReplied() {
var form = FormApp.openById('FORM_ID');
var roster = ['ada@example.com', 'bob@example.com'];
Logger.log(listFormNonResponders(form, roster));
}
Notes
getRespondentEmail()is empty unless the form collects emails (Settings → Collect email addresses, or a sign-in restriction that records the account). If the form does not collect emails, every roster address looks like a non-responder. Check that setting before you send reminders.- Responses with a blank respondent email are ignored when building the "already replied" set.
- This does not send mail. Pair it with Create Drafts From Rows so a person can review and hit Send.
- For consistent keys, this matches Normalize an Email Address.
Happy Coding!
