Best practice Google Scripts with two functions - google-apps-script

I'm not sure what my issue is here. I have an office visitor sign in/out Google spreadsheet. This is how I'm trying to get it to work. When a visitor selects a checkbox in the "in" column a timestamp will display in the next column. When a visitor selects a checkbox in the "out" column a timestamp will display in the next column. Currently this is how it's working: When I have only the first function in the code editor a timestamp displays in column 4 - like it's supposed to. When I add the second function a timestamp displays in column 6, but not in column 4. It's like the second function is overriding the first. What would correct the issue?
function onEdit() {
var s = SpreadsheetApp.getActiveSheet();
if( s.getName() == "SignInOut" ) { //checks that we're on the correct sheet
var r = s.getActiveCell();
if( r.getColumn() == 3 ) { //checks the column
var nextCell = r.offset(0, 1);
if( nextCell.getValue() === '' ) //is empty?
nextCell.setValue(new Date());
}
}
}
function onEdit() {
var s = SpreadsheetApp.getActiveSheet();
if( s.getName() == "SignInOut" ) { //checks that we're on the correct sheet
var r = s.getActiveCell();
if( r.getColumn() == 5 ) { //checks the column
var nextCell = r.offset(0, 1);
if( nextCell.getValue() === '' ) //is empty?
nextCell.setValue(new Date());
}
}
}

Both functions have the same name, so it will run the last.
Perhaps you can avoid having to define 2 times the same function, try something like:
function onEdit(e) {
var s = e.source.getActiveSheet(), r, colCell, nextCell;
if(s.getName() === 'SignInOut') { //checks that we're on the correct sheet
r = e.range; //s.getActiveCell();
colCell = r.getColumn();
if(colCell === 3 || colCell === 5) { //checks the column
nextCell = r.offset(0, 1);
if(nextCell.getValue() === '') //is empty?
nextCell.setValue(new Date());
}
}
}

Related

Combining two onEdit() in single Google Sheets App Script

I am trying to combine two onEdit functions in a single App Script. I have read through other posts on this subject and feel like I have integrated their suggestions but it is still not working.
Function A (timeStamp) places a time stamp in column B when columnn A is edited
Function B (arhviveRow) copies the edited row to sheet "Inactive" when a check box is marked True on sheet "Active" and then deletes the row from sheet "Active".
Both functions work correctly when run separately, but only the second function works when combined.
function onEdit(e) {
timeStamp();
archiveRow();
//Automatically stamp date and time on line
function timeStamp() {
var s = SpreadsheetApp.getActiveSheet();
if( s.getName() == "Active" ) { //checks that we're on Sheet1 or not
var r = s.getActiveCell();
if( r.getColumn() == 1 ) { //checks that the cell being edited is in column A
var nextCell = r.offset(0, 1);
if( nextCell.getValue() === "" ) //checks if the adjacent cell is empty or not?
nextCell.setValue(new Date() + new (Time));
}
}
}
//Archive and delete line
function archiveRow(){
//ColumnNumberToWatch defines which column on sheet to monitor for an edit
var ss = e.source,
sheet = ss.getActiveSheet(),
range = e.range,
targetSheet,
columnNumberToWatch = 9; // column A = 1, B = 2, etc
// "sheet.getName() ===" defines which sheet to watch for the edit
// "targetSheet =" defines sheet to copy data to
if (sheet.getName() === "Active" && e.value === "TRUE" && e.range.columnStart === columnNumberToWatch) {
targetSheet = "Inactive"
} else if (sheet.getName() === "Inactive" && e.value === "FALSE" && e.range.columnStart === columnNumberToWatch) {
targetSheet = "Active"
}
//Copies data to last row in targetSheet and then deletes from source sheet
ss.getSheetByName(targetSheet)
.appendRow(sheet.getRange(e.range.rowStart, 1, 1, sheet.getLastColumn())
.getValues()[0])
sheet.deleteRow(e.range.rowStart);
}
}
Any insights into where I went wrong would be greatly appreciated.
Thanks!
The new Date() object should already contain the time, and there is no Javascript Object for new Date(Time).
It should look like this:
function timeStamp() {
var s = SpreadsheetApp.getActiveSheet();
Logger.log(s);
if( s.getName() == "Active" ) { //checks that we're on Sheet1 or not
var r = s.getActiveCell();
if( r.getColumn() == 1 ) { //checks that the cell being edited is in column A
var nextCell = r.offset(0, 1);
if( nextCell.getValue() === "" ) {//checks if the adjacent cell is empty or not?
nextCell.setValue(new Date().toLocaleString());
}
}
}
}
Sample output for the date:
Active Sheet
Once the checkbox was clicked setting the value to TRUE, appends the row to the "Inactive" sheet.
Inactive Sheet
function onEdit(e) {
const sh = e.range.getSheet();
const name = sh.getName():
if (name == "Active" && e.range.columnStart == 1) {
e.range.offset(0, 1).setValue(Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "MM/dd/yyyy HH:mm:ss"));
}
if (name == 'Active' && e.range.columnStart == 9 && e.value == "TRUE") {
let tsh = e.source.getSheetByName('Inactive');
tsh.appendRow(sh.getRange(e.range.rowStart, 1, 1, sh.getLastColumn()).getValues()[0]);
sh.deleteRow(e.range.rowStart())
} else if (name = 'Inactive' && e.range.columnStart == 9 && e.value == "FALSE") {
let tsh = e.source.getSheetByName('Active');
tsh.appendRow(sh.getRange(e.range.rowStart, 1, 1, sh.getLastColumn()).getValues()[0]);
sh.deleteRow(e.range.rowStart());
}
}

