Google Script Time-Based Trigger -> Asking for Authorization all the time - javascript

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('');
}

Related

Google Sheet Auto Email Script

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

Script run only on specific sheet

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.

Sending message to Telegram from Google Sheet via Google Scripts

I'm trying to send a telegram message to myself, every morning, with a different quote that I have listed in a Google Sheet. I wrote some code that adds messages to the list, but I can't seem to generate a random row from the list to send daily.
var token = "TOKEN";
var telegramAPI = "https://api.telegram.org/bot" + token;
var webAppAPI = "https://script.google.com/macros/s/GOOGLE_WEB_APP_ADDRESS";
var ssId = "SPREADSHEET_ID";
function getMe() {
var url = telegramAPI + "/getMe";
var response = UrlFetchApp.fetch(url);
Logger.log(response.getContentText());
}
function setWebhook() {
var url = telegramAPI + "/setWebhook?url=" + webAppAPI;
var response = UrlFetchApp.fetch(url);
Logger.log(response.getContentText());
}
function sendText(id,text) {
var url = telegramAPI + "/sendMessage?chat_id=" + id + "&text=" + text;
var response = UrlFetchApp.fetch(url);
Logger.log(response.getContentText());
}
function doGet(e) {
return HtmlService.createHtmlOutput("Test Data" + JSON.stringify(e,null,4));
}
function doPost(e) {
Logger.log(e);
var data = JSON.parse(e.postData.contents);
var text = data.message.text;
var what = data.message.text.split("-")[0]
var who = data.message.text.split("-")[1]
var id = data.message.chat.id;
var name = data.message.chat.first_name;
var response = "Hi " + name + ", this quote has been added to your database: " + text;
sendText(id,response);
SpreadsheetApp.openById(ssId).getSheets()[1].appendRow([new Date(),id,name,text,response,what,who]);
All of this works fine. I added a query that pulls them over to my Quote sheet from my Telegram Feed sheet, that I'll put here to help someone:
=IFERROR(QUERY('Telegram Feed'!$G$1:$G$98,"",-1),"Error")
Now that I'm pulling in quotes, I want to generate a random one from the list and schedule it to send to myself on a daily basis. I've included what I've tried below, but I can't seem to figure out what I'm doing wrong.
The randomizer is partially working, but seems to be grabbing all of the content, which I need to refactor to say something along the lines of:
message = f"{quote} + ' - ' + {author}"
Randomizer:
function randomizer() {
var ssa = SpreadsheetApp.openById(ssId);
var ss = ssa.getSheetByName('Quotes');
var range = ss.getRange(1,1,ss.getLastRow(), 2);
var data = range.getValues();
for(var i = 0; i < data.length; i++)
{
var j = Math.floor(Math.random()*(data[i].length));
var element = data[i][j];
ss.getRange(i+1, 6).setValue(element);
Logger.log(element);
}
}
Up until this point, it mostly works (even though I need to figure out how to fix the randomizer function as mentioned above. It's when I try to send a random message from the script to Telegram that I run into problems.
function sendQuote(what,who) {
var data = randomizer();
var dataJSON = JSON.parse(data.postData.contents);
var url = telegramAPI + "/sendMessage?chat_id=" + 'CHAT_ID_NUM' + "&text=" + what + " - " who;
}
I'm getting nothing back. Anyone know what I'm doing wrong?
EDIT:
I followed the suggestions from Дмитро-Булах & carlesgg97, and I refactored a bunch of my randomize code to give me a quote and author. For some reason, I'm now getting the error "TypeError: Cannot read property "postData" from undefined.: from the line that reads var dataJSON = JSON.parse(data.postData.contents);
Does anyone know why this is happening?
I'll close the issue within 24hrs regardless. Thanks for the help everybody!
function sendQuote(quote,author) {
var data = randomize();
var dataJSON = JSON.parse(data.postData.contents);
var encodedText = encodeURIComponent(quote + " - " + author);
var url = telegramAPI + "/sendMessage?chat_id=" + 'CHAT_ID' + "&text=" + encodedText;
UrlFetchApp.fetch(url);
}
function randomize() {
var sss = SpreadsheetApp.openById(ssId);
var ss = sss.getSheetByName('Quotes');
var length = ss.getLastRow();
var overshoot = 97 //monitor for changes as list size increases
var true_length = length-overshoot;
var line = (Math.random() * ((true_length - 2) + 1)) + 2;
var quote_cell = ss.getRange(line,2);
var quote = quote_cell.getValue();
var author_cell = ss.getRange(line,1);
var author = author_cell.getValue();
Logger.log(quote + " - " + author);
}
Seems like you may be having two different problems:
You are not encoding the text as URL-safe. To safely append data (in this case the text URL Query string parameter) to your URL, you should use encodeURIComponent().
You don't seem to actually be sending the request. Did you miss the UrlFetchApp.fetch() call?
See below an example that fixes both issues:
function sendQuote(what,who) {
var data = randomizer();
var dataJSON = JSON.parse(data.postData.contents);
var encodedText = encodeURIComponent(what + " - " + who);
var url = telegramAPI + "/sendMessage?chat_id=" + 'CHAT_ID_NUM' + "&text=" + encodedText;
UrlFetchApp.fetch(url);
}

Google Sheet two lines cell with getValue()

I made a small script to send text via email from a spreadsheet.
I got the text of the cells using .getValue() but when my cells have two or more lines (Ctrl+enter) it just put them on the same line in the table I'm sending in the email.
I'd like to know if there is a way to keep the GoogheSheet formatting when extracting it with .getValue() or if I need to reprocess the string, and if so, how do I make any RE detect the new line...?
Here is the coding I used to extract the cells:
function readInList(debR, col){
/* Documentation
La routine lit chaque cellule d'un range de 1 col par 5 row et stock les valeurs dans une liste au format texte.
retourne cette liste
*/
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var stopRow = debR + 5;
var opCol = col;
var rangeList = [];
var i;
for (i=debR; i < stopRow; i++){
var cell = sheet.getRange(i, col);
rangeList.push(cell.getValue());
}
return (rangeList);
}
So the Mail sends a reconstructed table with the text, and all of this is inseted inside a html Mail:
function weeklyReport() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var rowMonth = [31,28,31,30,31,30,31,30,31,30,31,30];
var today = new Date();
var todayYear = today.getYear();
var todayMonth = today.getMonth();
var todayDate = today.getDate();
// Calc the number of rows depending of months that have passed
var rowCell=0;
var i = 0;
do {
rowCell+=rowMonth[i];
i++;
} while (i < todayMonth);
rowCell+=3 + todayDate
var range1 = readInListD(rowCell-4, 1);
var range2 = readInList(rowCell-4, 4);
var subject = 'Weekly report Clem Michard';
var greetings = 'Hi, ';
var sentence = 'please find my weekly report below:';
var table = textToTable(range1, range2);
var signature = 'Clem';
var tables = today;
var cmEmail= '***';
var owaEmail = '***';
var headEmail = '***';
var htmlBodyA =
"<html>"+
"<head>"+
"<style>"+
"table, th, td {"+
"border: 1px solid black;"+
"border-collapse: collapse;"+
"}"+
"</style>" +
"</head>"+
"<body>"+
"<p>" + greetings + "</p>"+
"<p>" + sentence + "</p>"+
"<pre>" + table + "</pre>"+
"<p>" + signature + "</p>"+
"</body>"+
"</html>";
/*- Message envoyé aux particpants avec un e-mail valide -*/
MailApp.sendEmail({
to: headEmail,
bcc: cmEmail,
subject: subject,
name: "Clément Michard",
replyTo: cmEmail,
htmlBody: htmlBodyA})
}
And use this to compose the table:
function textToTable(col1, col2){
/*
This method converts a list of str into an HTML table
takes 2 lists to build a table.
*/
var listC1, listC2, text, lLen, i, j;
listC1 = col1;
listC2 = col2;
lLen = listC1.length;
text = "<table><tr><th>" + "Date" + "</th><th>" + "Report" + "</th></tr>";
for (i = 0; i < lLen; i++){
text += "<tr><td>" + listC1[i] + "</td><td>" + listC2[i] + "</td></tr>";
}
text += "</table>";
return(text);
}

Automated duplicate check & bcc using Google Script

I wrote this JS to send email automatically using Google Script into a spreadsheet.
Unfortunately, the duplicate check is not working, and the bcc line trigger an error.
Actually I want to send an email only for the LAST answer into the spreadsheet everytime.
Could you help me?
var EMAIL_SENT = "EMAIL_SENT";
function sendEmails2() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2;
var numRows = active;
var dataRange = sheet.getRange(startRow, 1, numRows, 14)
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var name = row[2];
var surname = row[3];
var salesRepEmail = row[4];
var qualityAnalystEmail = "john#doe.com"
var customerEmail = row[5];
var websiteURL = row[6];
var solution1 = row[7];
var solution2 = row[8];
var solution3 = row[9];
var toResolve1 = row[10];
var toResolve2 = row[11];
var toResolve3 = row[12];
var checkDate = row[13];
var message = 'Bonjour '+ name + ' ' + surname + ', ' + 'blablabla';
var emailSent = row[14]; // Third column
if (emailSent != EMAIL_SENT) { // Prevents sending duplicates
var subject = "Votre Optimisation De Site Mobile pour " +websiteURL;
MailApp.sendEmail(customerEmail, subject, message, {
cc: "",
bcc: qualityAnalystEmail,+ " " + salesRepEmail,
});
sheet.getRange(startRow + i, 15).setValue(EMAIL_SENT);
// Make sure the cell is updated right away in case the script is interrupted
SpreadsheetApp.flush();
}
}
}
Your code is triggering on bcc line cause you put a extra comma. As seen on the documentation, the bcc parameters should be a string with
a comma-separated list of email addresses to BCC
In your cas, you should'nt have:
bcc: qualityAnalystEmail,+ " " + salesRepEmail
but:
bcc: qualityAnalystEmail + ", " + salesRepEmail
which gives:
MailApp.sendEmail(customerEmail, subject, message, {
cc: "",
bcc: qualityAnalystEmail+ ", " + salesRepEmail
});
(You also put a extra comma after your bcc parameters which is not good)
Thank you so much , Please find below the datas and the script.
I will try to call the variables into the HTML afterwards using Google Scriptlet. For the moment, the simple text is sufficient. It seems to be working like that, but the code is not clean.
Image Du Tableau
// This constant is written in column O for rows for which an email
// has been sent successfully.
var EMAIL_SENT = "EMAIL_SENT";
function testSchemas() { {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = sheet.getLastRow();
var numRows = 1; // Number of rows to process
var dataRange = sheet.getRange(startRow, 1, numRows, 15)
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var name = row[2];
var surname = row[3];
var salesRepEmail = row[4];
var qualityAnalystEmail = "xxx#yyy.com"
var customerEmail = row[5];
var websiteURL = row[6];
var solution1 = row[7];
var solution2 = row[8];
var solution3 = row[9];
var toResolve1 = row[10];
var toResolve2 = row[11];
var toResolve3 = row[12];
var checkDate = row[13];
function doGet() {
return HtmlService
.createTemplateFromFile('Index')
.evaluate();
}
Logger.log(doGet);
var htmlBody = HtmlService.createHtmlOutputFromFile('Index').getContent();
var message = 'Bonjour '+ name + ' ' + surname + ', ' + 'c\'est avec grand plaisir que je vous écris pour résumer ... - '+solution1+' \n\n- '+solution2+' \n\n- '+solution3+' \n\nMalgré...';
var emailSent = row[14]; // Third column
if (emailSent != "EMAIL_SENT") { // Prevents sending duplicates
/*MailApp.sendEmail(customerEmail, subject, message, {
cc: "",
bcc: qualityAnalystEmail + ", " + salesRepEmail
}); */
MailApp.sendEmail({
to: customerEmail,
bcc: qualityAnalystEmail + ", " + salesRepEmail,
subject: 'Résumé De Notre Consultation Du Site Mobile ' + websiteURL,
htmlBody: htmlBody,
});
}
Logger.log(name);
sheet.getRange(startRow + i, 15).setValue(EMAIL_SENT);
// Make sure the cell is updated right away in case the script is interrupted
SpreadsheetApp.flush();
}
}
}

Categories

Resources