Cannot write a right script for email alerts from google sheets - javascript

Try to write a script that will send the email alerts when a specific cell value appears. I have already put the following code:
function sendEmailAlert(w) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var cellValue = ss.getActiveSheet().getActiveRange().getA1Notation();
var getColumn = ss.getActiveSheet().getActiveRange().getColumn();
var sheetname = ss.getActiveSheet().getName();
var user = Session.getActiveUser().getEmail();
var Toemail = 'xxxxxxx#xxxxx.com';
var subject = 'xxxxxxx';
var body = 'The status was updated in - ' + sheetname + ' by - ' + user + ' Now the status in '+ cellValue + ' is ' +ss.getActiveCell().getValue()+ ' check file- ' + ss.getUrl();
if (ss.getActiveCell().getValue() == "Accepted" && getColumn == 15 && w.source.getActiveSheet().getName() === "Analysis") {
MailApp.sendEmail(Toemail, subject, body);
}
}
This works only when you make a change in the certain cell manually. If the cell contains the formula that makes the cell to be updated automatically, the script does not send any alerts when a specific cell value appears.
For example
My trigger is number 30. When I type 30 in the cell the script send me an alert message. But when a formula is applied in this cell like =DAYS(A1; A2) where A1 = 10/6/2020 and A2 = 9/6/2020 the script doesn’t send me anything.
Please help me to solve this problem. Hope the issue is clear. Any questions let me know down below
P.S.
I am not a programmer so please add comments to your code to explain the code rows actions

The reason your trigger is not triggering is because onEdit() requires the edit of the cell to be made by a user. Since you are changing the value of the cell using a formula, the trigger won't fire.
You might want to rethink your code and/or choose other methods to trigger the sending of the email.
You can, for example, use a time driven trigger which runs at a time chosen by you and checks if any changes have been made to the cell and send the email. Even though, the change won't be notified as quick as the onEdit(), it's an option since you plan on using formulas for your script.
Reference
Simple Triggers Restrictions;
Time Driven Triggers.

Related

Creating a Dialog Prompt Box from an onEdit Function isn't working

I'm trying to create a dialog prompt for a Google Sheet File whenever a certain column is edited. The prompt opens whenever I run it by itself manually, but for some reason when I try to run it within the onEdit function, it stops working. As you can see by the code and Logs below, the error seems to happen at the result variable since that's when the Logger stops outputting stuff. Any help would be appreciated, thanks in advance.
CODE:
function onEdit(e){
Logger.log("onEdit");
var spreadSheet = e.source;
var sheet = spreadSheet.getActiveSheet();
var sheetName = sheet.getName();
if(sheetName =='Sheet1' && e.range.columnStart == 23){
Logger.log("should be running email prompt");
emailPrompt();
}
}
function emailPrompt() {
Logger.log("Reaching email prompt");
var ui = SpreadsheetApp.getUi();
Logger.log("ui");
var result = ui.prompt(
'Email Template',
'Please edit the email:',
ui.ButtonSet.OK_CANCEL);
Logger.log("result");
// Process the user's response.
var button = result.getSelectedButton();
var text = result.getResponseText();
if (button == ui.Button.OK) {
// User clicked "OK".
//Insert Code to select email
ui.alert('Your name is ' + text + '.');
} else if (button == ui.Button.CANCEL) {
// User clicked "Cancel".
ui.alert('Email cancelled');
} else if (button == ui.Button.CLOSE) {
// User clicked X in the title bar.
ui.alert('Email cancelled.');
}
}
LOGS:
[20-07-10 15:21:09:472 CDT] onEdit
[20-07-10 15:21:11:198 CDT] should be running email prompt
[20-07-10 15:21:11:199 CDT] Reaching email prompt
[20-07-10 15:21:11:201 CDT] ui
EDIT: Setting up installable trigger
EDIT 2: Setting up an installable trigger worked, so thanks so much! The only problem I have right now is that this sheet is for the company I'm working for and they want to own the installable trigger. However, it appears that the prompt only shows up for the person who owns the trigger. If anyone else tries to edit the function and open the prompt. The following error shows up:
You do not have permission to call prompt at emailPrompt(onEdit:54) at onEdit_sendEmail(onEdit:42) –
So, now I have to figure out how to make it so that this trigger works for anyone who has access to the spreadsheet. Thanks!
Simple triggers have several limitations. Use an installable trigger instead.
NOTE: Don't use reserved function names (onOpen, onEdit, onSelectionChange, doPost, doGet, onInstall) for functions that will be called by installable triggers as some of these functions might be called twice for the same event and the others could be called by different events that might be confusing.