Is there a script function to get user email when they edit a cell in a spreadsheet?

I have some difficulty searching and creating a script. What I am trying to achieve is getting the user's email/name when they edited a cell in my spreadsheet. I tried getactiveuser but its not showing anything. I read that some ask to use geteffectiveuser but all I get is still my username back and not the other editor.
Here is my script so far:
function onEdit() {
var s = SpreadsheetApp.getActiveSheet();
if( s.getName() == "TEST" ) { //checks that we're on the correct sheet
var r = s.getActiveCell();
var email = Session.getActiveUser().getEmail();
if( r.getColumn() == 4 ) { //checks the column for HUB side
var nextCell = r.offset(0, 1);
if( nextCell.getValue() === '' ) //is empty?
nextCell.setValue(email());
}
}
}
Logger.log(Session.getActiveUser().getEmail());
As of the above, nothing is showing up.
You may perform a test on the following code, it work for me :)
function onEdit(e) {
var s = e.source.getActiveSheet();
if( s.getName() == "TEST" ) { //checks that we're on the correct sheet
var r = e.range;
if( r.getColumn() == 4 ) { //checks the column for HUB side
var nextCell = r.offset(0, 1);
if( nextCell.getValue() === '' ) //is empty?
nextCell.setValue(Session.getActiveUser().getEmail());
}
}
}

Script for auto Timestamp (Google Spreadsheet)

I need some help in making an auto updating timestamp script for my google spreadsheet. What I exactly need is that, when someone edits column A or B, a date and time will appear on column D.
I tried using this script
function onEdit() {
var s = SpreadsheetApp.getActiveSheet();
if( s.getName() == "Sheet1" ) { //checks that we're on the correct sheet
var r = s.getActiveCell();
if( r.getColumn() == 4 ) { //checks the column
var nextCell = r.offset(0, 3);
//if( nextCell.getValue() !== '' ) //is empty?
nextCell.setValue(new Date());
}
if( r.getColumn() == 5 ) { //checks the column
var nextCell = r.offset(0, 2);
//if( nextCell.getValue() !== '' ) //is empty?
nextCell.setValue(new Date());
}
}
}
It worked fine for me, but when I share it, it won't work others. I have close to zero experience with codes/scripts, so can someone please help me?

How to insert user email after Sheets cell is edited

Working on a sheet that when the user edits a cell (example C3), it will insert his/her email (name). Have a scrip that does work for only one column ("C"), but when moved to another sheet or column ("5 or E") it gives “Error – you do not have permission to call getActiveUser (line 41)".
Because it does work once, not sure what I am missing or why the same script wont work at all on another sheet. Thanks for any assistance.
function onEdit() {
var s = SpreadsheetApp.getActiveSheet();
if( s.getName() == "Sheet1" ) { //checks that we're on the correct sheet
var r = s.getActiveCell();
var email = Session.getActiveUser().getEmail();
Logger.log(email);
if( r.getColumn() == 3 ) { //checks the C column
var nextCell = r.offset(0, 1);
nextCell.setValue(email);
if( r.getColumn() == 5 ) { //checks the E column
var nextCell = r.offset(0, 1);
if( nextCell.getValue() !== '' ) //is empty?
nextCell.setValue(email);
}
}
}
Make sure you are the owner of the spreadsheet and you have granted the necessary permission to run the script.
function onEdit() {
var s = SpreadsheetApp.getActiveSheet();
if (s.getName() == "Sheet2") { //checks that we're on the correct sheet
var r = s.getActiveCell();
var email = Session.getActiveUser().getEmail();
if (r.getColumn() == 3) { //checks the C column
var nextCell = r.offset(0, 1);
nextCell.setValue(email);
}
if (r.getColumn() == 5) { //checks the E column
var nextCell = r.offset(0, 1);
Logger.log(nextCell.getValue());
if (nextCell.getValue() == '') //is empty?
nextCell.setValue(email);
}
}
}

howto adapt onEdit function to fire for specific value

In an 'onEdit' function, all examples that I find in this forum or elswhere contain the same (or similar) line to define the source, like:
if( r.getColumn() == 5 ) { //checks updates in column E
I cannot find how to adapt this, but I want my onEdit function to fire only if the column is set to a specific value:
if value of column E is set to "done" then perform rest of the function
Try something like this:
function onEdit(e) {
if (e.range.getColumn() === 5 && e.value.toLowerCase() === 'done')
Logger.log('Todo');
}
See Understanding Events.
I have solved this with following script:
function onEdit() {
var s = SpreadsheetApp.getActiveSheet();
if( s.getName() == "TaskBoard" ) { //checks that we're on the correct sheet; "TaskBoard"
var r = s.getActiveCell();
if( r.getColumn() == 2 ) { //checks updates in column B
var cellContent = r.getValue();
if (cellContent == 'Done')
{
var nextCell = r.offset(0, 4); //offset to same row, and column F; B+4
if( nextCell.getValue() === '' ) //is empty?
{
var time = new Date();
time = Utilities.formatDate(time, "CET", "yyyy-MM-dd");
nextCell.setValue(time);
}
}
};
};
}