Adding name to last edited (google script) - javascript

Currently i have the following google script:
function onEdit() {
var s = SpreadsheetApp.getActiveSheet();
var r = s.getActiveCell();
if(s.getName()=='Setup BRF'){
if( r.getColumn() != 2 ) { //checks the column
var row = r.getRow();
var time = new Date();
time = Utilities.formatDate(time, "GMT", "dd-MM-yy' , 'HH:mm:ss");
SpreadsheetApp.getActiveSheet().getRange('J1').setValue(time);
};
};
};
Everytime i edit something on the sheet called Setup BRF it updates the time and date in J1 to show when it was last updated/edited.
My question is if its possible to add a name to lets cell K1 which shows who last updated this sheet. My skill with javascript is nihil so any kind of help is appreciated.

You could use the event object passed to the function
So change the definition to
function onEdit(e) {
and then you can use e.user to get to the user
Something like this
if( r.getColumn() != 2 ) { //checks the column
var row = r.getRow(),
time = new Date(),
user = e.user;
time = Utilities.formatDate(time, "GMT", "dd-MM-yy' , 'HH:mm:ss");
SpreadsheetApp.getActiveSheet().getRange('J1').setValue(time);
SpreadsheetApp.getActiveSheet().getRange('K1').setValue(user);
};

Related

Google Apps Script for moving and timestamping row in Google Sheets

Let me start by saying writing scripts is not in my wheelhouse. I hobbled together my first one by by utilizing forums like this, but never really understood how it worked. Now, that script is no longer functioning and I'm stumped as to why. In addition, I'd like to add to that script, but am unsure as to how. Here's my situation and objective...
I have a spread sheet comprised of 2 sheets, and there are 2 things I'd like to happen when a specific dropdown is selected for any row.
First is for that row to move from sheet 1 to sheet 2. I achieved this by using the following script:
function onEdit(event) {
// assumes source data in sheet named Repairs
// target sheet of move to named Closed
// test column with yes/no is col 4 or D
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if(s.getName() == "Repairs" && r.getColumn() == 6 && r.getValue() == "Closed") {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Closed");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row);
}
}
This worked well for sometime, but recently stopped.
In addition to getting this to work again, the second function I would like to incorporate is to add a timestamp.
Ideally, once the row is moved to the 2nd sheet, I would like a column to be added that includes the time/date of the move.
If anyone is able to help with this I'd greatly appreciate it. If more detail is required please let me know and I'll do my best to provide it.
Thanks for reading!
I've modified your script to remove redundant commands. Everything you need to know about the edit is in the event object.
function onEdit(event) {
// assumes source data in sheet named Repairs
// target sheet of move to named Closed
// test column with yes/no is col 4 or D
var s = event.range.getSheet();
if( s.getName() == "Sheet1" && event.range.getColumn() == 6 && event.value == "Closed") {
var row = event.range.getRow();
var numColumns = s.getLastColumn();
var targetSheet = event.source.getSheetByName("Sheet2");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).moveTo(target);
target.offset(0,numColumns).setValue(new Date());
s.deleteRow(row);
}
}
Reference
onEdit(e) event object
Range.offset()

Moving rows with an updated timestamp to another Google Sheet

