I was using the following script on a google sheet that worked for months, but now around 1:30 PM Thursday 3/5/2020 it stopped working and pulling the user emails. I tried changing it to the second attempt, saved, and edited the cell, but nothing happened.
(Note: I cannot share the file due to regulations.)
What was working before:
function onEdit(e) {
var rg = e.range;
if (rg.getSheet().getName() == "Call Log" && rg.columnStart == 13) {
var nextCell = rg.offset(0, -3);
if (nextCell.getValue() == '') {
var userMail = e.user.getEmail();
nextCell.setValue(userMail);
}
}
}
My second attempt:
function onEdit(e) {
var rg = e.range;
if (rg.getSheet().getName() == "Call Log" && rg.columnStart == 24) {
var nextCell = rg.offset(0, 3);
if (nextCell.getValue() == '') {
var email = Session.getActiveUser().getEmail();
Logger.log(email);
nextCell.setValue(userMail);
}
}
}
onEdit Event Object clearly states the following:
If security policies do not allow access to the user's identity, User.getEmail() returns a blank string. The circumstances in which the email address is available vary: for example, the user's email address is not available in any context that allows a script to run without that user's authorization, like a simple onOpen(e) or onEdit(e) trigger, a custom function in Google Sheets, or a web app deployed to "execute as me" (that is, authorized by the developer instead of the user). However, these restrictions generally do not apply if the developer runs the script themselves or belongs to the same G Suite domain as the user.
Lara,
Honestly, I've never worked with google sheet functions. But it looks like their API is pretty straightforward. Based on the error
TypeError: Cannot read property 'range' of undefined (line 2, file
"Code")
I can assume that your function doesn't consume any values. You should retrieve the range from another object. I found this article very good to start with. It looks like you first have to get your sheet using var sheet = SpreadsheetApp.getActiveSheet(); and then carefully read API documentation.
Most likely you will end up with something like:
function onEdit(e) {
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getRange();
if (sheet.getName() === "Call Log" && range.getColumn() === 24) {
var nextCell = range.offset(0, 3);
if (nextCell.getValue() === '') {
var email = Session.getActiveUser().getEmail();
Logger.log(email);
nextCell.setValue(email);
}
}
}
But I can't test this solution. Please, give it a try or update this in the way you wish.
Related
I'm pretty new with Appscript and i'm looking for a solution when I complete a task, appscript code on edit will allow me to email whatever email is in the column B with just a simple task email that states the task has been completed.
This script does work but it emails just me whenever there is a change triggered. I'd like it just to email the email address in Column B and not me.
i've tried several different scripts but i don't know it well enough to pinpoint the issue or even edit it to fit my needs
function checkValue()
{
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName("Sheet1");
var valueToCheck = sheet.getRange("J:J").getValue();
if(valueToCheck="Approved")
{
MailApp.sendEmail("joes#nhcares.com","Task Completed","1231323"+
valueToCheck+ ".");
}
}
this may be too simple of a script, it does email me on edit but I need to tweak it more
Try this:
function checkValue(e) {
var sh = e.range.getSheet();
if (sh.getName() == "Sheet1" && e.range.columnStart == 10 && e.range.rowStart > 1 && e.value == 'Approved') {
let msg = `${sh.getRange(e.range.rowStart,1,1,sh.getLastColumn()).getDisplayValues().flat().join('\n')}`
MailApp.sendEmail(sh.getRange(e.range.rowStart,2).getDisplayValue(), "Task Completed", msg);
}
}
Use installable onEdit trigger
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
if( sheet.getSheetName() != 'Sheet1' ) {
return 0;
}
var selectedCell = ss.getActiveCell();
if( selectedCell.getColumn() == 1) {
var dateTimeCell = selectedCell.offset(0, 2);
dateTimeCell.setValue('auto');
GmailApp.sendEmail('12345#gmail.com', selectedCell.getRow(), 'hello')
}
if I modify column A and run script, Gmail sent.
but if I modify column A only (don't run code), then Gmail not sent.
'auto' is inserted in both case. I suspect only GmailApp.sendEmail is not working.
why?
Do you have a trigger set up for it? The function you have only shows a simple trigger onEdit() which cannot send emails. See Restrictions here.
Vytautas is right. It says that:
They cannot access services that require authorization. For example, a simple trigger cannot send an email because the Gmail service requires authorization, but a simple trigger can translate a phrase with the Language service, which is anonymous.
I have a spreadsheet on Google spreadsheets that has "D2" through all of "D" (because it will expand as used and when I add more) with a drop down box for priority status. The drop down has "Low, Medium, High". I want to get a script to send me an email when that priority gets edited to "High"
This is the script I did last night at 2AM half asleep.
{
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName("TC52 Bugs or Issues and Improvements.");
var valueToCheck = sheet.getRange(D).getValue();
var rangeEdit = e.range.getA1Notation();
if(rangeEdit == "D")
{
if(valueToCheck > High)
{
MailApp.sendEmail("austin.hendrix#decathlon.com", "High Priority please check now.", "Check spreadsheet" + valueToCheck+ ".");
}
}
}````
This article has a tutorial.
On that note, something along the lines of (Heavily edited by MetaMan)
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var dataRange = sheet.getRange(1,4,sh.getLastRow()) or getRange('D1:D'+sh.getLastRow()));
var data = dataRange.getValues();
for (var i in data) {
var row = data[i];
var emailAddress = "youremail#email.com"; // First column
var message = "High priority set with data in A column "+sheet.getRange(("A"+i+1)).getValues()[0]; // Second column
var subject = 'High priority set in D'+i;
if(row[0]=="High"){
MailApp.sendEmail(emailAddress, subject, message);
}
}
}
The function will send you an email when column D is edited to "High".
You will need to fill in 'Your Spreadsheet name' the recipient email address and what ever subject you wish. Also you can edit the body as well. The current body just tells you which row issue the email. Alternately, if you wish to provide more information I'll do it for you.
function onMyEdit(e) {
const sh = e.range.getSheet();
if(sh.getName() == 'Your Sheet Name' && e.range.columnStart == 4 && e.range.rowStart >1 && e.value == 'High') {
GmailApp.sendEmail('recipient','subject',`row ${e.range.rowStart} has been set to high`)
}
}
Since sending an email requires permission you will have to create an installable trigger for this function.
You can do it manually or use a function like the one below which will prevent you from creating more that one trigger.
function createTrigger() {
const ts = ScriptApp.getProjectTriggers().map(t=>t.getHandlerFunction());
if(!~ts.indexOf('onMyEdit')) {
ScriptApp.newTrigger('onMyEdit').forSpreadsheet(SpreadsheetApp.getActive().getId()).onEdit().create();
}
}
ScriptApp
Please Note: that you cannot run onEdit triggered functions from the Script Editor or even from a menu. They require the onEdit trigger which populates the single parameter e with the event object. You can run them from another function as long as it provides the event object.
My script works perfectly when I execute it manually through the editor but fails to fire with the edit or change trigger.
I saw a bunch of people having the same problem but none of these solutions help me solving this issue.
Has anybody a solution for this ?
function createNewSheets() {
// 1. Retrieve the current sheet names.
var dataSheet = SpreadsheetApp.getActiveSpreadsheet();
var sheetNames = dataSheet.getSheets().map(s => s.getSheetName());
// 2. Retrieve the values from "mastersheet" sheet.
var masterSheet = dataSheet.getSheetByName('Liste de nageurs');
var values = masterSheet.getRange('A2:B' + masterSheet.getLastRow()).getValues();
// 3. Using the retrieved sheet names and values, the new sheets are inserted and the values are put.
values.forEach(r => {
if (!sheetNames.includes(r[0])) {
var newSheet = dataSheet.insertSheet(r[0])
sheetNames.push(r[0]);
newSheet.appendRow(r);
}
});
}
I ran it this way, using a checkbox in A1:
function onEdit(e) {
//e.source.toast('entry');//just a toast to let me know it's work
const sh = e.range.getSheet();// getting sheet name
//next line limits execution to Sheet1 A1 being changed to 'TRUE'
if (sh.getName() == 'Sheet1' && e.range.columnStart == 1 && e.range.rowStart == 1 && e.value == 'TRUE') {
e.range.setValue('FALSE');//reset the checkbox back to 'FALSE'
//the rest is your code
var ss = SpreadsheetApp.getActive();
var names = ss.getSheets().map(s => s.getSheetName());
var masterSheet = ss.getSheetByName('Sheet2');//changed sheet name
var vs = masterSheet.getRange('A2:B' + masterSheet.getLastRow()).getValues();
vs.forEach(r => {
if (!names.includes(r[0])) {
var newSheet = ss.insertSheet(r[0])
names.push(r[0]);
newSheet.appendRow(r);
}
});
}
}
You can simplify your code if you learn how to use the event object better but I left most of your code intact. The problem that most users dislike about using the event object is that you can't debug the code by running it from the script editor because you have to supply the event object as a parameter. I normally debug them but running them from the trigger. You can use JSON.stringify(e) to look at the event object.
Using the event object normally results in faster code and simple triggers must finish in 30 seconds or less.
For my work I made a spreadsheet which tracks the maintenance dates for all different tasks of †heir respective machine.
My scripts have been working just fine, but I noticed that it would run on all the pages I have in my Sheet.
So I have been searching for a solution, but I can't seem to make the different solutions I found work for me.
The script I have been using:
function onEdit(e) {
if (e.range.getColumn() == 6) {
e.range.offset(0, 3).setValue("")}
};
function onEdit2(e) {
if ([10].indexOf(e.range.columnStart) != -1) {
e.range.offset(0, 1).setValue(newDate()).setNumberFormat("dd.MM.yyyy | HH:mm")};
}
With this I have been the closest to completing my quest (I think)
function Autoclear(e){
var sheet = event.source.getActiveSheet(e);
if(sheet.getName()=='Onderhoud'){
var editedCell = sheet.getActiveCell();
if (e.range.getColumn() == 6) {
e.range.offset(0, 3).setValue("")}
}
};
function Timestamp(e){
var sheet = event.source.getActiveSheet(e);
if(sheet.getName()=='Onderhoud'){
var editedCell = sheet.getActiveCell();
if ([10].indexOf(e.range.columnStart) != -1) {
e.range.offset(0, 1).setValue(new Date()).setNumberFormat("dd.MM.yyyy | HH:mm")};
}
}
This doesn't give me an error upon saving, but I do get the error message upon running.
(ReferenceError: 'e' is not defined)
The main goal is to make the script work in 1 specific page: "Onderhoud"
How can I make this work? If there is something not correctly formatted or left information I will been more than happy the provide.
Try this script, instead of the ones you have
function onEdit(e) {
var sheet = e.source.getActiveSheet();
var ind = [6, 10].indexOf(e.range.columnStart);
if (sheet.getName() == 'Onderhoud' && ind > -1) {
if (ind === 0) {
e.range.offset(0, 3).setValue(null)
} else {
e.range.offset(0, 1).setValue(new Date()).setNumberFormat("dd.MM.yyyy | HH:mm")
};
};
}
As noted by Amit, edit the designated columns (instead of running the script from the script editor) to check if the script works.
The onEdit trigger should not be run manually. The Spreadsheet service will pass the e object when the trigger is run via any edits in the spreadsheet.