If the value changes while using Google Script, I want to record the change in the cell next to it. Trigger is tested, but only the value after the change is saved, not the value before the change. Where do I need to fix to get the value before the change?
function onEdit1()
{
var sheet = SpreadsheetApp.getActiveSheet();
if (sheet.getName() == "sheet1") //"order data" is the name of the sheet where you want to run this script.
{
var actRng = sheet.getActiveRange();
var editColumn = actRng.getColumn();
var rowIndex = actRng.getRowIndex();
var headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues();
var aCol = headers[0].indexOf("A") + 1;
var usdCol = headers[0].indexOf("USD") + 1;
var rmbCol = headers[0].indexOf("RMB") + 1;
var changedData = sheet.getRange(rowIndex, usdCol).getValues();
var logData = sheet.getRange(rowIndex, aCol).getValues();
if (aCol > 0 && rowIndex > 1 && editColumn == usdCol)
{
if (!sheet.getRange(rowIndex, aCol).isBlank())
{
sheet.getRange(rowIndex, aCol).setValue(Utilities.formatDate(new Date(), "UTC+8", "yyyy-MM-dd") + "에 " + changedData + "(으)로 변경" + "/" + logData);
}else{
logData = Utilities.formatDate(new Date(), "UTC+8", "yyyy-MM-dd") + "에 " + changedData + "(으)로 변경됨" + " / ";
// sheet.getRange(rowIndex, aCol).setValue(Utilities.formatDate(new Date(), "UTC+8", "yyyy-MM-dd") + "에 " + changedData + "(으)로 변경됨" + " / ");
}
}
}
}
To get the value of a cell before it changes you could use the on edit trigger.
If a single cell is edited and, the event object might included value and oldValue properties.
The following is a very simple example that logs the old value to the cell to the right of the edited cell.
function onEdite(e){
if(e.oldValue) e.range.offset(0,1).setValue(e.oldValue);
}
The value property will be undefined if the cell is cleared.
The oldValue property will be undefined if the cell was blank
Both properties will be undefined if multiple cells were edited (range property includes more than one cell)
Related
I tried the script from Auto Email Function for Google Sheets Mobile and it worked the first time. When I tried to change the variables, it does not automatically send the email, unless I run the script again, it would then update the response sheet and then clears the checkbox. Please help me with this. Kindly see my code below.
function EmailNotification(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Course_AutoEmail'); //source sheet
var columnb = sheet.getRange('I:I'); //Column with check boxes
var columnbvalue = columnb.getValues();
var notifysheet = ss.getSheetByName('Responses'); //destination sheet
var data = [];
var rownum = [];
//Condition check in B:B (or check box column); If true copy the same row to data array
for (let i = 0; i < columnbvalue.length; i++) {
if (columnbvalue[i][0] === true) {
var columnb2 = sheet.getRange('I747:I'); //row started in row 747
columnb2.setValue('false');
data.push.apply(data, sheet.getRange(i + 1, 1, 1, 20).getValues());
//Copy matched ROW numbers to rownum
rownum.push(i);
//Copy data array to destination sheet
notifysheet.getRange(notifysheet.getLastRow() + 1, 1, data.length, data[0].length).setValues(data);
var activeRow = notifysheet.getLastRow();
var name = notifysheet.getRange(activeRow, 1).getDisplayValue(); // The number is the column number in the destination "responses" sheet that you want to include in the email
var employeeID = notifysheet.getRange(activeRow, 2).getDisplayValue();
var position = notifysheet.getRange(activeRow, 3).getDisplayValue();
var team = notifysheet.getRange(activeRow, 4).getDisplayValue();
var date = notifysheet.getRange(activeRow, 10).getDisplayValue();
var rec1 = notifysheet.getRange(activeRow, 19).getDisplayValue();
var rec2 = notifysheet.getRange(activeRow, 20).getDisplayValue();
var email = rec1 + "," + rec2;
var subject = name + ': 201 Completion';
//Body of the email message, using HTML and the variables from above
var message =
'<br><div style="margin-left:10px;">Hi, </div>' +
'<br><div style="margin-left:10px;">Good day!</div>' +
'<br><div style="margin-left:10px;"><b>' + name + '</b> has completed the course. </div>' +
'<br><div style="margin-left:20px;"><h3 style="text-decoration: underline; color: #f36f21">Employee Details: </h3></div>' +
'<div style="margin-left:25px;">Name: <b>' +
name +
'</b></div>' +
'<div style="margin-left:25px;">Position: <b>' +
position +
'</b></div>' +
'<div style="margin-left:25px;">Team: <b>' +
team +
'</b></div>' +
'<div style="margin-left:25px;">Completion Date: <b>' +
date +
'</b></div>' +
'<br><br><div style="margin-left:10px;">Let me know if you have any questions. </div>' +
'<br><div style="margin-left:10px;">Thanks! </div>';
MailApp.sendEmail(email, subject, '', {
htmlBody: message,
name: 'Updates',
});
}
}
}
I read your code.
if you don't want your checked checkbox unchecked in spreadsheet.
so you have to remove `columnb2.setValue('false');` line of code.
this line is made checkbox unchecked.
solution of other problems : http://one7techlab.com
I am trying to get an e-mail to be sent when the value in a cell that contains a formula goes below a certain number.
I have achieved this for various other spreadsheets that have the cell value manually entered, but for this specific one sheet where the value on the cell results from a simple SUM formula, the e-mail is not being sent. Now if I enter the value manually into the cell, the e-mail is sent right away.
Below is the code and here is a copy of my spreadsheet:
https://docs.google.com/spreadsheets/d/1gnmJfkmIKHyNqLqTFK-bdOZnh2Ejkia6xo3r_3cjwkk/edit?usp=sharing
function CheckBasketsInventory(e) {
var ss = e.source;
var inventorySheet = ss.getSheetByName("Baskets");
var rowIndex = e.range.getRow();
var columnIndex = e.range.getColumn();
var numCols = 11;
var row = inventorySheet.getRange(rowIndex, 1, 1, numCols).getValues()[0];
var editedInventory = row[10];
var editedMinimum = row[8];
var sheetName = ss.getActiveSheet().getName();
// Checking that: (1) edited cell is an inventory quantity, and (2) Inventory is below minimum
if(editedInventory <= editedMinimum && sheetName == "Baskets" && columnIndex == 11 && rowIndex > 1) {
var inventoryValues = inventorySheet.getDataRange().getValues();
var emailBody = "";
for(var i = 1; i < inventoryValues.length; i++) {
var inventory = inventoryValues[i][10];
var minimum = inventoryValues[i][8];
if(inventory <= minimum) {
var productName = inventoryValues[i][0] + " " + inventoryValues[i][1] + " " + inventoryValues[i][2];
var productUnits = minimum + " " + inventoryValues[i][9];
var messagePart1 = "Inventory for " + productName + " has gone under " + productUnits + ". ";
var messagePart2 = "Organise purchase order. Inventory as of today is: " + inventory + " " + inventoryValues[i][9];
var message = messagePart1.concat(messagePart2);
var newItem = "<p>".concat(message, "</p>");
emailBody += newItem;
}
}
var emailSubject = "Low inventory alert";
var emailAddress = "danielrzg#gmail.com";
// Send Alert Email
if(emailBody != "") {
MailApp.sendEmail({
to: emailAddress,
subject: emailSubject,
htmlBody: emailBody
});
}
}
}
Thank you.
As you can see in the documentation:
Script executions and API requests do not cause triggers to run. For
example, calling FormResponse.submit() to submit a new form response
does not cause the form's submit trigger to run.
This includes values edited by a Sheet Formula not triggering an onEdit trigger.
I am trying to send email when value of column 8 matched column 3 for all the rows in a google script .
function sendEmailNotification() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var lrow=ss.getLastRow()
var sheet = SpreadsheetApp.getActiveSheet();
for (var i = 2; i < lrow; i++)
{
if (sheet.getRange(i, 8).getValue() = sheet.getRange(i, 3).getValue())
var emailSubject = 'Value of ' + sheet.getRange(i, 1).getDisplayValue() + ' triggered, now pending your attention';
var emailBody = 'Person1 has approved the item on row ' + ' of spreadsheet "' + '".\n\n';
emailBody += 'To open the spreadsheet, click this link: ' + ss.getUrl() + '\n\n';
emailBody += '(this is an automatically sent message)';
MailApp.sendEmail("sdas22#gmail.com", emailSubject, emailBody);
; }}
The main problem is the IF statement
This is yours which does not work and which is generating an error message
if (sheet.getRange(i, 8).getValue() = sheet.getRange(i, 3).getValue())
This is mine which does work
if ((sheet.getRange(i, 8).getValue()) == (sheet.getRange(i, 3).getValue())){
}
A couple of things to note.
The comparison operator is "==" rather than "="
The each of the getValue statements are encapsulated in brackets
There are no "curly brackets" to indicate the purpose of the IF statement. This is particular important.
There's also semicolon on the last line that seem out of place.
This is my version of your code - which runs
function sendEmailNotification() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var lrow=ss.getLastRow()
var sheet = SpreadsheetApp.getActiveSheet();
for (var i = 2; i < lrow; i++)
{
if ((sheet.getRange(i, 8).getValue()) == (sheet.getRange(i, 3).getValue())){
var emailSubject = 'Value of ' + sheet.getRange(i, 1).getDisplayValue() + ' triggered, now pending your attention';
var emailBody = 'Person1 has approved the item on row ' + ' of spreadsheet "' + '".\n\n';
emailBody += 'To open the spreadsheet, click this link: ' + ss.getUrl() + '\n\n';
emailBody += '(this is an automatically sent message)';
MailApp.sendEmail("sdas22#gmail.com", emailSubject, emailBody);
}
}
}
In Google Spreadsheet I want to be able to send a email with a HTML Table within the Email. I have accomplished this below and would like to now extend the functionality more. Now I am trying to understand / find a way on how to filter the getRange based on a variable.
Example:
If Column C = Todays Date I want to return all rows with Todays date into the HTML Table in the Email. I have been playing with the GetRange but when adjusting it something other then a Range it breaks. How should I go about doing this?
function sendEmail() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var range = sheet.getDataRange();
var recipient = 'email#gmail.com'
var subject = 'Subject'
var date = Utilities.formatDate(new Date(), "GMT+1", "dd/MM/yyyy")
var schedRange = sheet.getRange("A1:L21"); // Trying to understand
//var schedRange = sheet.getRange(Col == 3 && compare == date);
// Put Name & Date into email first.
// We only want the schedule within borders, so
// these are handled separately.
var body = '<div style="text-align:center;display: inline-block;font-family: arial,sans,sans-serif">'
body += '<H1>'+ 'Deployment Table Header ' +'</H1>';
body += '<H2>'
body += getHtmlTable(schedRange);
body += '</div>';
debugger;
recipient = 'email#gmail.com'; // For debugging, send only to self
GmailApp.sendEmail(recipient, subject, "Requires HTML", {htmlBody:body})
}
/**
* Return a string containing an HTML table representation
* of the given range, preserving style settings.
*/
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));
}
// Build HTML Table, with inline styling for each cell
var tableFormat = 'style="font-size: 10px; border:1px solid black;border-collapse:collapse;text-align:center" border = 1 cellpadding = 1';
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(),
'M/d');
}
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('');
}
As stated in the comments, you can filter out any rows you don't want when you build your HTML table:
function getHtmlTable(range){
// ... your code...
var today = new Date();
for (row=0;row<data.length;row++) {
var row_date = data[row][2]; // Assuming date is in 3rd column
if(sameDay(new Date(row_date), today){ // See note
html.push('<tr height="'+rowHeights[row]+'">');
for (col=0;col<data[row].length;col++) {
// ... your code ...
}
}
}
}
function sameDay(d1, d2) {
return d1.getFullYear() === d2.getFullYear() &&
d1.getMonth() === d2.getMonth() &&
d1.getDate() === d2.getDate();
}
A few notes:
Calling new Date(row_date) will only work if the date is formatted correctly for the Date constructor. If it is not, you need to parse the date before creating the Date object.
sameDay function borrowed from this answer.
I have a bounded script to a spreadsheet 'A' that generates a new spreadsheet 'N' for each name I have in a list in spreadsheet 'A'. I would like to add a bounded script to each spreadhsheet 'N' such as:
function onEdit() {
var sh = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var row = sh.getActiveCell().getRowIndex();
var col = sh.getActiveCell().getColumn();
Logger.log(row + " " + col);
if (row == 3 && col == 1)
{
var value = sh.getActiveCell().getValue();
if (value == "I")
{
var today = formatDate(new Date());
var newdate = new Date(today);
newdate.setDate(newdate.getDate() + 15);
var dd = newdate.getDate();
var mm = newdate.getMonth() + 1;
var y = newdate.getFullYear();
var someFormattedDate = mm + '/' + dd + '/' + y;
Logger.log(someFormattedDate);
sh.getRange(row, 3).setValue(someFormattedDate);
}
}
}
function formatDate(date)
{
return (date.getMonth() + 1) + '/' + date.getDate() + '/' + date.getFullYear();
}
I have tried to do that by inserting formulas but the TODAY() function always updates the cell.
Any ideas? Is it possible to add bounded snippet of code to a google spreadsheet created programmatically with google apps scripts?
Thank you for your help.
I found what I was looking for with SriptApp Class with the SpreadsheetTriggerBuilder