I have built a Google Sheet using scrips to automatically timestamp certain events on the sheet upon edit.
Two of the timers are built to time just the first edit of two particular cells:
function onEdit() {
var s = SpreadsheetApp.getActiveSheet();
if( s.getName() == "SUBARU" ) {
var r = s.getActiveCell();
if( r.getColumn() == 3 ) {
var nextCell = r.offset(0, 19);
if( nextCell.getValue() === '' )
nextCell.setValue(new Date());
}
}
}
Two additional timers time any instance two other cells are edited:
function onEdit() {
var s = SpreadsheetApp.getActiveSheet();
if( s.getName() == "SUBARU" ) {
var r = s.getActiveCell();
if( r.getColumn() == 9 ) {
var nextCell = r.offset(0, 15);
nextCell.setValue(new Date());
}
}
}
And three other timers time when three specific entries happen in one particular cell:
function onEdit() {
var s = SpreadsheetApp.getActiveSheet();
if( s.getName() == "SUBARU" ) {
var r = s.getActiveCell();
if( r.getColumn() == 5 ) {
var nextCell = r.offset(0, 20);
if( r.getValue() === "3 - Menu Ready")
nextCell.setValue(new Date()).setNumberFormat('dd-MM-yyyy HH:mm:ss');
}
}
}
My problem is that I have seven scripts per sheet, and 4 sheets using the scripts (so 28 total scripts running). My Google quote is 30 scripts running at the same time. Can anyone think of ways I can simplify these scripts to run quicker or combine any so that I have fewer running at any given time?
Any help would be greatly appreciated!!!
My suggestion for this is to group all logic into one "onEdit" function.
Here's my code approach/suggestion to handle it:
if(s.getName() == "SUBARU") {
//put the logic to handle sheet SUBARU
} else if(s.getName() == "ABC") {
//put the logic to handle sheet ABC
} else if(s.getName() == "DEF") {
//put the logic to handle sheet DEF
}
Related
I want to add the current data and time in a specific column with any edit in whole sheet. I tried to write a script and got a little bit success but could not get desired result.
When I run the below script then it insert the time stamp in the very next column but I want to insert the timestamp in a specific column e.g in Column D.
Secondly it only works when I change values in a cell, but I want to add time stamp also when I change even color of a cell too.
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() ) { //checks the column
var nextCell = r.offset (0,1) ;
// if( nextCell.getValue() === '' ) //is empty?
nextCell.setValue(new Date() );
}
}
}
Kindly help me to get the desired result.
if you want to insert the timestamp in a specific column e.g in Column D:
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() ) { //checks the column
var nextCell = s.getRange('D' + r.getRow()); // change D to any column needed
// if( nextCell.getValue() === '' ) //is empty?
nextCell.setValue(new Date() );
}
}
}
Notes:
onEdit(e) runs when a user changes a value in a spreadsheet.
tests show onEdit runs when cells borders are changed
onEdit does NOT run when color is changed, font is changed.
I found two scripts. Since they both were an onEdit() function they couldn't work side by side, I tried to merge them.
I am using this sheet for a very basic inventory of things I sell / keep track of what I have sold.
I want two things;
First: I would like the cell in column A to change to the current date whenever I do a change on that row.
Second: If I change the value in column B to "Sold" I want it to be moved to a different sheet (as well as getting a new date due the change).
Column B has the following choices:
-Ja (as in stock)
-Bokad (as in booked)
-Såld (as in sold)
The name of the Sheets are:
-Blocket (inventory)
-Sålda (sold)
function onEdit(event) {
// assumes source data in sheet named Blocket
// target sheet of move to named Sålda
// test column with "Såld" is col 2
var s = event.source.getActiveSheet(),
cols = [2],
colStamp = 1,
ind = cols.indexOf(event.range.columnStart)
if (s.getName() == 'Blocket' || ind == -1) return;
event.range.offset(0, parseInt(colStamp - cols[ind]))
.setValue(e.value ? new Date() : null);
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if(s.getName() == "Blocket" && r.getColumn() == 2 && r.getValue() == "Såld")
{
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Sålda");
if(targetSheet.getLastRow() == targetSheet.getMaxRows()) {
targetSheet.insertRowsAfter(targetSheet.getLastRow(), 20); //inserts 20 rows
after last used row
}
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row);
}
}
See if this works
function onEdit(e) {
var s, targetSheet;
s = e.source.getActiveSheet();
if (s.getName() !== 'Blocket' || e.range.columnStart == 1) return;
s.getRange(e.range.rowStart, 1)
.setValue(new Date());
if (e.range.columnStart == 2 && e.value == "Såld") {
targetSheet = e.source.getSheetByName("Sålda");
if (targetSheet.getLastRow() == targetSheet.getMaxRows()) {
targetSheet.insertRowsAfter(targetSheet.getLastRow(), 20); //inserts 20 rows
}
s.getRange(e.range.rowStart, 1, 1, s.getLastColumn()).moveTo(targetSheet.getRange(targetSheet.getLastRow() + 1, 1));
}
}
I have a code that puts a timestamp in when column 1 is edited and then a second timestamp when another column has the word 'collected' input to it. From this I then work out time it took to be collected and use that data. However if someone edits column 1 again it updates the timestamp so I'm looking for a script to allow it to only do it on first edit. Here is my current script;
function onEdit(e) {
var sheet = SpreadsheetApp.getActiveSheet();
if( sheet.getName() == "CC sheet" ) {
//Update timestamp when changed to collected
var range = sheet.getActiveCell();
Logger.log(range.getColumn())
if( range.getColumn() == 7.0 ) { //if we are in the status column...
var nextCell = range.offset(0, 2);
if(range.getValue() == 'Collected')
if( nextCell.getValue() === '' ) //is empty?
nextCell.setValue(new Date());
}
//end
}
if(e.source.getActiveSheet().getName() !== 'CC sheet' || e.range.columnStart !== 1) return;
e.range.offset(0, 5).setValue(e.value ? new Date() : null);
}
It is the bottom bit I need to change to only update on first edit. Any help with this would be much appreciated.
replace last row or code with this one:
if (e.range.offset(0, 5).getValue() === '') {
e.range.offset(0, 5).setValue(e.value ? new Date() : null);
}
it's the same 'is empty?' check, as you have in the first part of script.
I'm very new to Google Sheets and particularly using the Apps Script API to make functions for Sheets.
My goal is to search 3 cells in a row, and if two of three contain an 'X', the third which does not turns blue.
Currently the sheet has conditional formatting as follows:
X = Green
Empty = Red
? = Orange
! = Blue
So the intent is to change the Empty cell to ! if the other two cells in the row are X.
Image for reference:
Essentially, I need a function which can check a range of cells for their contents, but I don't know how to properly use the API, if someone could give me a bit of help it would be greatly appreciated.
Note: This is NOT for a project of any sort, this is just for my friends and myself.
Edit
My thoughts were to have the range as the function parameter (A1:C1 for instance) and then access the cell's data for the range and check them against each other. My issue is that I don't know how to use the API to get this data.
If the scenario mentioned before applies, you can use this method:
function checkRow() {
var ss = SpreadsheetApp.getActive();
var activeCell = ss.getActiveCell();
var currentRow = activeCell.getRow();
var currentCol = activeCell.getColumn();
var allRange = ss.getRange("A1:C3");
var activeValue = activeCell.getValue();
var secondCell, thirdCell;
if(activeValue == "x")
{
if ( currentCol == 1 )
{
secondCell = allRange.getCell( currentRow, currentCol+1 );
thirdCell = allRange.getCell( currentRow, currentCol+2 );
} else if ( currentCol == 2 )
{
secondCell = allRange.getCell( currentRow, currentCol-1 );
thirdCell = allRange.getCell( currentRow, currentCol+1 );
}
else if ( currentCol == 3 )
{
secondCell = allRange.getCell( currentRow, currentCol-1 );
thirdCell = allRange.getCell( currentRow, currentCol-2 );
}
if ( secondCell.getValue() == "x" && thirdCell.getValue() == "" )
{
thirdCell.setValue("!");
thirdCell.setBackground("#00FFFF");
} else if (thirdCell.getValue() == "x" && secondCell.getValue() == "" )
{
secondCell.setValue("!");
secondCell.setBackground("#00FFFF");
}
}
}
I'm trying to adapt my inEdit script to give not just a timestamp but also add a "2" in another field,
I thought the following would work but only the date works and it ignores my "2".
What am I missing for both the date and 2 to appear onEdit?
function onEdit() {
var s = SpreadsheetApp.getActiveSheet();
if( s.getName() == "Sanshiro" ) { //checks that we're on the correct sheet
var r = s.getActiveCell();
if( r.getColumn() == 6 ) { //checks the column
var nextCell = r.offset(0, -5);
if( nextCell.getValue() === '' ) //is empty?
nextCell.setValue(new Date());
nextCell = r.offset(0, 10);
if( nextCell.getValue() === '' ) //is empty?
nextCell.setValue("2");
} }
I don't know if the check if the 'nextcell' is empty is really needed ? you still want to update that cell if a new edit takes place, right ? Anyway, I think you can simplify your script to:
function onEdit(e) {
if (e.source.getActiveSheet()
.getName() !== "Sanshiro" || e.range.columnStart !== 6) return //checks that we're on the correct sheet
e.range.offset(0, -5)
.setValue(new Date());
e.range.offset(0, 10)
.setValue(2);
}