google script column change email notification - email

This is my first attempt at writing any kind of script, and also posting a question.
I have created a google sheet, and I would like to send an e-mail notification every time a row is added in this spreadsheet (or to keep things simple, every time a new cell is populated in column A).
I've been searching these forums for a couple of hours, and put together the following script, and tried installing both "onedit" & "onchange" triggers in google scripts but nothing working.
The following links have been helpful, but still not able to get the result I want. No notification is being triggered at all automatically upon the relevant edits.
how to attach onChange cell value event/script to google sheet
email notification if cell is changed
//Open function
function sendNotification() {
//Get spreadsheet & sheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
//Define notification details
var recipients = "myname#email.com";
var subject = "New lead";
var body = 'A new lead has been added to Simba. For message: ' + message + '';
//Specify several sheet variables
var cell = ss.getActiveCell().getA1Notation();
var row = sheet.getActiveRange().getRow();
var cellvalue = ss.getActiveCell().getValue().toString();
var message = '';
//Specify if statement
if(cell.indexOf('A')!=-1){
message = sheet.getRange('B'+ sheet.getActiveCell().getRowIndex()).getValue()
}
//Send the Email
MailApp.sendEmail(recipients, subject, body);
//Close function
};

var body = 'A new lead has been added to Simba. For message: ' + message + '';
At this line, "message" is undefined. It occurs an error. By this error, mail cannot be sent. Because the definition of "message" is below from this line. So please change this line to below
message = sheet.getRange('B'+ sheet.getActiveCell().getRowIndex()).getValue()
And please install a trigger for this function. The method of installing trigger is shown at your reference URL.

Related

How to send a conditional email based on the value of a cell from a form response?

I have a formula that calculates a number based on the response from a google form. Depending on what this number I want to send an email using details from the from as well as a pre typed email in another cell.
In Col1 is a time stamp, in col14 is an employee start date. My formula in Col33 works out how many days they have been employed at the time of submitting the form.
I want to send an email to the person if the number of days is less than 182.
I have an email pre typed out and can place this anywhere. At the moment I have it in all cells in col36. The email address will be in column32.
I have tried a number of different codes and none of them are sending the email no matter what the trigger I have set up is. I have very basic knowledge on apps script so my current code might be completely wrong, but it should show roughly what I'm getting at.
function sendEmail() {
var values = SpreadsheetApp.getActiveSheet().getDataRange().getValues()
for (i in values.length) {
var data = values[i][33];
var emailAddress = values[i][32];
var message = values[i][36];
if (data < 182); {
MailApp.sendEmail(emailAddress, "Flexible Working Request", message);
}
}
}
The current results have just been deleting the data in col33, Col34 & Col36 on the new form response row only.
Sorry if this question has been answered elsewhere, any other answer I found to similar issues I could not get to work.
I got someone who is much better at google apps script at work to give me a hand
It is to do with google forms pushing down formulas to the side
So we had to move the formula calculating the number of days to another sheet and then used this formula which worked
function sendEmailv2() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Form responses
1');
var scrip = Session.getScriptTimeZone();
var date = sheet.getRange(sheet.getLastRow(),14).getValue();
var sub = sheet.getRange(sheet.getLastRow(),1).getValue();
Logger.log(date);
var fortmat = Utilities.formatDate(new Date(date), scrip, "dd/MM/yyyy");
var Subfortmat = Utilities.formatDate(new Date(sub), scrip, "dd/MM/yyyy");
var emailAddress = sheet.getRange(sheet.getLastRow(),32).getValue();
var sheet2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet4');
var message = sheet2.getRange(1,1).getValue();
var days = sheet2.getRange(sheet2.getLastRow(),2).getValue();
if (days<182){
MailApp.sendEmail(emailAddress, "Flexible Working Request", message,{noReply:true});
}
}
Thanks!
You don’t need to go over all the columns to get a single cell value, so there is no need for a for loop. You can do it directly with:
var sheet = SpreadsheetApp.getActiveSheet().getSheets[0];
var cell = ["A33"];
var days_value = sheet.getRange(cell).getValue();
Then you can just make an if condition to send the email:
if (days_value < 182){
MailApp.sendEmail(emailAddress, "Flexible Working Request", message);
}
Hope this helps

Generate and send pdf through Google Forms to my email address - doesn't send, debugging to no assitance