How to trigger a google apps script in google sheets when a cell is changed by an external source (firebase)?

I am trying to trigger a Google App Script that I have bound to a google sheet.
Data from firebase is pulled into a sheet which should trigger the script. I'm currently using onEdit(e) which works when I manually add the data in but doesn't work when the data is updated from firebase. Is there any way I can set up a trigger to run the function every time the cell values in a specific range are changed.
Thanks!
Script
function onEdit(e) {
var ss = SpreadsheetApp.getActive()
var dumpingGround = ss.getSheetByName("Dumping Ground")
var dataDump = ss.getSheetByName("Data Dump")
var ddLastRow = dataDump.getLastRow() + 1
var editCol = e.range.getColumn();
var editRow = e.range.getRow();
Logger.log("edit")
/*Copy from dumping ground to data dump*/
if ((editRow == 1 && editCol == 2) || (editRow == 1 && editCol == 3)){
/*Set required range for data dump and dumping ground*/
var ddRange = '\'Data Dump\'!A' +ddLastRow+ ':BF' + ddLastRow
var dgCopyRange = '\'Dumping Ground\'!B1:BF1'
/*Copy action*/
ss.getRange('\'Dumping Ground\'!B1:BF1').copyTo(ss.getRange(ddRange), SpreadsheetApp.CopyPasteType.PASTE_NORMAL, false);
/*Check data dump row count and delete 1000 rows if necessary*/
if(ddLastRow = 9999){
dataDump.deleteRows(1, 1000);
}
}
};
From the Apps Script documentation:
Script executions and API requests do not cause triggers to run. For example, calling Range.setValue() to edit a cell does not cause the spreadsheet's onEdit trigger to run.
I think your best but would be to create a time trigger and check for changes in the specified range. Naturally, I can't really say for sure if that's something that would even work for your purposes, but it'd be worth a try.
Here are some alternatives to consider:
If the data pull is initiated by your script, then simply have that function complete the desired actions.
If you have a separate service populating the data, you can use the Sheets API.
You could publish the script as a web app and trigger via GET or POST
You could try executing a function using Apps Script API. Please review the requirements for doing so, because it may not work for your requirements.

Amend Javascript code to Print,Tab & enter

I'm very new to java script, and I have to amend this code to make a product work...If I can't, may end sending it back.
I've tried amending the code very basically.Changed Tab to Enter, and back again.
function processData (arrData)
{
var sData = DataToString(arrData);
Print("Data: " + sData);
if (!SendKeyStrokes (sData.replace(/\x00/g, " ") + "{TAB}"))
NotifyWarning("Ignoring keystrokes sent to TWedge. Please set focus to the target application.");
}
This will output the bar code and tab over to next cell.
I'm hoping its easy, but I would like to amend it to do..
Code,tab,Code,tab,Code,tab,Code,Tab,Code,ENTER

Why is this jQuery load()-command repeated?

