Skip to content

Commit 0e43f02

Browse files
committed
Add code from v1.3.2 (birdy) version
Added all the code from the Google Sheet Apps Script (birdy version).
1 parent 4e148e1 commit 0e43f02

File tree

1 file changed

+249
-0
lines changed

1 file changed

+249
-0
lines changed

Code.gs

Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
1+
/**
2+
* Batch Emailer v1.3.2 (birdy)
3+
* Last updated: November 10th, 2024
4+
*
5+
* Created by: Jonathan Kung
6+
*
7+
* This script will generate a batch email message to multiple emails.
8+
* This should be attached to a Google Sheet with 6 columns at least.
9+
* Columns: CHECKBOX | NAME | EMAIL1 | EMAIL2 | TIMESTAMP | MESSAGE
10+
* The checkbox column must contain only 1 checkbox per row.
11+
* The first row must contain headings only.
12+
*/
13+
14+
15+
//// RESET CHECKBOXES
16+
function resetCheckboxes() {
17+
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
18+
var data = sheet.getDataRange().getValues();
19+
20+
// Loop through each row (starting from row 2 to skip the header)
21+
for (var i = 1; i < data.length; i++) {
22+
var checkboxCell = sheet.getRange(i + 1, 1); // Get first column with checkboxes
23+
24+
// Clear the checkboxes
25+
checkboxCell.setValue(false);
26+
}
27+
}
28+
29+
30+
//// CREATE DRAFT GMAIL
31+
function createDraftWithBcc() {
32+
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
33+
var data = sheet.getDataRange().getValues();
34+
var bccEmails = [];
35+
var rawBccEmails = [];
36+
var studentNames = [];
37+
var doneColumnIndex = 4; // 5th column (index starts at 0)
38+
var messageColumnIndex = 5; // 6th column containing message
39+
var currentDate = new Date();
40+
var ui = SpreadsheetApp.getUi();
41+
42+
// Loop through the data, check to see if a student has been checked off and populate BCC with the parent emails and the message to be sent
43+
for (var i = 1; i < data.length; i++) {
44+
var sendEmail = data[i][0]; // Get status of checkbox in the first column
45+
var studentName = data[i][1].trim(); // Get student name from second column
46+
var parentEmail = data[i][2].trim(); // Get parent email from the third column
47+
var parentEmailOther = data[i][3].trim();// Get parent email from fourth column
48+
var emailCell = sheet.getRange(i + 1, 3); // Get email column
49+
var emailCellOther = sheet.getRange(i + 1, 4); // Get other email column
50+
51+
// Clear the colour from email cells
52+
emailCell.setBackground(null);
53+
emailCellOther.setBackground(null);
54+
55+
// Populate the BCCs
56+
if (sendEmail == true) { // Only add email to BCC if the flag is checked
57+
if (parentEmail == "" && parentEmailOther == "") {
58+
emailCell.setBackground('yellow');
59+
emailCellOther.setBackground('yellow');
60+
ui.alert('Missing Email \(see highlighted cells\).')
61+
return;
62+
}
63+
else {
64+
emailCell.setBackground('null');
65+
emailCellOther.setBackground('null');
66+
rawBccEmails.push(parentEmail);
67+
rawBccEmails.push(parentEmailOther);
68+
studentNames.push(studentName);
69+
}
70+
}
71+
}
72+
73+
// Clean up rawBccEmails list to get rid of nulls and duplicates
74+
bccEmails = Array.from(new Set(rawBccEmails.filter(item => item !== "" && item !== null && item !== undefined)));
75+
76+
// Handle what to do if students are checked vs. no students are checked
77+
// If students are checked, send the message
78+
if (bccEmails.length > 0) {
79+
// Prompt for the email message
80+
var response = ui.prompt('Draft Message', 'Type in the basic message you would like to send (you may edit or add more later in Gmail):', ui.ButtonSet.OK_CANCEL);
81+
var emailBody = response.getResponseText();
82+
var batchCount; // The number of emails we will send (we need to break it up because there is a limit set by Google as maxEmails)
83+
var emailCount; // The number of emails in the array
84+
var maxEmails = 50; // The max amount of emails allowed in a message (could be changed by Google)
85+
86+
// If user is ready to send the message.
87+
if (response.getSelectedButton() == ui.Button.OK) {
88+
// Count the number of emails in the array
89+
emailCount = bccEmails.length;
90+
91+
// Determine how many messages to send (batches of maxEmails - the limit Google will allow)
92+
batchCount = Math.ceil(emailCount / maxEmails);
93+
94+
for (var j = 0; j < batchCount; j++) {
95+
var emailChunk = bccEmails.slice(j * maxEmails, (j + 1) * maxEmails);
96+
var messageNum = j + 1;
97+
var messageCountText = "";
98+
99+
// If there are more than 50 email recipients then send a special message
100+
if (batchCount > 1) {
101+
messageCountText = "\nGoogle has a limit of " + maxEmails + " email addresses per message so " + batchCount + " drafts have been created.\nThis is draft " + messageNum + " of " + batchCount + "."
102+
}
103+
104+
var fullMessage = "------------DELETE BEFORE SENDING------------" + messageCountText + "\n\nMESSAGE BEING SENT FOR:\n" + studentNames.join('\n') + "\n\n------------DELETE BEFORE SENDING------------\n\n\n" + emailBody;
105+
106+
// Create the Gmail draft
107+
var draft = GmailApp.createDraft("", "", fullMessage, {bcc: emailChunk.join(',')});
108+
}
109+
110+
// Populate the next column with the message that was sent
111+
for (var i = 1; i < data.length; i++) {
112+
var sendEmail = data[i][0]; // Get status of checkbox in the first column
113+
114+
if (sendEmail == true) {
115+
var cell = sheet.getRange(i + 1, messageColumnIndex + 1);
116+
cell.setValue(emailBody); // Paste the email message sent
117+
118+
// Timestamp
119+
var cell = sheet.getRange(i + 1, doneColumnIndex + 1); // This will create a cell object based on the row/column coordinates for the status cell
120+
cell.setValue(currentDate); // Set status message for parents already emailed
121+
}
122+
}
123+
Logger.log('Draft created with BCC: ' + bccEmails.join(', '));
124+
SpreadsheetApp.getUi().alert('GMAIL DRAFT CREATED!\n\nCheck your Deltalearns Gmail DRAFTS folder\nto complete and send your message.\n\nBY: JONATHAN KUNG');
125+
}
126+
// If user is not ready to send the message.
127+
else {
128+
ui.alert('Cancelled.');
129+
Logger.log('User cancelled the message send.')
130+
}
131+
resetCheckboxes();
132+
}
133+
else { // If no students are checked, send alert and don't send anything.
134+
Logger.log('No checkboxes selected.');
135+
SpreadsheetApp.getUi().alert('No checkboxes selected.');
136+
}
137+
}
138+
139+
140+
//// DELETE DATESTAMP AND MESSAGE COLUMNS
141+
function resetStatus() {
142+
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
143+
var data = sheet.getDataRange().getValues();
144+
var ui = SpreadsheetApp.getUi();
145+
146+
// Ask user if they are sure they want to do this
147+
var response = ui.alert('Are you sure you want to clear the \"Email Sent On\" and \"Email Message\" columns?', ui.ButtonSet.OK_CANCEL);
148+
if (response == ui.Button.OK) {
149+
// Loop through each row (starting from row 2 to skip the header)
150+
for (var i = 1; i < data.length; i++) {
151+
var doneCell = sheet.getRange(i + 1, 5); // Get fifth column with date
152+
var messageCell = sheet.getRange(i + 1, 6) // Get sixth column with message
153+
154+
// Clear the "DONE" message and reset the background color
155+
doneCell.setValue(''); // Clear text
156+
messageCell.setValue('');
157+
}
158+
159+
SpreadsheetApp.getUi().alert('The data will now be cleared.');
160+
Logger.log('The user said YES and the data was reset.')
161+
}
162+
else {
163+
ui.alert('Cancelled.');
164+
Logger.log('The user cancelled the operation.')
165+
}
166+
}
167+
168+
169+
//// RESET ENTIRE SHEET
170+
function resetSheet() {
171+
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
172+
var data = sheet.getDataRange().getValues();
173+
var ui = SpreadsheetApp.getUi();
174+
175+
// Ask user if they are sure they want to do this
176+
var response = ui.alert('Are you sure you want to clear all data on the current sheet?', ui.ButtonSet.OK_CANCEL);
177+
if (response == ui.Button.OK) {
178+
// Loop through each row (starting from row 2 to skip the header)
179+
for (var i = 1; i < data.length; i++) {
180+
var nameCell = sheet.getRange(i + 1, 2) // Get name column
181+
var emailCell = sheet.getRange(i + 1, 3) // Get email column
182+
var emailCellOther = sheet.getRange(i + 1, 4) // Get other email column
183+
var doneCell = sheet.getRange(i + 1, 5); // Get date column
184+
var messageCell = sheet.getRange(i + 1, 6) // Get message column
185+
var notesCell = sheet.getRange(i + 1, 7) // Get notes column
186+
187+
// Clear everything
188+
nameCell.setValue('');
189+
emailCell.setValue('');
190+
emailCell.setBackground(null);
191+
emailCellOther.setValue('');
192+
emailCellOther.setBackground(null);
193+
doneCell.setValue('');
194+
messageCell.setValue('');
195+
notesCell.setValue('');
196+
}
197+
resetCheckboxes();
198+
199+
SpreadsheetApp.getUi().alert('The data will now be cleared.');
200+
Logger.log('The user said YES and the sheet was reset.')
201+
}
202+
else {
203+
ui.alert('Cancelled.');
204+
Logger.log('The user cancelled the operation.')
205+
}
206+
}
207+
208+
209+
//// SELECT ALL ROWS
210+
function selectAll() {
211+
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
212+
var data = sheet.getDataRange().getValues();
213+
214+
// Loop through each row (starting from row 2 to skip the header)
215+
for (var i = 1; i < data.length; i++) {
216+
var checkboxCell = sheet.getRange(i + 1, 1); // Get first column with checkboxes
217+
if (data[i][2] !== "" || data[i][3] !== "") { // Test to see if there are emails in the cells
218+
// Clear the checkboxes
219+
checkboxCell.setValue(true);
220+
}
221+
}
222+
}
223+
224+
225+
//// DESELECT ALL ROWS
226+
function deselectAll() {
227+
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
228+
var data = sheet.getDataRange().getValues();
229+
230+
// Loop through each row (starting from row 2 to skip the header)
231+
for (var i = 1; i < data.length; i++) {
232+
var checkboxCell = sheet.getRange(i + 1, 1); // Get first column with checkboxes
233+
checkboxCell.setValue(false);
234+
}
235+
}
236+
237+
238+
//// SET UP THE MENU
239+
function onOpen() {
240+
var ui = SpreadsheetApp.getUi();
241+
// Add a custom menu with an option to run the script
242+
ui.createMenu('EMAIL TOOLS')
243+
.addItem('Email Selected Rows', 'createDraftWithBcc')
244+
.addItem('Select All Rows', 'selectAll')
245+
.addItem('Deselect All Rows', 'deselectAll')
246+
.addItem('Clear \"Email Sent On\" and \"Email Message\" Columns', 'resetStatus') // Add "Reset Email Sent On Column" option
247+
.addItem('Clear All Data', 'resetSheet') // Reset the current sheet
248+
.addToUi();
249+
}

0 commit comments

Comments
 (0)