Google Apps Script: Capture timestamp/email of logged in user who has updated a field in a specific column - google-apps-script

I have created a Google Sheet that is shared with multiple people within my organization. It will not be shared with anyone outside the company. On said spreadsheet, when a user checks the box in column 1, I would like to put a timestamp in column 2, and the logged in user's email in column 3.
The timestamp works; and the email works when I do it; but it only works for me. I have tried, deploying as a webapp (executing as the user accessing the app), deploying as a API Executable, all to no avail.
I suspect it's due to trying to trigger this from onEdit, since they may think I'm trying to harvest something that the user isn't releasing to me intentionally. Since we're all in the same company, and it's not ill intended; I'm thinking there must be a solution. A function which stores the logged in user, and another function that gets this value onEdit?
in the code I've pasted, I have it checking for values greater than 5, as I was unclear how to check for checkbox=TRUE.
Any advice?
function onEdit() {
var s = SpreadsheetApp.getActiveSheet();
var email = Session.getActiveUser().getEmail();
Logger.log(email);
var r = s.getActiveCell();
if( r.getColumn() == 1) {
if(r.getValue()>5){
var nextCell = r.offset(0, 2);
nextCell.setValue(new Date());
var emailCell = r.offset(0, 3);
emailCell.setValue(email);}}
}
I expect any user within my organization, to check the box in column 1, and the time they checked it appears in column 2; and their email address shows up in column 3.

Related

Installed onEdit trigger does not

I have a function that is intended to detect changes in one spreadsheet and copy them into another spreadsheet in the same exact cell location if the change is made in sheet1. I first tried to do this using the installed onEdit(e) function provided by sheetsAPI, but kept running into the error that I'm not authorized to open a new spreadsheet from a built-in function. I tried setting up my own trigger, but it won't activate even though I assigned an OnEdit trigger to the function.
function ChangeDetect(e){
var range = e.range
var esheet = SpreadsheetApp.getActiveSheet()
var ss = SpreadsheetApp.getActiveSpreadsheet()
var sheet = ss.getSheets()[1];
// literally, if the edit was made in the first sheet of the spreadsheet, do the following:
if (esheet.getIndex() == ss.getSheets()[0].getIndex()){
var numrows = range.getNumRows();
var numcols = range.getNumColumns();
for (var i = 1; i <= numrows; i++) {
for (var j = 1; j <= numcols; j++) {
var currentValue = range.getCell(i,j).getValue();
var cellRow = range.getCell(i,j).getRow();
var cellCol = range.getCell(i,j).getColumn();
var ss3 = SpreadsheetApp.openByUrl('https://docs.google.com/spreadsheets/d/1K2ifzjPTATH77tV4xInh0Ga2SuPsLdgNRSbekjDx-w8/edit#gid=0')
var sheet3 = ss3.getSheets()[0];
sheet3.getRange(cellRow,cellCol).setValue(currentValue)
}
}
}
}
I think you may be experiencing the limitation/restrictions of installable triggers:
Restrictions
Because simple triggers fire automatically, without asking the user for authorization, they are subject to several restrictions:
The script must be bound to a Google Sheets, Docs, or Forms file.
They do not run if a file is opened in read-only (view or comment) mode.
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.
They can modify the file they are bound to, but cannot access other files because that would require authorization.
They may or may not be able to determine the identity of the current user, depending on a complex set of security restrictions.
They cannot run for longer than 30 seconds.
In certain circumstances, add-ons for Google Sheets, Docs, and Forms run - their onOpen(e) and onEdit(e) simple triggers in a no-authorization mode that presents some additional complications. For more information, see the guide to the add-on authorization lifecycle.
These restrictions do not apply to doGet() or doPost().

Unstable Behavior for mailApp.sendEmail [duplicate]

