Conditional Formatting to a specific column - google-sheets

I'm new to google sheets and I like to set conditional formatting to a specific column.
Starting on Row 8, Column D
I want to set the back ground color based on that is on the cell
If cell content like 'pass' then background color should be green (183,225,205)
If cell content like 'fail' then background color should be Red (213,139,139)
If cell content like 'pending' then background color should be Yellow (252,232,178)
So on edit of the cell I want to check the value of the cell
function onEdit(e){
var actualSheetName =
SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getName()
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet()
var allValuesOnColumA = ss.getRange("A1:A").getValues()
var lastRow = allValuesOnColumA.filter(String).length + 1
var range = ss.getRange(8, lastRow)
conditionalFormatting(8, 4, (lastRow +1) -8, 1, actualSheetName)
}
I started a conditionalFormatting Function but I can't get it to work.
function conditionalFormatting(rowN, colN, optRows, optCols, spreadsheetName)
{
var mySpreadsheet = SpreadsheetApp.getActiveSpreadsheet()
var mySheet = mySpreadsheet.getSheetByName(spreadsheetName)
var range1Values = mySheet.getRange(rowN,colN, optRows, optCols).getValues()
//debugger
for (var row in range1Values)
{
for (var col in range1Values[row])
{
for(var i=0, iLen=range1Values.length; i<iLen; i++)
{
if(range1Values[row][col] == 'pass')
{
//debugger
Logger.log('Local Row ' + locRow + ' Local Col ' + locCol)
var pendingCell=mySheet.getRange(locRow, locCol)
pendingCell.setBackground("green")
}
else if(range1Values[row][col] == 'fail')
{
// Logger.log('fail in')
//mySheet.getRange(range1Values.offset(row, col, 1, 1).getA1Notation()).setBackgroundColor(213,139,139) //red
//Logger.log('fail Out')
}
else if(range1Values[row][col] == 'pending')
{
//Logger.log('Pending in')
//mySheet.getRange(range1Values.offset(row, col, 1, 1).getA1Notation()).setBackgroundColor(252,232,178) //Yellow
//Logger.log('Pending Out')
}
}
}
}
}
Edit:
The desired result should look like:

Try this (works on cells that have the keywords 'pass', 'fail', and 'pending' starting in row 8 for column D as specified):
function onEdit(e){
var actualSheetName = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getName();
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var lastRow = ss.getLastRow();
conditionalFormatting(8, 4, (lastRow +1) - 8, 1, actualSheetName);
}
function conditionalFormatting(rowN, colN, optRows, optCols, spreadsheetName) {
var mySpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var mySheet = mySpreadsheet.getSheetByName(spreadsheetName);
var range1Values = mySheet.getRange(rowN,colN, optRows, optCols).getValues();
for (var row in range1Values) {
for (var col in range1Values[row]) {
if (range1Values[row][col].toLowerCase() == 'pass' || range1Values[row][col].toLowerCase() == 'passed') {
mySheet.getRange(Number(row)+rowN, Number(col)+colN).setBackground('green')
Logger.log('Contents PASS')
} else if (range1Values[row][col].toLowerCase() == 'fail' || range1Values[row][col].toLowerCase() == 'failed') {
mySheet.getRange(Number(row)+rowN, Number(col)+colN).setBackgroundRGB(213,139,139)
Logger.log('Contents FAIL')
} else if (range1Values[row][col].toLowerCase() == 'pending') {
mySheet.getRange(Number(row)+rowN, Number(col)+colN).setBackgroundRGB(252,232,178)
Logger.log('Contents PENDING')
} else {
Logger.log('Contents did not meet any of the criteria')
}
}
}
}
Out of curiosity, is there any reason you aren't just using the built-in conditional formatting feature in Google Sheets? Although this code works, I find it much easier to just use the built-in conditional formatting feature.
EDIT (FOR ADDITIONAL QUESTION IN COMMENTS):
Modified code to not be case sensitive with keywords and also included keywords 'passed' & 'failed'
Hope this helps!