I have gone through many stackoverflow posts and other websites to find a solution to this problem, but none of the solutions i could find either fit my problem or just straight up didn't work.
Im using javascript and jQuery (and some Java for background work) to build a page on a website. The page contains a table with data (the data is handled by Java) and i want to have that table refresh every 10 seconds. That works.
But now i also want to highlight all the cells that have changed values in them. For that, as you see in my code snippet, i just simply turn the background of those cells black. That works too.
My problem is that the color only changes for a split second before changing back to standard white. Using the console and playing around a bit i was able to find out that the table is actually reloaded twice, which to me must mean the load-command is executed twice.
window.setInterval(function () {
if (frozen == false) {
$('table').load(document.URL + ' table');
var elem = document.getElementById("freezebtn"); //This is a button generated by Java Code
elem.style.background = getRandomColor();
var tab = document.getElementsByTagName('table').item(1);
var l = tab.rows.length;
for (var i = 0; i<l; i++) {
var tr = tab.rows[i];
var cll = tr.cells[1];
var check = tr.cells[0];
if(check.innerText === "getAsk") {
var valAsk = cll.innerText;
var ask = Number(valAsk);
if (ask != loadPreviousAsk()) {
console.log("TELEFONMAST!");
cll.style.backgroundColor = "#000000";
}
}
//Do this for every other Updateable Cell
...
}
cachePreviousValues(someValues,thatINeed,To,BeCached);
}
My Question is, what is/could be causing the repeat of the load command (or why won't the cells stay black at all)?
Is there a better way of achieving what im trying to do?
Could my code sample be optimized in any other way?
$.fn.load() is async (by default). To handle any logic regarding loaded data, you can use the complete callback:
$('table').load(document.URL + ' table', function(){/* your logic regarding loaded data here*/);

crm2011 plugin call js function

How can I run JavaScript function from appropriate web resource with a plugin in CRM2011.
I couldn't find any information on the Internet. Most of the resources describes how to trigger plugin from JS, but not opposite.
Here's JS code taht is copying the notes to the description field.
When save is clicked. you can see that the data is correctly display in a description field. However if you press save and close and open form again the description field will be empty.
I thought that the reason for that is that the JS executed after safe event but later tests descovered that it's false. Could someone point out an error in this JS code which cause that data is not saving?
Or give a suggestion how's write a plugin which is retrieving data from related entity and writes it into field in the form. thanx
function copyNotes()
{
// CLEAR DESCRIPTION FIELD
alert("JS");
Xrm.Page.getAttribute("description").setValue('');
// GET ID OF THE CASE AND CLEAN IT AND GET URL for oData stuff
//THEN CALL RETRIEVE FUNCTION
var caseID = Xrm.Page.data.entity.getId();
caseID = caseID.replace('{', '').replace('}', '');
var oDataPath = Xrm.Page.context.getServerUrl() + "/xrmservices/2011/organizationdata.svc";
ODataPath = Xrm.Page.context.getServerUrl() + "/XRMServices/2011/OrganizationData.svc";
retrieveRecord(caseID);
}
// CREATE AN HTTP REQUEST AND SEND IT
function retrieveRecord(Id) {
var retrieveReq = new XMLHttpRequest();
retrieveReq.open("GET", ODataPath + "/AnnotationSet?$filter=ObjectId/Id" + " eq (guid'" + Id + "')", true);
retrieveReq.setRequestHeader("Accept", "application/json");
retrieveReq.setRequestHeader("Content-Type", "application/json; charset=utf-8");
retrieveReq.onreadystatechange = function() {
// THIS HANDLES A CALLBACK
retrieveReqCallBack(this);
};
retrieveReq.send();
}
function retrieveReqCallBack(retrieveReq) {
if (retrieveReq.readyState == 4 /* complete */ )
{
if (retrieveReq.status == 200) {
//Success
var retrieved = this.parent.JSON.parse(retrieveReq.responseText).d;
// ITERATE THROUGH THE NOTES FOR THIS CASE
for (var i = 0; i < retrieved.results.length; i++) {
// IF IS AN EMPTY FIELD ADD 'case details:'
if (Xrm.Page.getAttribute("description").getValue() == null || Xrm.Page.getAttribute("description").getValue() == 'null') {
Xrm.Page.getAttribute("description").setValue('Case details:');
}
// BOF PARSE DATE
var date = retrieved.results[i].CreatedOn;
date = new Date(parseInt(date.replace("/Date(", "").replace(")/", ""), 10));
// EOF PARSE DATE
var newtext = "--------------------\r\n" + "Created by: " + retrieved.results[i].CreatedBy.Name + " - " + date + "\r\n" + retrieved.results[i].NoteText + "\r\n--------------------\r\n";
var text = Xrm.Page.getAttribute("description").getValue() + "\r\n" + newtext;
Xrm.Page.getAttribute("description").setValue(text);
}
}
}
}
There is no supported way to call back to the client from the server from within the plugin. I'm also not aware of any unsupported way.
I don't think this question even makes sense. Plugin's only trigger when there has been a CRUD operation of some sort. Any CRUD operation triggered by the GUI will result in a refresh of the entity any way. You could perform an update via javascript and an Odata call, but then once the plugin has finished, you can run whatever javascript you'd like to run.
There's no (reasonable) way to do that.
The reason for that is the fact that plugin is a server-size executed thingy. It can't even assume there's a GUI. (Of course, we know there is but generally, a server-size code can't interact with the GUI directly).
JavaScript is client-side code and a client assumes a server. That's (roughly) why JS can call a plugin (although I wouldn't put it that way) but not the other way around.
I've never had a need of such an operation so I'm curious as to what your task is. Are you asking of pure, academic interest or is it a part of a design? Perhaps there's a better way to reach your goal?

Categories

Resources