This question already has an answer here:
MailApp.sendEmail not firing [duplicate]
1 answer
I have a simple GoogleSheet which is meant to send an email if one edits 4th column on a "TESTING" tab.
I wrote a basic script, with static recipient, body and subject.
I authorized the function upon authorization request.
The recipient is one of my hotmail accounts (which has no linkage to this Google sheet, so should not have an issue raised by MailApp.sendEmail Not Working?.
I have tried both "GmailApp.sendEmail" and "MailApp.sendEmail", but the behavior is the same:
When I run my onEdit() function inside the editor, everything works exactly as expected, and the email function works if the cursor is in the appropriate 4th column on the appropriate sheet.
But after I save the code, and try to evince the same behavior by editing a cell in column 4 on that sheet, I get as far as the step1 break but the email does not get sent (I did check the spam folder, after reading the discussion on StackOverflow on the subject)
function onEdit() {
var s = SpreadsheetApp.getActiveSheet();
if( s.getName() == "TESTING" )
{
var r = s.getActiveCell();
var col = r.getColumn();
var row = r.getRow();
if( col == 4)
{
s.getRange(row, 5).setValue("step1"); // did we get this far?
MailApp.sendEmail("me#hotmail.com", "step1", "step1");
s.getRange(row, 6).setValue("step2"); // do we get this far?
}
}
}
The active sheet is pretty simple:
Any idea what would be causing such behavior?
And the answer was apparently in one of the previous threads, courtesy of Serge.
I had to go into Resources and edit Current Project Triggers to allow for onEdit triggers.

Google app script trigger not working

I have a google app script which sends email, and i have set a trigger such that it sends email on every form submit. The problem is the trigger works perfectly fine for initial few minutes, but later even after entering correct data. The script does not send the mail, i have to manually press the execution button of the script. Here is my code
var EMAIL_SENT = "EMAIL_SENT";
function sendEmailsapp() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = sheet.getLastRow(); // Number of rows to process
// Fetch the range of cells A2:B3
var dataRange = sheet.getRange(startRow, 1, numRows,8)
// 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 emailAddress = row[4]; // First column
var message = row[5]; // Second column
var emailSent = row[7]; // Third column
var money=row[6]
if (emailSent != EMAIL_SENT) { // Prevents sending duplicates
var subject = "You have been registered for follwoing events:-";
var event;
MailApp.sendEmail(emailAddress, subject, "Please bring your college id and copy of this mail either in phone or printed paper"+
"\n\n"+"Name:-"+row[1]+"\n"+"USN:-"+row[2]+"\n"+"Mobile:-"+row[3]+"\n"+"Event:-"+ message+"\nMoney status:-"+money+"You registered on"+row[0]);
sheet.getRange(startRow + i, 8).setValue(EMAIL_SENT);
// Make sure the cell is updated right away in case the script is interrupted
SpreadsheetApp.flush();
}
}
}
The code works fine. The only problem is triggers.
Here is the image of my trigger. sendEmailsapp is the trigger, and sendEmailsweb is another trigger which also suffers from same problem.
here is the log
My only Problem is the trigger is not getting triggered, it is not with the email being sent.
My trigger wasn't working just like yours, even though the script was correct.
The solution was very stupid. I deleted the trigger and added a new one. Exactly the same trigger.
I had this issue with my script, but I was using Time-Driven as the Event. I set it on every minute but it just wouldn't do anything. Used the logging method written above and I found out that the trigger works fine - every minute as I set. But it just wouldn't actually do the same thing as when I explicitly click on the Run button.
I suspected that it had something to do with the following line:
var sheet = SpreadsheetApp.getActiveSheet();
So I played around with it and changed it to:
var spreadsheet = SpreadsheetApp.openById("INSERT_SPREADSHEET_ID_HERE");
var sheet = SpreadsheetApp.setActiveSheet(spreadsheet.getSheets()[0]);
And it finally worked.
Replace INSERT_SPREADSHEET_ID_HERE with the ID of your spreadsheet (from your URL https://docs.google.com/spreadsheets/d/INSERT_SPREADSHEET_ID_HERE/edit#gid=0).
And from the getSheets()[0], the 0 would be your first of possibly multiple sheets in that specific spreadsheet.
I hope this helps in any way.
What I found useful was to set notifications to immediate in "Resources>Current Projects Triggers". I set it to send me an email on error. That email contains details of the problem which you can then solve :).
I'd be willing to bet that the problem is not the trigger. Even though your code works, it could be conditions that are preventing the conditional section of your code to work. You can test to see that the function is actually triggering, even if it's not giving you the expected result. Put a Logger.log() statement immediately after the function:
function sendEmailsapp() {
Logger.log('sendEmailsapp ran!');
Then VIEW the LOGS. I can't believe that the function isn't being triggered. The email might not be getting sent, but I'd be willing to bet that you are going to get that msg 'sendEmailsapp ran!' printed to the LOGS. So, that's the first thing you need to do.
The next thing you need to do is put a Logger.log() statement immediately after retrieving the email:
var emailSent = row[7];
Logger.log('value of the email is: ' + emailSent);
Then check the LOGS for what values are actually being returned. If every value being returned is "EMAIL_SENT", then no email will ever get sent.
We need to know what the actual results are. You need to provide what was printed to the LOGS.

Fetch editors name in google spreadsheet and write it to cell

Is there any way to have an onEdit function that fetches the editors name and writes it to B2 whenever A2 is changed?
https://docs.google.com/spreadsheets/d/1hYp2KAZSlRN2HNUWvyHAkc35mJtDPBSVipl4PtrSIJw/edit?usp=sharing
(e.g, the name of my google account is "Thomas G.", so this should be written to B2.)
Possible?
IMPORTANT CAVEAT: the code below will generally work only if the owner/publisher of the script and the user accessing the sheet belong to the same Google Apps domain. It will NOT work for non-apps users.
You can do this with the following onEdit() method in your sheet:
function onEdit(e) {
var editedRange = e.range;
if ( editedRange.getColumn()==1 ) { // if column A was edited
var u = Session.getActiveUser().getEmail();
editedRange.offset(0, 1).setValue(u); // write user's email to corresponding row in column B
}
};
Note: this will require users to authorize the script's access to their data on Google (to know the user's email).

