Can I Simplify my Script in Google Sheets? - google-sheets

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

Inserting Timestamp in Google Spreadsheet

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.

Update cell in row with current date when there is a change in that row

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));
}
}

How to stop timestamp updating when column is edited after first edit

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.

Search a row for matches

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");
}
}
}

Combining two setvalue strings

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);
}

Resources