Adds everyone in your signup spreadsheet to Google Contacts, matching on email so nobody is entered twice.
Uses
Google Contacts
Google Sheets
Add your signup sheet to Google Contacts
Once a day, the spreadsheet your signups or enquiries land in is checked against Google Contacts. Every row is matched to your address book by email address: somebody new is added as a contact, and somebody already there is left in place rather than entered twice.
Nothing already on a contact is ever overwritten. When a row matches an existing contact, only what is blank is added, such as a missing phone number or name, and if your sheet holds a different phone number from the card it says so in the run summary and changes nothing. A row with no first name, or nothing usable in the 'Email' column, is skipped and named at the end, because without an email there is no safe way to tell that person from someone already there. No contact is ever deleted, and an unchanged sheet writes nothing.
Your tab needs a header row with the columns 'First Name', 'Last Name', 'Email' and 'Phone'; last name and phone may be empty. Company names are not stored.
signupSheetUrl to blank.Set signupSheetUrl to blank.signupTabName to blank.Set signupTabName to blank.signupSheetUrl. Save it as signupSheet.Read the rows of signupSheetUrl. Save it as signupSheet.signupRows to signupSheet.rows.Set signupRows to signupSheet.rows.signupRowCount to 0.Set signupRowCount to 0.rowCountErrorIf a step below fails, save the error as rowCountErrorsignupRows and save it as signupRowCount.Count the items in signupRows and save it as signupRowCount.signupRowCount to 0.Change signupRowCount to 0.signupRowCount is 0If signupRowCount is 0addressBook.List contacts. Save it as addressBook.knownContacts to addressBook.contacts.Set knownContacts to addressBook.contacts.knownContactCount to 0.Set knownContactCount to 0.contactCountErrorIf a step below fails, save the error as contactCountErrorknownContacts and save it as knownContactCount.Count the items in knownContacts and save it as knownContactCount.knownContactCount to 0.Change knownContactCount to 0.knownContactCount is 0If knownContactCount is 0knownContacts.Start an empty list and save it as knownContacts.knownEmails.Start an empty list and save it as knownEmails.knownContact in knownContacts:For each knownContact in knownContacts:knownEmail to blank.Set knownEmail to blank.contactEmailErrorIf a step below fails, save the error as contactEmailErrorknownContact.email lowercase and save it as knownEmail.Make knownContact.email lowercase and save it as knownEmail.knownEmail to blank.Change knownEmail to blank.knownEmail is emptyIf knownEmail is emptyknownEmail to (this contact has no email address).Change knownEmail to (this contact has no email address).knownEmail to the end of knownEmails and save it as knownEmails.Add knownEmail to the end of knownEmails and save it as knownEmails.addedPeople.Start an empty list and save it as addedPeople.updatedPeople.Start an empty list and save it as updatedPeople.needsAttention.Start an empty list and save it as needsAttention.skippedRows.Start an empty list and save it as skippedRows.alreadyCurrentCount to 0.Set alreadyCurrentCount to 0.signupRow in signupRows:For each signupRow in signupRows:firstName to blank.Set firstName to blank.lastName to blank.Set lastName to blank.signupEmail to blank.Set signupEmail to blank.signupPhone to blank.Set signupPhone to blank.firstNameReadErrorIf a step below fails, save the error as firstNameReadErrorsignupRow["First Name"] and save it as firstName.Trim signupRow["First Name"] and save it as firstName.firstName to blank.Change firstName to blank.lastNameReadErrorIf a step below fails, save the error as lastNameReadErrorsignupRow["Last Name"] and save it as lastName.Trim signupRow["Last Name"] and save it as lastName.lastName to blank.Change lastName to blank.signupEmailReadErrorIf a step below fails, save the error as signupEmailReadErrorsignupRow.Email and save it as signupEmail.Trim signupRow.Email and save it as signupEmail.signupEmail to blank.Change signupEmail to blank.signupPhoneReadErrorIf a step below fails, save the error as signupPhoneReadErrorsignupRow.Phone and save it as signupPhone.Trim signupRow.Phone and save it as signupPhone.signupPhone to blank.Change signupPhone to blank.firstName lastName and save it as personName.Trim firstName lastName and save it as personName.rowLabel to personName.Set rowLabel to personName.rowLabel is emptyIf rowLabel is emptyrowLabel to signupEmail.Change rowLabel to signupEmail.rowLabel is emptyIf rowLabel is emptyrowLabel to A row with no name and no email address.Change rowLabel to A row with no name and no email address.firstName is emptyIf firstName is emptyrowLabel - the 'First Name' column is empty, and a contact needs a first name. to the end of skippedRows and save it as skippedRows.Add rowLabel - the 'First Name' column is empty, and a contact needs a first name. to the end of skippedRows and save it as skippedRows.signupEmail is a valid email addressIf not signupEmail is a valid email addressrowLabel - the 'Email' column is empty or is not an email address. Without one there is no way to tell whether they are already in your contacts, so this row was left alone. to the end of skippedRows and save it as skippedRows.Add rowLabel - the 'Email' column is empty or is not an email address. Without one there is no way to tell whether they are already in your contacts, so this row was left alone. to the end of skippedRows and save it as skippedRows.signupEmail lowercase and save it as matchKey.Make signupEmail lowercase and save it as matchKey.matchKey in knownEmails and save it as matchIndex.Find the position of matchKey in knownEmails and save it as matchIndex.matchIndex is less than 0If matchIndex is less than 0createdResource to blank.Set createdResource to blank.createErrorIf a step below fails, save the error as createErrorfirstName. Save it as createResult.Create contact firstName. Save it as createResult.createResult.resource_name and save it as createdResource.Trim createResult.resource_name and save it as createdResource.rowLabel - could not be added to Google Contacts: createError as text to the end of skippedRows and save it as skippedRows.Add rowLabel - could not be added to Google Contacts: createError as text to the end of skippedRows and save it as skippedRows.createdResource isn't emptyIf createdResource isn't emptyrowLabel to the end of addedPeople and save it as addedPeople.Add rowLabel to the end of addedPeople and save it as addedPeople.knownContacts and save it as knownContacts.Add a record of resourceName, fullName, email, and phone to the end of knownContacts and save it as knownContacts.matchKey to the end of knownEmails and save it as knownEmails.Add matchKey to the end of knownEmails and save it as knownEmails.existingContact to knownContacts[@matchIndex].Set existingContact to knownContacts[@matchIndex].existingResource to blank.Set existingResource to blank.resourceErrorIf a step below fails, save the error as resourceErrorexistingContact.resourceName and save it as existingResource.Trim existingContact.resourceName and save it as existingResource.existingResource to blank.Change existingResource to blank.existingResource is emptyIf existingResource is emptyrowLabel - matches a contact that came back without an ID, so it could not be updated. to the end of skippedRows and save it as skippedRows.Add rowLabel - matches a contact that came back without an ID, so it could not be updated. to the end of skippedRows and save it as skippedRows.existingName to blank.Set existingName to blank.nameErrorIf a step below fails, save the error as nameErrorexistingContact.fullName and save it as existingName.Trim existingContact.fullName and save it as existingName.existingName to blank.Change existingName to blank.existingPhone to blank.Set existingPhone to blank.phoneErrorIf a step below fails, save the error as phoneErrorexistingContact.phone and save it as existingPhone.Trim existingContact.phone and save it as existingPhone.existingPhone to blank.Change existingPhone to blank.firstNameToAdd to blank.Set firstNameToAdd to blank.lastNameToAdd to blank.Set lastNameToAdd to blank.existingName is emptyIf existingName is emptyfirstNameToAdd to firstName.Change firstNameToAdd to firstName.lastNameToAdd to lastName.Change lastNameToAdd to lastName.phoneToAdd to blank.Set phoneToAdd to blank.signupPhone isn't emptyIf signupPhone isn't emptyexistingPhone is emptyIf existingPhone is emptyphoneToAdd to signupPhone.Change phoneToAdd to signupPhone.rowLabel - your sheet says signupPhone but their contact card says existingPhone. The contact was left as it is; change it by hand if the sheet is right. to the end of needsAttention and save it as needsAttention.Add rowLabel - your sheet says signupPhone but their contact card says existingPhone. The contact was left as it is; change it by hand if the sheet is right. to the end of needsAttention and save it as needsAttention.firstNameToAdd isn't empty or phoneToAdd isn't emptyIf firstNameToAdd isn't empty or phoneToAdd isn't emptyupdateErrorIf a step below fails, save the error as updateErrorexistingResource.Update contact existingResource.rowLabel to the end of updatedPeople and save it as updatedPeople.Add rowLabel to the end of updatedPeople and save it as updatedPeople.rowLabel - is already in your contacts but could not be updated: updateError as text to the end of skippedRows and save it as skippedRows.Add rowLabel - is already in your contacts but could not be updated: updateError as text to the end of skippedRows and save it as skippedRows.alreadyCurrentCount.Add 1 to alreadyCurrentCount.runSummary to Signup sheet checked against Google Contacts.Set runSummary to Signup sheet checked against Google Contacts.
Added: the length of addedPeople as text
Updated: the length of updatedPeople as text
Already up to date: alreadyCurrentCount as text
Needs a look: the length of needsAttention as text
Skipped: the length of skippedRows as text.addedPeople isn't emptyIf addedPeople isn't emptyrunSummary to runSummaryChange runSummary to runSummary
Added to your contacts:
addedPeople joined by a new line.updatedPeople isn't emptyIf updatedPeople isn't emptyrunSummary to runSummaryChange runSummary to runSummary
Filled in on contacts you already had:
updatedPeople joined by a new line.needsAttention isn't emptyIf needsAttention isn't emptyrunSummary to runSummaryChange runSummary to runSummary
Worth a look:
needsAttention joined by a new line.skippedRows isn't emptyIf skippedRows isn't emptyrunSummary to runSummaryChange runSummary to runSummary
Skipped:
skippedRows joined by a new line.runSummary.Show in the output: runSummary.