I'm using two scripts to achieve my goal. The first script inserts a timestamp in the adjacent column when an update is made to a field. This works great. The next script monitors the timestamp column and when the timestamp changes, copy entire row to a "recent updates" sheet. I'm then going to use the Awesome Table plugin to create a news feed for all the recent updates.
When the timestamp column is blank and an edit is made the timestamp is appropriately entered into the timestamp column. The second script picks it up and crops it into my "recent updates" sheet...
...but if a previous update was made and the timestamp field is already present the script runs without error, but does not copy the new row to "recent updates". How can I get the row to paste every time the timestamp field changes?
/**
* #file Copy row to new cell when date value changes
* {#link https://support.google.com/docs/thread/13191603}
*/
/**
* Runs the snippet.
* Please, register this function for EDIT event
* once from the owner of the Spreadsheet
*
* #param {GoogleAppsScript.Events.SheetsOnEdit} e
*/
function CopyUpdates(e) {
if (!e) return;
var currentSheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var currentRange = currentSheet.getActiveRange();
var currentRow = currentRange.getRow();
if (
e.value &&
currentSheet.getName() == "Open Actions - Cutover Punchlist" , "Open Actions - FSA Interfaces" , "Open Actions - General" &&
currentRow > 2 &&
currentRange.getColumn() == 9
) {
var dataRange = currentSheet.getRange(currentRow + ':' + currentRow);
var destinationSheet = currentSheet.getParent().getSheetByName("RecentUpdates");
var destinationRow = destinationSheet.getLastRow() + 1;
dataRange.copyTo(destinationSheet.getRange(destinationRow, 1), {
contentsOnly: true
});
}
}
The script already is working properly upon testing. Maybe there is something that interferes with your trigger which can be caused by the first function. Thus you will need to merge them.
I renamed it to onEdit(e) instead. I merged them since they are actually a subset of onEdit(e), just having different conditions. It should be fine to merge them under the same function.
Code:
var currentSheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
function onEdit(e) {
if (!e) return;
var currentRange = currentSheet.getActiveRange();
var currentRow = currentRange.getRow();
if ( e.value &&
currentSheet.getName() == "Open Actions - Cutover Punchlist" , "Open Actions - FSA Interfaces" , "Open Actions - General" &&
currentRow > 2 ) {
if (currentRange.getColumn() == 8) { // adjacent column (first function conversion, if H column is edited)
var adjacentCell = currentSheet.getRange('H' + currentRow);
var timestampCell = adjacentCell.offset(0, 1);
timestampCell.setValue(new Date());
// since H is edited, timestamp column is updated
// so we copy (regardless if the old value is blank or a timestamp)
copyUpdates(currentRow);
}
if (currentRange.getColumn() == 9) { // timestamp column (second function conversion, if I column is edited)
// edited timestamp manually, copy
copyUpdates(currentRow);
}
}
}
function copyUpdates(currentRow) {
var dataRange = currentSheet.getRange(currentRow + ':' + currentRow);
var destinationSheet = currentSheet.getParent().getSheetByName("RecentUpdates");
var destinationRow = destinationSheet.getLastRow() + 1;
dataRange.copyTo(destinationSheet.getRange(destinationRow, 1), {
contentsOnly: true
});
}
Sample Data:
Sample Testing:
1. Wrote "add timestamp" to "H3" (Should trigger your first function)
2. Wrote "add timestamp" to "H4" (Should trigger your first function)
3. Edited "H4" to "change timestamp" (Should trigger your first function)
4. Edited "I4" to "1/22/2021" (Should trigger your second function)
Sample Data outcome:
RecentUpdates outcome:

Trying to do Dynamic Equity Split calculations in Google Sheets

new to using javascript in Google Sheets. I am trying to create a sheet that automatically calculates what business partners will receive based upon their dynamic split percentage and the incoming money. The percentage comes from one cell, but each payment made to the partners will be entered in a column. Here's what I have so far:
/**
* Creates a Date Stamp if a column is edited.
* Also performs dynamic split calculations
*/
//CORE VARIABLES
// The column you want to check if something is entered.
var COLUMNTOCHECK = 13;
// Where you want the date time stamp offset from the input location. [row, column]
var DATETIMELOCATION = [0,-1];
// Where the calculations will be performed for the Partners.
var PARTNERONELOCATION = [0, 1];
var PARTNERTWOLOCATION = [0, 2];
var PARTNERTHREELOCATION = [0, 3];
// Sheet you are working on
var SHEETNAME1 = 'Sheet1'
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var partnerOnePercent = sheet.getRange("G2").getValue();
var partnerOnePaySource = sheet.getRange("M2").getValue();
var partnerTwoPercent = sheet.getRange("G3").getValue();
var partnerTwoPaySource = sheet.getRange("M2").getValue();
var partnerThreePercent = sheet.getRange("G4").getValue();
var partnerThreePaySource = sheet.getRange("M2").getValue();
//checks that we're on the correct sheet.
if(sheet.getSheetName() == SHEETNAME1 ) {
var selectedCell = ss.getActiveCell();
//checks the column to ensure it is on the one we want to cause the date and calculations to appear.
if( selectedCell.getColumn() == COLUMNTOCHECK) {
var dateTimeCell = selectedCell.offset(DATETIMELOCATION[0],DATETIMELOCATION[1]);
dateTimeCell.setValue(new Date());
var partnerOneCell = selectedCell.offset(PARTNERONELOCATION[0],PARTNERONELOCATION[1]);
partnerOneCell.setValue((partnerOnePercent/100)*partnerOnePaySource);
var partnerTwoCell = selectedCell.offset(PARTNERTWOLOCATION[0],PARTNERTWOLOCATION[1]);
partnerTwoCell.setValue((partnerTwoPercent/100)*partnerTwoPaySource);
var partnerThreeCell = selectedCell.offset(PARTNERTHREELOCATION[0],PARTNERTHREELOCATION[1]);
partnerThreeCell.setValue((partnerThreePercent/100)*partnerThreePaySource);
}
}
}
The thing I would like it to do is when I enter a payment into the column (column 13), Is for the payment to be split into the partner location cells (var partnerOneCell, var partnerTwoCell, var partnerThreeCell) that are offset from the cell that the payment amount is typed in, and I only want it to be calculated by the percentages as they are at the moment the payment amount is entered. Any help would be appreciated.
Right now it is only calculating based upon cell M2 (row 2, column 13). I want it to be able to calculate based upon the amount I enter in any cell within that column, and only the cell I am currently updating. I think that this has something to do with getActiveRange or something, but I'm not familiar enough with these methods.
Edit: Upon testing, it also seems that row 3 column 14 is reflecting a calculation of partnerOnePaySource*partnerOnePercent with PaySource coming from row 3 column 13 (M3), though I'm not sure why.
Alright everyone, after reading over my code, I realized how I could use the getActiveCell method within the PaySource variables.
var partnerOnePercent = sheet.getRange("G2").getValue();
var partnerOnePaySource = ss.getActiveCell().getValue();
var partnerTwoPercent = sheet.getRange("G3").getValue();
var partnerTwoPaySource = ss.getActiveCell().getValue();
var partnerThreePercent = sheet.getRange("G4").getValue();
var partnerThreePaySource = ss.getActiveCell().getValue();
With this I was able to fix my problem and it now works.

