can you please tell me, how to change code to run script only on specified sheet? I want to send e-mails if some value in 2nd column of specified sheet will change. Currently it is sending e-mails if I change 2nd column in any sheet.
I have tried code below, but didn't work:
var sheet = SpreadsheetApp.getActiveSpreadsheet();
SpreadsheetApp.setActiveSheet(sheet.getSheetByName('sheetname'))
This is code I have:
function sendNotification() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var mycell = ss.getActiveSelection();
var cellcol = mycell.getColumn();
var row = sheet.getActiveRange().getRow();
var cellvalue = mycell.getValue().toString();
var recipients = "email#email.com";
if (cellcol == 2)
{
var subject = 'Update to '+sheet.getName();
var body = sheet.getName() + ' has been updated. Visit ' + ss.getUrl() + ' to view the changes on row: «' + row + '». New comment: «' + cellvalue + '»';
MailApp.sendEmail(recipients, subject, body);
}
}
Thank you.
Related
I have a form that contains 84 questions, not all of them are mandatory.
This is the script I manage to write so far:
function SendEmail() {
var ActiveSheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var StartRow = 2;
var RowRange = ActiveSheet.getLastRow() - StartRow + 1;
var WholeRange = ActiveSheet.getRange(StartRow,1,RowRange,84);
var AllValues = WholeRange.getValues();
var message = "";
for (i in AllValues) {
var CurrentRow = AllValues[i];
var EmailSent = CurrentRow[85];
if (EmailSent == "Sent")
continue;
# I know this part takes only the first 5 column, I wrote them only as an example. In bold the headers of each column.
message =
"<p><b>Kind of content: </b>" + CurrentRow[2] + "</p>" +
"<p><b>Project Name: </b>" + CurrentRow[3] + "</p>" +
"<p><b>Project Description: </b>" + CurrentRow[4] + "</p>" +
"<p><b>Name of your team: </b>" + CurrentRow[5] + "</p>" +
"<p><b>Scope of work: </b>" + CurrentRow[6] + "</p>";
var setRow = parseInt(i) + StartRow;
ActiveSheet.getRange(setRow, 85).setValue("sent");
}
var SendTo = "email#gmail.com";
var Subject = "New"+" " + CurrentRow[2] +" "+"project request";
MailApp.sendEmail({
to: SendTo,
cc: "",
subject: Subject,
htmlBody: message,
});
}
What I want is to send an email every time somebody fills the form and the content of the email should include only the last row and only the columns with data with their header.
The way this script is written will generate an email with 84 rows, most of them empty and not relevant. Can somebody give me a hand with it?
Thank you so much for your help!!
You can use sheet.getLastRow() to get the index of the last row in the sheet that has data.
For finding columns that have data, you can iterate through the row data and look for cell values that are not blank.
var header = sheet
.getRange(1,1,1,sheet.getLastColumn())
.getDisplayValues()[0];
var data = sheet
.getRange(sheet.getLastRow(),1,1,sheet.getLastColumn())
.getDisplayValues()[0];
var output = [];
for (var d=0; d<data.length; d++) {
if (data[d] !== "") {
output.push(header[d] + " = " + data[d]);
}
}
return data.join("\n");
I know you are too naive to coding and Amit is a busy person, so just to help you, I am plugging in the code he has provided to your code with a small correction, so you can just copy the entire code :)
function SendEmail() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var lRow = sheet.getLastRow();
var emailSent = sheet.getRange(lRow, 86).getValue();
var header = sheet
.getRange(1,1,1,sheet.getLastColumn())
.getDisplayValues()[0];
if (emailSent != "Sent"){
var data = sheet
.getRange(lRow,1,1,sheet.getLastColumn())
.getDisplayValues()[0];
var output = [];
for (var d=0; d<data.length; d++) {
if (data[d] !== "") {
output.push(header[d] + " = " + data[d]);
}
}
var message = output.join("\n");
var SendTo = "email#gmail.com";
var Subject = "New"+" " + sheet.getRange(lRow, 3).getValue() +" "+"project request";
MailApp.sendEmail({
to: SendTo,
cc: "",
subject: Subject,
htmlBody: message,
});
sheet.getRange(lRow, 86).setValue("sent");
}
}
You can use filter, for example
var AllValues = WholeRange.getValues().filter( row => row[5] != '');
will reduce AllValues to only those there column 6 isn't empty
I have Google Apps Script which inputs events into my google calendar from a spreadsheet. Anyone know how to have the script set a row's background color to green & last column value to "complete" only if it's been ran through the loop?
Currently I have it just setting the full range to these parameters, but would like to prevent certain rows from being included if the last column is equal to "Invalid".
function inputEvents() {
var spreadsheet = SpreadsheetApp.getActiveSheet();
var calendarId = spreadsheet.getRange("B1").getValue();
var calendar = CalendarApp.getCalendarById(calendarId)
var lr = spreadsheet.getLastRow();
var count = spreadsheet.getRange("A3:AF"+lr+"").getValues();
for (x=0; x<count.length; x++) {
var events = count[x];
var name = events[2];
var phone = events[3];
var email = events[4];
var title = events[5];
var startTime = events[6];
var endTime = events[7];
var description = events[8];
var location = events[9];
var eventId = events[31];
var contactHeader = "CONTACT:";
var descriptionHeader = "DESCRIPTION:";
var complete = "Complete";
var invalid = "Invalid";
var info =
contactHeader.bold() + "\n"
+ name + "\n"
+ phone + "\n"
+ email + "\n"
+ "\n" + descriptionHeader.bold() + "\n"
+ description;
var options = {
'guests' : email,
'description': info,
'sendInvites': 'True',
'location': location,
}
if (eventId != complete && eventId != invalid){
calendar.createEvent(title, startTime, endTime, options);
spreadsheet.getRange("AF3:AF"+lr+"").activate().setValue('Complete');
spreadsheet.getRange("A3:AF"+lr+"").activate().setBackground('#d9ead3');
}
}
}
You're using the setValue and setBackground methods to the entire range, you need to apply them only to the range you're interested in, try setting a currentRow variable and change the range you're getting inside your if statement, like this:
var currentRow = 3 + x;
if (eventId != complete && eventId != invalid){
calendar.createEvent(title, startTime, endTime, options);
spreadsheet.getRange("AF" + currentRow).setValue('Complete');
spreadsheet.getRange("A"+ currentRow + ":AF" + currentRow).setBackground('#d9ead3');
}
So I have this google script function that reads information from a google spreadsheet and sends an email with the data. I set up a time-based trigger that activates every day at a certain hour but the problem is that every time it triggers the script ask for authorization so basically what I'm receiving is the email with this "time-based" error that asks for authorization.
The function self-works perfectly when I manually execute it and confirm the authorization myself.
I set up the time-based trigger via code and the trigger option of the scripts but none of them seems to work.
Do you guys know a way to always keep the authorization on so the trigger can work and send the email with the data?
so to add some additional information here, this is the code I'm using right now:
The spreadsheet is shared between two people, me and a co-worker.
If I manually execute this script, it will ask for authorization and then send to my email the data I need. My problem comes when I tried to set up a trigger to automatically execute this script. Every time the trigger execute the script I get an email saying that it needs authorization.
Function: emailCarts
Error Message: Authorization is required to perform this action. Activation: Time-Based
function emailCharts(sheet,emails,emailSubject){
var ss = SpreadsheetApp.openById("SPREADSHEET_ID");
var sheet = SpreadsheetApp.openById("SPREADSHEET_ID").getSheetByName("Graficos");
var emailSubject = 'Reporte Automático Reclamos y Sugerencias ' + Utilities.formatDate(sheet.getRange("B2").getValue(),ss.getSpreadsheetTimeZone(),"dd/MM/yy");
var emails = 'MY_EMAIL'; // your email ID
var charts = sheet.getCharts();
var sheet2 = SpreadsheetApp.openById("SPREADSHEET_ID").getSheetByName("Tabla");
var schedRange = sheet2.getDataRange();
var body = '<div style="text-align:left;display: inline-block;font-family:
arial,sans,sans-serif">'
body += '<H1>'+ 'Reclamos Abiertos ' +'</H1>';
body += getHtmlTable(schedRange);
body += '</div><br>';
debugger;
if(charts.length==0){
MailApp.sendEmail({to: emails,subject: "ERROR:"+emailSubject,htmlBody: "No hay
gráficos en el spreadsheet"});
return;
}
var chartBlobs = new Array(charts.length);
var emailBody = "Estimados,<br><br> Junto con saludar, se hace envío del reporte
automático de los Reclamos/Sugerencias/Felicitaciones Abiertos y Cerrados,
correspondiente a la fecha: "
+ Utilities.formatDate(sheet.getRange("B2").getValue(),ss.getSpreadsheetTimeZone(),"dd/MM/yy");
var emailImages = {};
for(var i=0;i<charts.length;i++){
var builder = charts[i].modify();
builder.setOption('vAxis.format', '#');
var newchart = builder.build();
chartBlobs[i] = newchart.getAs('image/png');
emailBody = emailBody + "<p align='center'><img src='cid:chart"+i+"'></p>";
emailImages["chart"+i]= chartBlobs[i];
}
for (var i = 0; i < emails.length; i++){
MailApp.sendEmail({to: emails[i], subject: emailSubject, htmlBody: emailBody+body, inlineImages: emailImages});
}
}
function getHtmlTable(range){
var ss = range.getSheet().getParent();
var sheet = range.getSheet();
startRow = range.getRow();
startCol = range.getColumn();
lastRow = range.getLastRow();
lastCol = range.getLastColumn();
// Read table contents
var data = range.getValues();
// Get css style attributes from range
var fontColors = range.getFontColors();
var backgrounds = range.getBackgrounds();
var fontFamilies = range.getFontFamilies();
var fontSizes = range.getFontSizes();
var fontLines = range.getFontLines();
var fontWeights = range.getFontWeights();
var horizontalAlignments = range.getHorizontalAlignments();
var verticalAlignments = range.getVerticalAlignments();
// Get column widths in pixels
var colWidths = [];
for (var col=startCol; col<=lastCol; col++) {
colWidths.push(sheet.getColumnWidth(col));
}
// Get Row heights in pixels
var rowHeights = [];
for (var row=startRow; row<=lastRow; row++) {
rowHeights.push(sheet.getRowHeight(row));
}
// Future consideration...
var numberFormats = range.getNumberFormats();
// Build HTML Table, with inline styling for each cell
var tableFormat = 'style="border:1.5px solid black;border-collapse:collapse;text- align:center" border = 1.5 cellpadding = 5';
var html = ['<table '+tableFormat+'>'];
// Column widths appear outside of table rows
for (col=0;col<colWidths.length;col++) {
html.push('<col width="'+colWidths[col]+'">')
}
// Populate rows
for (row=0;row<data.length;row++) {
html.push('<tr height="'+rowHeights[row]+'">');
for (col=0;col<data[row].length;col++) {
// Get formatted data
var cellText = data[row][col];
if (cellText instanceof Date) {
cellText = Utilities.formatDate(
cellText,
ss.getSpreadsheetTimeZone(),
"dd/MM/yy");
}
var style = 'style="'
+ 'color: ' + fontColors[row][col]+'; '
+ 'font-family: ' + fontFamilies[row][col]+'; '
+ 'font-size: ' + fontSizes[row][col]+'; '
+ 'font-weight: ' + fontWeights[row][col]+'; '
+ 'background-color: ' + backgrounds[row][col]+'; '
+ 'text-align: ' + horizontalAlignments[row][col]+'; '
+ 'vertical-align: ' + verticalAlignments[row][col]+'; '
+'"';
html.push('<td ' + style + '>'
+cellText
+'</td>');
}
html.push('</tr>');
}
html.push('</table>');
return html.join('');
}
Is there a way to make the output of 'message' in the email neater?
Right now, it's just 1 line of long data sent to the user. I tried using <br> but it didnt seem to work.
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getDataRange();
var data = range.getValues();
setUpCalendar_(data, range);
var message = "";
for (i in data) {
var row = data[i];
var subject = "Compiled List for " + row[0];
message += row[0] + row[1] + row[2] + row[3];
}
MailApp.sendEmail("emailgoeshere", subject, message);
}
As mentioned in the comment above, this has already been explained a few times...
below is an example that sends data in text format AND in html format so that recipients that reject html content will still see something readable ;-)
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getDataRange();
var data = range.getValues();
setUpCalendar_(data, range);
var txt = "";
var html = '<table style="background-color:lightblue;border-collapse:collapse;" border = 1 cellpadding = 5><tr>'
for (i in data) {
var row = data[i];
var subject = "Compiled List for " + row[0];
txt += row[0] +' - '+ row[1] +' - '+ row[2] +' - '+ row[3]+'\n';
html+= '<td>'+row[0] +'</td><td>'+ row[1] +'</td><td>'+ row[2] +'</td><td>'+ row[3] +'</td></tr><tr>';
}
html += '</tr></table>';
MailApp.sendEmail('an email adress', subject, txt,{'htmlBody':html});
}
Change the background color to your taste
Try using \n to start a new line
function gamEmail(e) {
var sheet = SpreadsheetApp.getActiveSheet();
var lastRow = sheet.getLastRow();
var first = sheet.getRange(lastRow, getColIndexByName("First Name")).getValues()[0];
var nickName = sheet.getRange(lastRow, getColIndexByName("Preferred Name")).getValues()[0];
if (nickName.isBlank() == true)
{var name = first;}
else
{name = nickName;}
var last = sheet.getRange(lastRow, getColIndexByName("Last Name")).getValues()[0];
var mobile = sheet.getRange(lastRow, getColIndexByName("Mobile Phone")).getValues()[0];
var office = sheet.getRange(lastRow, getColIndexByName("Office")).getValues()[0];
var subject = "**GAM New User**" + " " + name + " " + last;
this script sets up a GAM command line for new users, the name variable needs to be the new users first name unless they have a nickName. Then I need to set the name variable to nickName. I can't seem to find an answer. Any suggestions? thanks in advance.