Set cell value using if statement - google-apps-script

I'm trying to use an if statement in scripts to set cell values once conditions are met, however its not working and i can't figure out why.
I need to do it using scripts rather than formulas in the sheet itself
var mainWSname = "Exposure"
function onEdit(e){
var activeCell = e.range();
var r = activeCell.getRow()
var c = activeCell.getColumn()
var val = activeCell.getValue();
var wsName = activeCell.getSheet().getName()
if(wsName === mainWSname && c === 2 && val === "Match"){
wsName.getRange(r, 3).setValue("18")
wsName.getRange(r, 4).setValue("80")
}
}

Try this modification:-
var mainWSname = "Exposure"
function onEdit(e){
var activeCell = e.range;
var r = activeCell.getRow()
var c = activeCell.getColumn()
var val = e.value;
var wsName = activeCell.getSheet()
if(wsName.getName() === mainWSname && c === 2 && val === "Match"){
wsName.getRange(r, 3).setValue("18")
wsName.getRange(r, 4).setValue("80")
}
}
Reference:
Event Object

Related

Multiple Columns for First Level Dependent Dropdown List

I have a spreadsheet with 4 columns that i am concerned with:
Group (Ferrous/Non-ferrous/etc.)
RI No. (Unique identifier)
Item Description (Name of the chosen RI No. item)
Supplier (Sellers of chosen RI No.)
The flow of data happens like this:
I select Group (say, Ferrous) --> In RI No. column, an automatic dropdown is created, showing RI Nos. of all items under Ferrous category show up --> I select a particular RI No. from this drop-down --> Item Description appears through VLOOKUP --> A drop-down of all sellers selling that item show up in in Supplier column.
Now, I wrote a code which does this work perfectly, but i was wondering if there was a way to make it so that:
I select Group (say, Ferrous) --> In RI No. column AND in Item Description column, an automatic dropdown is created, showing RI Nos. of all items under Ferrous category show up --> If I select RI No., item description gets populated/If I select Item Description, RI No. gets populated --> corresponding suppliers list show up as they do now.
Sample spreadsheet: https://docs.google.com/spreadsheets/d/16qv-OgCIezEuaOm8fQdq91FiQbBny4MzGRIho9ZCY-E/edit#gid=1605627126
The code:
var ws = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var wsopt = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("sorted items");
var opts = wsopt.getRange(2,1,wsopt.getLastRow()-1,13).getValues();
var firstlevelcolumn = 2;
var secondlevelcolumn = 5;
var thirdlevelcolumn= 6;
var wsopt2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("supplier details");
var opts2 = wsopt2.getRange(3,1,wsopt2.getLastRow()-1,12).getValues();
function onEdit(e)
{ var activecell= e.range;
var val = activecell.getValue();
var r= activecell.getRow();
var c= activecell.getColumn();
var wsName= activecell.getSheet().getName();
if (wsName == "JPS")
{
if (wsName == "JPS" && c == firstlevelcolumn && r > 2)
{ applyFirstLevelValidation(val,r);}
if (wsName == "JPS" && c == secondlevelcolumn && r > 2)
{ applySecondLevelValidation(val,r);}
}//JPS
else if (wsName == "DDNI")
{
if (wsName == "DDNI" && c == firstlevelcolumn && r > 2)
{applyFirstLevelValidation(val,r);}
if (wsName == "DDNI" && c == secondlevelcolumn && r > 2)
{ applySecondLevelValidation(val,r);}
}//DDNI
}//close onEdiT
function applyFirstLevelValidation(val,r)
{
if(val=== "")
{
ws.getRange(r,secondlevelcolumn).clearContent();
ws.getRange(r,secondlevelcolumn).clearDataValidations();
ws.getRange(r,thirdlevelcolumn).clearContent();
ws.getRange(r,thirdlevelcolumn).clearDataValidations();
} else
{
ws.getRange(r,secondlevelcolumn).clearContent();
ws.getRange(r,secondlevelcolumn).clearDataValidations();
ws.getRange(r,thirdlevelcolumn).clearContent();
ws.getRange(r,thirdlevelcolumn).clearDataValidations();
var filteredopts = opts.filter(function(o){return o[0]===val});
var listToApply = filteredopts.map(function(o){return o[1]});
var cell=ws.getRange(r,secondlevelcolumn);
applyValidationToCell(listToApply,cell);
}//close else
}//close applyFirstLevelValidation
function applySecondLevelValidation(val,r)
{
if(val=== "")
{
ws.getRange(r,thirdlevelcolumn).clearContent();
ws.getRange(r,thirdlevelcolumn).clearDataValidations();
} else
{
ws.getRange(r,thirdlevelcolumn).clearContent();
ws.getRange(r,thirdlevelcolumn).clearDataValidations();
var firstlevelcolvalue = ws.getRange(r,firstlevelcolumn).getValue();
var filteredopts2 = opts2.filter(function(o){return o[6]===firstlevelcolvalue && o[4]===val});
var listToApply2 = filteredopts2.map(function(o){return o[0]});
var cell2=ws.getRange(r,thirdlevelcolumn);
applyValidationToCell(listToApply2,cell2);
}//close else
}
function applyValidationToCell(list,cell)
{
var rule = SpreadsheetApp.newDataValidation().requireValueInList(list).build();
cell.setDataValidation(rule);
}