I'm trying to send myself a form-based report as a pdf. The problem is, I don't receive any emails. Debugging doesn't help much, since that only tells me which values are "undefined" (they are being defined the instant one fills out the form and triggers the email by clicking send; in theory). My coding experience stems from the days of TurboPascal and .bat-files, and I have lately realised I need to shape up. Trying to figure out Android, and this is a little experiment at work. But I had forgotten the lost feeling of "what now?"...
Here's the code:
// Samfunnsutvikling kursrapport
var docTemplate = "TemplateIDinGoogleDoks";
var docName = "Kursrapport";
// When Form Gets submitted
function onFormSubmit(e) {
//Get information from form and set as variables
var email = "worker#work.no";
var namn = e.namedvalues.namn;
var arrangement = e.namedvalues.arrangement;
var dato = e.namedvalues.dato;
var referat = e.namedvalues.referat;
// Get document template, copy it as a new temp doc, and save the Doc’s id
var copyId = DocsList.getFileById(docTemplate)
.makeCopy(docName+' for '+namn)
.getId();
// Open the temporary document
var copyDoc = DocumentApp.openById(copyId);
// Get the document’s body section
var copyBody = copyDoc.getActiveSection();
// Replace place holder keys,in our google doc template
copyBody.replaceText('keynamn', namn);
copyBody.replaceText('keyarrangement', arrangement);
copyBody.replaceText('keydato', dato);
copyBody.replaceText('keyreferat', referat);
// Save and close the temporary document
copyDoc.saveAndClose();
// Convert temporary document to PDF
var pdf = DocsList.getFileById(copyId).getAs("application/pdf");
// Attach PDF and send the email
var subject = "Kursrapport";
var body = "Kursrapporten frå " + namn + "";
GmailApp.sendEmail(email, subject, body, {htmlBody: body, attachments: pdf});
// Delete temp file
DocsList.getFileById(copyId).setTrashed(true);
}
The script/document is authorized to send emails, but, oddly, I had to authorize it twice. It is saved.
In general, you can add Logger.log() to print variable values or just messages to see how far does it reach.
It looks as attachments parameter expects Blob[] type, however you are passing just Blob. So, it should be:
GmailApp.sendEmail(email, subject, body, {htmlBody: body, attachments: [pdf]});
You may also want to replace DocsList with DriveApp class as-is since the first one is depricated.
Update
It turned out also that getActiveSection() was renamed to getBody().

How to trigger an email notification when cell value is modified by function