Google Apps Script in Form

I'm building a form for students to enter in and I want to Auto input their email address and I'm unsure how to do this. I'm come up with the following but I'm very new to this and may be way off. I'm unsure how to implement it and I'm getting a null response. Do I need a form question which says email ? how do I get the user's email to be recorded but in a hidden way?
function formEnterEmail(e) {
var userEmail = Session.getActiveUser().getEmail();
var sheet = SpreadsheetApp.getActiveSheet();
var lastRow = sheet.getLastRow();
// Set the status of the new ticket to 'New'.
// Column F is the Status column
sheet.getRange(lastRow, getColIndexByName("Email")).setValue(userEmail);
function getColIndexByName(colName) {
var sheet = SpreadsheetApp.getActiveSheet();
var numColumns = sheet.getLastColumn();
var row = sheet.getRange(1, 1, 1, numColumns).getValues();
for (i in row[0]) {
var name = row[0][i];
if (name == colName) {
return parseInt(i) + 1;
}
}
return -1;
}
}
If you are building a form that you will be emailing to the students, then when you set up the form you can have it log all their email addresses for you without you having to write any script at all.
Here is a great way to get started writing a new form... go to this page:
http://www.google.com/drive/apps.html?usp=ad_search
and scroll down to the "Forms" section then click on "Create".
This should walk you through everything you will need to set up the form, and the results will be put into a spreadsheet for you, along with the students' email addresses. You can keep the resulting spreadsheet private so that you will be the only one who can view all the responses.
I hope that helps.
You can collect the user's email address in Google Forms only if you are using Google Apps for Business or Google Apps for Education, and then only from users in your domain. If you don't meet those requirements, then your only option is to request that users fill in the information, or to email a URL to a pre-filled-form.
This isn't really "hidden", as the live form will report that the user id is being collected.
If you're creating your form from a script, you can control the email collection feature by using Form.setCollectEmail(true). However, you can also set this up without using any code.
In the form editor, look for "Form Settings". They should appear above all the questions. Set the check boxes that require domain login, and username collection.
The spreadsheet that collects responses will automatically contain a "Username" column:

Resources