How can I create a filter area in Google Sheets using Google Apps Script?

enter image description here
I want to create a filter area in A1 and A2 cells so that when I put drivers' name on these cells, the table (A:C) should be filtered according to the value entered in A1 and A2. Can someone explain me how to write Apps Script to perform such function?
Thank you in advance!
Try, with both names in C1 and C2 (pls, change sheet name as necessary)
function onEdit(e) {
var col = 3
var sh = e.source.getActiveSheet()
if (sh.getName() != "Sheet1") return;
if (e.range.columnStart > col || e.range.columnEnd < col) return;
if (e.range.rowStart > 2) return;
var names = sh.getRange(1, col, 2, 1).getValues().flat()
var range = sh.getRange(3, col, sh.getLastRow() - 2, sh.getLastColumn() - col + 1);
var filter = sh.getFilter();
if (filter !== null) filter.remove();
if (countNotOccurrences(names, '') == 0) return;
var hiddenNames = range.getValues().slice(1).map(row => row[0]).filter(who => names.indexOf(who) == -1);
range.createFilter();
var criteria = SpreadsheetApp.newFilterCriteria().setHiddenValues([...new Set(hiddenNames)]).build();
sh.getFilter().setColumnFilterCriteria(col, criteria);
}
const countNotOccurrences = (arr, val) => arr.reduce((a, v) => (v !== val ? a + 1 : a), 0);
Driver Data
function MyFunction() {
const ss = SpreadsheetApp.getActive()
const sh = ss.getSheetByName('Sheet0');
const osh = ss.getSheetByName('Sheet1');
osh.clearContents();
const sr = 3;
const dA = sh.getRange(1,1,2).getValues().flat();
const name = dA[0] + ' ' + dA[1];
const nameColumn = 1;
const vo = sh.getRange(sr,1,sh.getLastRow() - sr + 1, sh.getLastColumn()).getValues().filter(r => r[nameColumn -1] == name);
osh.getRange(1,1,vo.length,vo[0].length).setValues(vo);
}
It can be something like this probably:
function onEdit(e) {
if (e.range.columnStart > 1) return;
if (e.range.rowStart > 2) return;
filter_table(e.value);
}
function filter_table(name) {
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getRange(3,1,sheet.getLastRow(),3);
var data = range.getValues();
var hidden_values = data.map(x => x[0]).filter(x => x != name);
var filter = sheet.getFilter();
if (filter !== null) filter.remove();
range.createFilter();
var criteria = SpreadsheetApp.newFilterCriteria().setHiddenValues(hidden_values).build();
sheet.getFilter().setColumnFilterCriteria(1, criteria);
}
It filteres the range A3:C every time you edit cell A1 or cell A2.
But I'm not sure though what do you want to get when the two cells contain different names.
Update
Here is the 'multi-filter' solution :
function onEdit(e) {
if (e.range.columnStart > 1) return;
if (e.range.rowStart > 2) return;
var sheet = SpreadsheetApp.getActiveSheet();
if(sheet.getName() != 'Filter') return; // <-- to limit the trigger only one sheet 'Filter'
var range = sheet.getRange(1,1,sheet.getLastRow(),3);
var [name1, name2, ...data] = range.getValues();
var hidden_values = data.map(x => x[0])
.filter(x => x != name1[0] && x != name2[0]);
var filter = sheet.getFilter();
if (filter !== null) filter.remove();
range.offset(2,0).createFilter();
if (name1[0] + name2[0] == '') return;
var criteria = SpreadsheetApp.newFilterCriteria()
.setHiddenValues(hidden_values).build();
sheet.getFilter().setColumnFilterCriteria(1, criteria);
}
If both of the cells are empty you will see all the rows.