I would like to create a Google Sheets with event triggers. I'm using Google Apps Script.
I succeeded, thanks to Stack Overflow, to create a Google Sheets with an automatic mail notification when a cell is modified by a user.
Now I would like to know if this is possible when cell is modified by a function (not user's modification), such as :
if (today() >= B3 ; "late" ; "not late")
The function checks date, and give result "late" or "not late".
When deadlines are reached, the function would return "late" and a mail would be sent to warn me. The body mail would have the value of the cell in the B, D and E column and in the same row of the cell modified (I know how to do this using e.source, getRange and getRow)
So far, i've tried this, but it's not working
function sendNotification(e) {
if("F" == e.range.getA1Notation().charAt(0)) {
if(e.value == "Late") {
//Define Notification Details
var recipients = "user#example.com";
var subject = "Deadlines" ;
var body = "deadline reached";
//Send the Email
MailApp.sendEmail(recipients, subject, body);
}
}
}
How can I set up mail notifications when cells in F column have the "late" value (with "late" being the result of a function) ?
You can use a simple script that runs on a timer trigger and checks for any modification in a specific column in your sheet.
I use script like that for a lot of tasks, including calendar and sheets monitoring.
Below is a test code that works on column F, you have to run it once manually to create the scriptProperties value that I use to detect changes.
Then create a time trigger to run it every hour or any other timer value you find useful.
The only issue would be if you have a very long sheet, you could reach the length limit of the properties... (right now I don't remember the max length, will have to check ;-)
Code :
function checkColumnF() {
var sh = SpreadsheetApp.getActiveSheet();
var values = sh.getRange('F1:F').getValues().join('-');
if(PropertiesService.getScriptProperties().getKeys().length==0){ // first time you run the script
PropertiesService.getScriptProperties().setProperty('oldValues', values);
return;
}
var oldValues = PropertiesService.getScriptProperties().getProperty('oldValues').split('-');
var valuesArray = values.split('-');
while (valuesArray.length>oldValues.length){
oldValues.push('x'); // if you append some rows since last exec
}
Logger.log('oldValues = '+oldValues)
Logger.log('current values = '+valuesArray)
for(var n=0;n<valuesArray.length;n++){
if(oldValues[n] != valuesArray[n]){ // check for any difference
sendMail(n+1,valuesArray[n]);
}
}
PropertiesService.getScriptProperties().setProperty('oldValues', values);
}
function sendMail(row,val){
Logger.log('value changed on row '+row+' value = '+val+' , mail sent');
// uncomment below when you are sure everything runs fine to avoid sending dozens of emails while you test !
//MailApp.sendEmail(Session.getActiveUser().getEmail(),'value changed in your sheet','Row '+row+' is now '+val);
}

google apps script to create new pdf document of updated cells after form submission and email this pdf error message:

Please bear with me as I am very much a beginner at this. I am trying to write a Google script which creates a new spreadsheet of the relevant data after a form is submitted, converts this to a PDF, and sends it as an email attachment to an email address which is submitted to the form. I am writing the code in a script which is bound to the sheet which performs some calculations on the data once it is submitted. The form is also bound to the sheet. I will paste my code below and here is a link to the sheet:
https://docs.google.com/spreadsheets/d/1oQTeQFwl7IfWF8D17oK1Mutp4TXidQXUT4lv46ktuwM/edit?usp=sharing
I am trying to email the small green summary section on the sheet named INPUTS/OUTPUTS as a pdf.
The Template file "MyCalculations" is just an empty spreadsheet apart from one line saying "here are your calculation results".
The summary section updates itself well and correctly after a form is submitted I am just having real trouble accessing the sheet because I can't code!
Here is the code so far:
function onFormSubmit(e){
//Variables
var userEmail = SpreadsheetApp.getActiveSheet().getRange("H24").getValue();
var totalOutstandingPrincipalDebt = SpreadsheetApp.getActiveSheet().getRange("G22").getValue();
var totalOutstandingInterest = SpreadsheetApp.getActiveSheet().getRange("H22").getValue();
var totalOutstandingCompensation = SpreadsheetApp.getActiveSheet().getRange("I22").getValue();
var dailyInterestRate = SpreadsheetApp.getActiveSheet().getRange("J22").getValue();
var grandTotal = SpreadsheetApp.getActiveSheet().getRange("G23").getValue();
var docTemplate = DriveApp.getFilesByName("MyCalculations");
//Template Info
var docName="Calculations";
var copyDoc= docTemplate.makeCopy();
var copyId = copyDoc.getId();
var copyBody = docTemplate.getActiveSection();
copyBody.getRange(2, 1).setValue("Total Outstanding Principal Debt");
copyBody.getRange(2, 2).setValue("Total Outstanding Interest");
copyBody.getRange(2, 3).setValue("Total Outstanding Compensation");
copyBody.getRange(2, 4).setValue("Grand Total");
copyBody.getRange(2, 5).setValue("Daily Interest Rate");
copyBody.getRange(3, 1).setValue(totalOutstandingPrincipalDebt);
copyBody.getRange(3, 2).setValue(totalOutstandingInterest);
copyBody.getRange(3, 3).setValue(totalOutstandingCompensation);
copyBody.getRange(3, 4).setValue(grandTotal);
copyBody.getRange(3, 5).setValue(dailyInterestRate);
//Save as PDF and send e-mail
var pdf = getFileById(copyId).getAs("application/pdf");
var subject = "Calculations";
var body = "Thank you very much for using our online calculator. Please find your results attached.";
MailApp.sendEmail(userEmail, subject, body, {htmlBody: body, attachments: pdf});
//Deletes temporary Document
DriveApp.getFileById(copyId).setTrashed(true);
}
I also don't think that in this code, I have specified which sheet on my spreadsheet I am wanting to get the data from, but I don't know how to do that either!
Any help would be so so appreciated!
var docTemplate = DriveApp.getFilesByName("MyCalculations");
getFilesByName returns a FileIterator not a Spreadsheet so you have to change that to:
var docTemplate = DriveApp.getFilesByName("MyCalculations").next().getAs(MimeType.GOOGLE_SHEETS);
Next, in var copyBody = docTemplate.getActiveSection(); there is no such method called getActiveSection change that to:
var copyBody = docTemplate.getActiveSheet();
Lastly, the line var pdf = getFileById(copyId).getAs("application/pdf");
should be
var pdf = DriveApp.getFileById(copyId).getAs("application/pdf");
Implement those changes and let me know how it works. =)
Update
I fiddled around and as far as I can tell, DriveApp automatically converts almost all files to a PDF. So, as I understand it, you are using the MyCalculations spreadsheet as a template so that you can convert it into a PDF and send it.
We can accomplish this with a little bit of a roundabout way.
First, we create a new sheet in our original spreadsheet, and hide it from view so that the user can't see it.
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var myCalculations = spreadsheet.insertSheet("MyCalculations",spreadsheet.getNumSheets());
myCalculations.hideSheet();
Secondly, we set all the values that you want. So change
copyBody.setRange ...
to
myCalculations.setRange ...
Thirdly, once we have all our data set. We are going create a temporary Spreadsheet to copy all our data into so that we may export it as a PDF and send it in an email
var tempSpreadsheet = SpreadsheetApp.create('Temporary');
Fourth, we copy our calculations page into the temporary spreadsheet.
myCalculations.copyTo(tempSpreadsheet);
Perfect! Now we just convert the temporary spreadsheet into a PDF and do a little clean-up. Be sure to note the change to the line where we delete the temporary spreadsheet. I get the id by just calling the getId() method
var pdf = tempSpreadsheet.getAs(MimeType.PDF);
var subject = "Calculations";
var body = "Thank you very much for using our online calculator. Please find your results attached.";
MailApp.sendEmail(userEmail, subject, body, {htmlBody: body, attachments: pdf});
//Deletes temporary Document
DriveApp.getFileById(tempSpreadsheet.getId()).setTrashed(true);
That should do the trick. Comment how it works for you. =)
I managed to get this code working:
//Set out global variables
var docTemplate = ("1Ff3SfcXQyGeCe8-Y24l4EUMU7P9TsgREsAYO9W6RE2o");
var docName=("Calculations");
function onFormSubmit(e){
//Variables
var userEmail = SpreadsheetApp.getActiveSheet().getRange("H24").getValue();
var totalOutstandingPrincipalDebt =SpreadsheetApp.getActiveSheet().getRange("G22").getValue();
var totalOutstandingInterest = SpreadsheetApp.getActiveSheet().getRange("H22").getValue();
var totalOutstandingCompensation = SpreadsheetApp.getActiveSheet().getRange("I22").getValue();
var dailyInterestRate = SpreadsheetApp.getActiveSheet().getRange("J22").getValue();
var grandTotal = SpreadsheetApp.getActiveSheet().getRange("G23").getValue();
//Template Info
var copyId=DriveApp.getFileById(docTemplate).makeCopy(docName+' for '+userEmail).getId();
var copyDoc = DocumentApp.openById(copyId);
var copyBody = copyDoc.getActiveSection();
//Putting the data into the file
copyBody.insertParagraph(0,'Total Outstanding Principal Debt: ' + totalOutstandingPrincipalDebt);
copyBody.insertParagraph(1,'Total Outstanding Interest: '+ totalOutstandingInterest );
copyBody.insertParagraph(2,'Total Outstanding Compensation: '+ totalOutstandingCompensation);
copyBody.insertParagraph(3,'Grand Total: ' + grandTotal);
copyBody.insertParagraph(4,'Daily Interest Rate: '+ dailyInterestRate);
copyDoc.saveAndClose();
//email pdf document as attachment
var pdf = DriveApp.getFileById(copyId).getAs("application/pdf");
var subject = "Calculations";
var body = "Thank you very much for using our online calculator. Please find your results attached.";
MailApp.sendEmail(userEmail, subject, body, {htmlBody: body, attachments: pdf});
//Deletes temporary Document
DriveApp.getFileById(copyId).setTrashed(true);
}