Related

Jump to a specific cell based on Active Cell

I'm completely new to Java Scipt although over the years I've messed around with VBA & Macros in Excel. I am now using Google Sheets almost exclusively, hence needing to learn Java.
I'm trying to jump to a specific cell (E5) if the current cell is (C14). This is what I've put together so far using scripts 'borrrowed' from others.
ie On entry of data in Cell C13 and pressing Enter, focus goes to Cell C14. The next data is to go into Cell E5.
function onSelectionChange(e) {
var sheetNames = ["Score Input"]; // Set the sheet name.
var ranges = ["C14"]; // Set the range to run the script.
var range = e.range;
var sheet = range.getSheet();
var check = ranges.some(r => {
var rng = sheet.getRange(r);
var rowStart = rng.getRow();
var rowEnd = rowStart + rng.getNumRows();
var colStart = rng.getColumn();
var colEnd = colStart + rng.getNumColumns();
return (range.rowStart >= rowStart && range.rowEnd < rowEnd && range.columnStart >= colStart && range.columnEnd < colEnd);
});
if (check) {
jumpToDetails();
}
};
function jumpToDetails() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Score Input");
var goToRange = sheet.getRange('c14').getValue();
//sheet.getRange(goToRange).activate();
SpreadsheetApp.getActive().getRange('E5').activate();
}
It worked, or did until I inserted a row in the sheet, and even though I have changed the associated cell addresses, it now doesn't work?
Two questions. 'Why has it stopped working'? and 'Is there a simpler way to do it'?
I prefer using onEdit(e) on range C13 and jump to E5
For instance here is a script that jump from one cell to the following in addresses'list
function onEdit(event){
var sh = event.source.getActiveSheet();
var rng = event.source.getActiveRange();
if (sh.getName() == 'Score Input'){ // adapt
var addresses = ["C13","E5","E10","H10","E13","H13","E16"]; // adapt
var values = addresses.join().split(",");
var item = values.indexOf(rng.getA1Notation());
if (item < addresses.length - 1){
sh.setActiveSelection(addresses[item + 1]); // except last one
}
}
}
if you want to be able to add rows and columns, play with named ranges (for instance ranges names 'first', 'second, 'third')
function onEdit(event){
var sh = event.source.getActiveSheet();
var rng = event.source.getActiveRange();
if (sh.getName() == 'Score Input'){
var addresses = ["first","second","third"];
var values = addresses
.map(ad => myGetRangeByName(ad))
.join().split(",");
var item = values.indexOf(rng.getA1Notation());
if (item < addresses.length - 1){
sh.setActiveSelection(addresses[item + 1]); // except last one
}
}
}
function myGetRangeByName(n) {
return SpreadsheetApp.getActiveSpreadsheet().getRangeByName(n).getA1Notation();
}
reference
class NamedRange

How can I make a function in google sheet run on all the previous cells above until the previous function

I want to make a function in google sheet, for example here "sum" I want it sum all above cells until the previous another function
So if I copied it to another row it will sum all above cell until the previous function also (3 of pic).
Try these custom functions
// mike steelson
function sumSinceLastFormula(rng){
var lastRow = SpreadsheetApp.getActiveRange().getRow()-1
var col = SpreadsheetApp.getActiveRange().getColumn()
var sum=0
for (var i = lastRow; i>1; i--){
var value = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange(i,col).getFormula()
if (value && value.toString().charAt(0) === '=') {break}
else {sum += SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange(i,col).getValue()}
}
return sum
}
function countaSinceLastFormula(rng){
var lastRow = SpreadsheetApp.getActiveRange().getRow()-1
var col = SpreadsheetApp.getActiveRange().getColumn()
var counta=0
for (var i = lastRow; i>1; i--){
var value = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange(i,col).getFormula()
if (value && value.toString().charAt(0) === '=') {break}
else {counta++}
}
return counta
}
function countifSinceLastFormula(rng,crit){
var lastRow = SpreadsheetApp.getActiveRange().getRow()-1
var col = SpreadsheetApp.getActiveRange().getColumn()
var countif=0
for (var i = lastRow; i>1; i--){
var value = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange(i,col).getFormula()
if (value && value.toString().charAt(0) === '=') {break}
else {if (SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange(i,col).getValue()==crit) {countif++} }
}
return countif
}
to automatically update the values, add reference to previous cells
=sumSinceLastFormula(F$2:F8)
when in F9, and copy where you need it.
https://docs.google.com/spreadsheets/d/1iXDbYDd_5rmHa1E41zobTWB6MKvABR1ERpCgcValIng/copy
You can calculate the cumulative by a single formula like
={"sum";arrayformula(SUMIF(ROW(A2:A),"<="&ROW(A2:A),F2:F))}

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

Copy Row of data based on two conditions to a sheet which is opened by ID or URL

I have a code that helps me copy a row of data based on a condition in a given column. I have a sheet called "Master" which has around 1000 rows of data. I want to move a row of data to a sheet called "Master Responses" if column 1 of "Master" has the word "Positive" or "Negative" in it. I used the or function (||) in the IF STATEMENT to select the condition (that is if "Positive" is entered or "Negative") but the row is only copied when I type "Positive" in the first column. When I type "Negative" in the first column the row is not copied. Also, I wanted to know how the code should be modified if I had to call the "Master Responses" sheet by using ".openByID or .openByURL". I have attached the code, please feel free to edit it. I am new to scripting and have been stuck on this for over a month. Any help would be appreciated. Thanks in advance.
function onEdit()
{
var sheetNamesToWatch = ["Master"];
var columnNumberToWatch = 1;
var valuesToWatch = ["Positive"];
var valuesToWatch1 = ["Negative"];
var targetSheetsToMoveTheRowTo = ["Master Responses"];
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getActiveCell();
if(sheetNamesToWatch.indexOf(sheet.getName()) != -1 &&
valuesToWatch.indexOf(range.getValue()) != -1 ||
valuesToWatch1.indexOf(range.getValue()) != -1 && range.getColumn()
==columnNumberToWatch)
{
var targetSheet = ss.getSheetByName(targetSheetsToMoveTheRowTo[valuesToWatch.indexOf(range.getValue())]);
var targetRange = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
sheet.getRange(range.getRow(), 1, 1,
sheet.getLastColumn()).copyTo(targetRange);
}
}
I'm not sure about .openByID or .openByURL, however this should fix the problem with "Negative".
I also added extra parenthesis on the first if statement so that it was clear to me what it was checking on.
function onEdit()
{
var sheetNamesToWatch = ["Master"];
var columnNumberToWatch = 1;
var valuesToWatch = ["Positive"];
var valuesToWatch1 = ["Negative"];
var targetSheetsToMoveTheRowTo = ["Master Responses"];
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getActiveCell();
if((sheetNamesToWatch.indexOf(sheet.getName()) != -1) && ((valuesToWatch.indexOf(range.getValue()) != -1) ||
(valuesToWatch1.indexOf(range.getValue()) != -1)) && (range.getColumn() ==columnNumberToWatch))
{
if (valuesToWatch.indexOf(range.getValue()) != -1)
{
var targetSheet = ss.getSheetByName(targetSheetsToMoveTheRowTo[valuesToWatch.indexOf(range.getValue())]);
}
else
{
var targetSheet = ss.getSheetByName(targetSheetsToMoveTheRowTo[valuesToWatch1.indexOf(range.getValue())]);
}
var targetRange = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
sheet.getRange(range.getRow(), 1, 1,
sheet.getLastColumn()).copyTo(targetRange);
}
}

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

Resources