I want to get a timestamp on edit in my datetime row, but I need it to also timestamp when I copy/paste multiple rows in google script

I'm trying to add timestamps to my datetime row on edit. What I'm getting right now is if one row is edited at a time it works. However, what I need is to timestamp every row when I copy/paste values in over multiple rows.
function getDatetimeCol(){
var SHEET_NAME = 'Queue';
var DATETIME_HEADER = 'datetime (+48h for archive)';
var headers = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(SHEET_NAME).getDataRange().getValues().shift();
var colindex = headers.indexOf(DATETIME_HEADER);
return colindex+1;}
function onEdit(e) {
var SHEET_NAME = 'Queue';
var ss = SpreadsheetApp.getActiveSheet();
var cell = ss.getActiveCell();
var datecell = ss.getRange(cell.getRowIndex(), getDatetimeCol());
if (ss.getName() == SHEET_NAME && cell.getColumn() == 1 && !cell.isBlank() && datecell.isBlank()) {
datecell.setValue(new Date()).setNumberFormat("yyyy-MM-dd hh:mm");
}
};
function onEdit(e) {
//e.source.toast('entry');
const sh = e.range.getSheet();
if (sh.getName() == 'Queue' && e.range.columnStart == 1) {
//e.source.toast('cond');
let col = {};
sh.getRange(1, 1, 1, sh.getLastColumn()).getValues()[0].forEach((h, i) => { col[h] = i + 1 });
for (var i = 0; i < e.range.rowEnd - e.range.rowStart + 1; i++) {
let rg = sh.getRange(e.range.rowStart + i, col['datetime (+48h for archive)']);
if (rg.isBlank() && sh.getRange(e.range.rowStart,1).getValue() != '') {
//e.source.toast('if');
rg.setValue(new Date()).setNumberFormat("yyyy-MM-dd hh:mm");
}
}
}
}

Sheets Script to Clear cell only when both target cells are cleared