How to copy paste a google spreadsheet table into gmail using google script?

I have a google spreadsheet with a pivot table, which i want to be emailed automatically based on certain criteria using my gmail. I am quite happy with the email script and the cinditions however I cannot find anywhere a script that can effectively replicate a "copy - paste" of the table into the email.
I would appreciate any help you could offer with this.
Thanks
Agi
I managed to get it to work using advice from this community. Thank you!
I am trying to get it to display values horizontally i.e. each line a new customer record. However, i get something different. I am attaching a file with what I get and the code. I would appreciate any advice. I am so sure that the solution is just there but after many hours I cannot get it :( I am showing the code below and I am attaching a photo with the current and desired outcome.
Many thanks
Agi
function testMail(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var responses = ss.getSheetByName("Monitoreo de Pedidos");
// var lastRow = responses.getLastRow();
// var values = responses.getRange("A2"+(lastRow)+":R2"+(lastRow)).getValues();
var values = responses.getRange("A3:R12").getValues();
var headers = responses.getRange("A2:R2").getValues(); //The headers. A1 TO R1 does not contain relevant data
var message = composeMessage (headers,values);
var messageHTML = composeHtmlMsg(headers,values);
Logger.log(messageHTML);
MailApp.sendEmail(Session.getEffectiveUser().getEmail(),'test html', message,{'htmlBody':messageHTML});
}
function composeMessage(headers,values){
var message = 'Here are the data you submitted :\n'
for (var j=0;j<5;++j){ //NUMBER OF ROWS
for(var c=0;c<values[0].length;++c){ //NUMBER OF COLUMNS, in the future this will be dynamic
message+='\n'+headers[0][c]+' : '+values[j][c]
}
}
return message;
}
function composeHtmlMsg(headers,values){
var message = 'Here are the data you submitted :<br><br><table style="background- color:yellow;border-collapse:collapse;" border = 1 cellpadding = 5><th>Title</th> <th>Customer Info</th><tr>'
for (var j=0;j<5;++j){
for(var c=0;c<values[0].length;++c){
message+='<tr><td>'+headers[0][c]+'</td><td>'+values[j][c]+'</td></tr>'
}
}
return message+'</table>';
![Desired outcome][1]}
You need to write the email body as html and insert the in there. More work if you want to mimic formatting. Try if and write back if you get stuck.