Edit script to apply across all sheets

This is the script that I am using currently. I want it to apply to all sheets in my document automatically. Please help. The following is the code.
/**
* Creates a Date Stamp if a column is edited.
*/
//CORE VARIABLES
// The column you want to check if something is entered.
var COLUMNTOCHECK = 1;
// Where you want the date time stamp offset from the input location. [row, column]
var DATETIMELOCATION = [0,1];
// Sheet you are working on
var SHEETNAME = '46'
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
//checks that we're on the correct sheet.
if( sheet.getSheetName() == SHEETNAME ) {
var selectedCell = ss.getActiveCell();
//checks the column to ensure it is on the one we want to cause the date to appear.
if( selectedCell.getColumn() == COLUMNTOCHECK) {
var dateTimeCell = selectedCell.offset(DATETIMELOCATION[0],DATETIMELOCATION[1]);
dateTimeCell.setValue(new Date());
}
}
}
I want the script to execute on every sheet so that whenever I add a new sheet the script runs automatically and helps me add a time stamp to column two when I add a value to column 1.
Please help.
I am a complete noob here and as such some detailed explanation will help me immensely.
Basically, just remove the if statement and the code will apply to EVERY sheet.
In the answer given below, I've also used some of the objects returned by the onEdit trigger.
/**
* Creates a Date Stamp if a column is edited.
*/
//CORE VARIABLE
// The column you want to check if something is entered.
var COLUMNTOCHECK = 1;
function onEdit(e) {
var sh = e.range.getSheet();
if (e.range.columnStart == COLUMNTOCHECK){
// edited the right column do something
var targetcell = sh.getRange(e.range.rowStart,2);
targetcell.setValue(new Date());
}
else {
// do nothing
}
}

Google Sheets Wildcards in if statements

I have a Google Sheet that has form responses. The e-mail address was not required, however it should have been. Either way, I am trying to back-fill the e-mail addresses (in order to make them ready to import as Spiceworks tickets, but I digress). I am going through and typing in usernames, but I want Sheets to auto-fill the domain. I was thinking I could do this by having it detect that the string ended in #, and then just adding the domain to it. Currently I have:
// assumes source data in sheet named Done 14-15
// test column with done is col 9 or I
if(s.getName() == "Done 14-15" && r.getColumn() == 9 && r.getValue() == "?#" ) {
var row = r.getRow();
var value = r.getValue();
r.setValue(value + "example.org");
var numColumns = s.getLastColumn();
s.getRange(row, 1, 1, numColumns).copyTo(target);
}
As you can see, I have a question mark for a wildcard. I have tried using an asterisk or a percentage sign as well, and not gotten anywhere. It will replace if I have literally ?# in there, but I want it to take anything# and append our domain.
RegEx should solve your problem.
Replace the r.getValue() == "?#" with
var regEx = new RegExp('.*#$')
if (regEx.test(r.getValue())) {
// your code
}
Instead of r.getValue() == "?#" you can write r.getValue().endsWith("#")
The email addresses can be easily updated like this:
var newValue = event.value.replace(/#$/,'#example.org');
Where the match is not found, the replacement will not happen... and newValue will equal the original value. Instead of checking for the match before deciding to do something, I'm suggesting doing it then checking the result.
Since you are entering the email addresses by hand, this is a good application of the onEdit() simple trigger and its event object.
function onEdit(event) {
var r = event.range;
var s = r.getSheet();
if (s.getName() == "Done 14-15" && r.getColumn() == 9 && r.getRow() > 1) {
// Replace an # at the end of the string with domain
var newValue = event.value.replace(/#$/,'#example.org');
// If value changed, write it back to spreadsheet
if (event.value !== newValue) {
event.range.setValue(newValue);
}
}
}
If you have rows that have already been edited and need to be checked, this function will take care of them. It uses the technique from How can I test a trigger function in GAS? to create a fake event, then passes it to the onEdit() trigger function.
// Call onEdit for each row in conversion sheet
function convertAllEmails() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName( "Done 14-15" );
var lastRow = sheet.getLastRow();
for (var row=1; row<lastRow; row++) {
var fakeEvent = {
range: sheet.getRange(row,9);
value: range.getValue();
};
onEdit( fakeEvent );
}
}

Categories