I got a script thanks to help of another user Marios but I required a tweak and was asked to create a new post.
The original script
function onEdit(e){
var row = e.range.getRow();
var col = e.range.getColumn();
var dateTime = 4;
var targetColumn = 9;
var startRow = 19;
var ws = "Tracking Sheet";
var as = e.source.getActiveSheet();
if(col === targetColumn && row >= startRow && as.getName() === ws )
{
let range = as.getRange(row,dateTime);
e.range.getValue() == '' ? range.setValue('') : range.setValue(new Date());
}
}
I tried to modify by adding an else statement but was unsucessful.
This works great for in all aspects but only for one targetColumn and I would like to have 2 targetColumns and then the script would only clear the dateTime cell if both of the targetColumns are seen to be empty or cleared.
var row = e.range.getRow();
var col = e.range.getColumn();
var dateTime = 4;
var targetColumn = 9;
var targetColumn = 11;
var startRow = 19;
Any help or a modification to the current script would be most welcomed,
Explanation:
You assigned two different values to the same variable:
var targetColumn = 9;
var targetColumn = 11;
but that simply means targetColumn will only have the last value assigned to it, which is 11.
My approach would be to put the target columns into an array and then check whether both of them are empty before you delete the date value from the desired cell.
Solution:
function onEdit(e){
var row = e.range.getRow();
var col = e.range.getColumn();
var dateTime = 4;
var targetColumns = [9,11];
var startRow = 19;
var ws = "Tracking Sheet";
var as = e.source.getActiveSheet();
if(targetColumns.includes(col) && row >= startRow && as.getName() === ws )
{
let range = as.getRange(row,dateTime);
let t1 = as.getRange(row,targetColumns[0]).getValue();
let t2 = as.getRange(row,targetColumns[1]).getValue();
t1 == '' && t2 == '' ?
range.setValue('') :
range.setValue(new Date());
}
}

Google Apps Script spreadsheet date manipulation

I have three scripts that are in a google docs spreadsheet. In this spreadsheet, in column H (or column 8), if I type an "x", the script changes it into that days date. After a few days, every date in column H has changed from a date to just a number. The numbers look like this: 40492, 40494, 40511. I am not sure what is causing this. Maybe it's something that is wrong in my script. I've pasted them below. Any ideas?
function onEdit(e) {
var colorA = "yellow";
var colorB = "#dddddd";
var colorC = "#dddddd";
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Purchase Orders");
var range = e.source.getActiveRange();
var sheetName = SpreadsheetApp.getActiveSheet().getName();
if (sheetName == "Purchase Orders") {
// 3 is column C
if (range.getColumn() == 3 && range.getValue() != "") {
sheet.insertRowAfter(range.getRow());
var r = range.getRow() + 1;
sheet.getRange("A" + r + ":H" + r).setBackgroundColor(colorC);
}
}
var col = e.source.getActiveRange().getColumn();
if(col == 3 || col == 8) {
var rows = sheet.getMaxRows();
//column C
var rangeC = sheet.getRange("C1:C"+rows);
var valuesC = rangeC.getValues();
//column H range
var rangeH = sheet.getRange("H1:H"+rows);
var colorH = rangeH.getBackgroundColors();
var valuesH = rangeH.getValues();
//iterate over each row in column C and H
//then change color
for (var row = 0; row < valuesC.length; row++) {
//check for columnC and column H
var hRow = colorH[row];
if (valuesC[row][0] != "" && valuesH[row][0] == "") {
hRow[0] = colorA;
} else if (valuesH[row][0] != "") {
hRow[0] = colorB;
}
}
sheet.getRange("H1:H" + rows).setBackgroundColors(colorH);
}
}
And this one
function onEdit(e) {
var ss = e.source.getActiveSheet();
var r = e.source.getActiveRange();
// 1 is A, 2 is B, ... 8 is H
if (r.getColumn() == 8 && r.getValue() == "x") {
r.setValue(Utilities.formatDate(new Date(), "MST", "yyyy-MM-dd"));
}
}
And this last one
ss = SpreadsheetApp.getActiveSpreadsheet();
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var menuEntries = [ {name: "New PO", functionName: "NewPO"}];
ss.addMenu("New PO", menuEntries);
}
function NewPO() {
SpreadsheetApp.getActiveSheet().insertRowsBefore(1,6);
// Adjust this range accordingly, these are the cells that will be
// copied. Format is getRange(startRow, startCol, numRows, numCols)
ss.getSheetByName("PO Form").getRange(1, 1, 6, 8)
.copyTo(SpreadsheetApp.getActiveSheet().getRange(1, 1, 6, 8));
}
In OnEdit, you probably want to set the format for that cell as well. setNumberFormat(numberFormat) appears to be the function you are after.
http://code.google.com/googleapps/appsscript/class_range.html#setNumberFormat