I am trying something reasonably simple but can’t get it to work:
I want to hide multiple columns and/or rows based on the value of a cell.
I have it working with a simple script however it seems to only do its job when the trigger cell in question has the value input manually, i.e. I have a drop-down list of “0” & “1” and when I change it manually from “0” to “1” it all works.
However, the cell in question gets its value itself from a simple if condition and even though the value is, in the end, the same it seems the script is not working in such a case.
I would be grateful for any help.
That's the script I found online and is apart from not being triggered correctly in my case very useful:
//TITLE:
//Hide a row if a value is inputted.
//**GLOBALS**
// Sheet the data is on.
var SHEET = "TEST2";
// The value that will cause the row to hide.
var VALUE = "1";
// The column we will be using
var COLUMN_NUMBER = 1
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var activeSheet = ss.getActiveSheet();
//Ensure on correct sheet.
if(SHEET == activeSheet.getName()){
var cell = ss.getActiveCell()
var cellValue = cell.getValue();
//Ensure we are looking at the correct column.
if(cell.getColumn() == COLUMN_NUMBER){
//If the cell matched the value we require,hide the row.
if(cellValue == VALUE){
activeSheet.hideRow(cell);
};
};
};
}
The cell(s) in question use this simple line:
=IF(INDIRECT("A4")=1,"0",IF(E10="NON-FACS",1,0))
Current outcome is: Nothing happens (except when input manually)
The expected outcome is: column number 1 should be hidden
Related
In the for-loop of the onEdit function, I am attempting to activate a cell by referencing the location of another cell. This is done to allow the function to activate the cell directly to the right of the currently active cell, no matter which cell between D2 and D27 is currently active. The endgame here is to be able to enter a part number into column D, then have the cell directly to the right activate so a quantity can be entered.
var ss = SpreadsheetApp.getActive()
var sheet1 = SpreadsheetApp.getActive().getSheetByName("Sheet1")
function selectedRange() {
return sheet1.getA1Notation();
}
//Set active cell to A2 (cell below Name header) when file is opened.
function onOpen() {
sheet1.getRange('A2').activate();
}
//Look for name from scanner
function onEdit(e) {
var range = e.range;
if (range.getA1Notation() === 'A2') {
var active = ['Alpha', 'Beta'].includes(range.getValue()) ? "D2" : "A2"; //D7 for
correct responses, A2 for incorrect (repeats the process)
sheet1.getRange(active).activate();
}
//Does this cell contain a valid part number?
var values = sheet1.getRange('D2:D27').getValues();
for(var i in values){
if(values[i][0].match("PLA-OPTRET1-")!=null){ //Retainer Element 1
//cell contains "PLA-OPTRET1-". Do something
//sheet1.getRange('B2').activate();
range.offset(0,1);
break;
}
if(values[i][0].match("PLA-OPT1-")!=null){ //Element 1
//cell contains "PLA-OPT1-". Do something
sheet1.getRange('B2').activate();
break;
}
}
}
When I run the code and meet the criteria to trigger the case with the offset, nothing happens. I don't get any errors - the cell that I just wrote my product number into remains highlighted.
I know the event is triggering because I have tried activating a cell with an absolute reference using A1 notation, but this will not work for my uses.
You can do it using range.offset(row, column).
range.offset(0,1);
To activate,
range.offset(0,1).activate();
We have a spreadsheet that automatically attributes status for each row based on information enteredin cells located in column T. The stauts appear on column M showing open, pending and closed. I'm using the following code:
// Sheet the data is on.
var SHEET = "DLT";
// The value that will cause the row to hide.
var VALUE = "Closed"
// The column we will be using
var COLUMN_NUMBER = 14
function onEdit (e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var activeSheet = ss.getActiveSheet();
//Ensure on correct sheet.
if(SHEET == activeSheet.getName()){
var cell = ss.getActiveCell()
var cellValue = cell.getValue();
//Ensure we are looking at the correct column.
if(cell.getColumn() == COLUMN_NUMBER){
//If the cell matched the value we require,hide the row.
if(cellValue == VALUE){
activeSheet.hideRow(cell);
};
};
};
}
I understand that there is a mistake on the code, as the spreadsheet changes automatically the "stauts" value on column M as soon as information is entered on column T, and this code this won't work because technically the Active.cell bit is telling the script to look at the current cell being edited (which in this case will be the cell on column T as this is the last field to be filled before triggering the spreadsheet change status to closed.)
Doubt is, how to make the script still looks into the current row being edited but consider the value on column M and not the active cell.
function onEdit (e) {
var sh = e.range.getSheet();
//column 20 is T
if(sh.getName()== 'DLT' && e.range.columnStart == 20 ){
SpreadsheetApp.flush();//This will provide enough time to allow the spreadsheet to complete all of it's calculations.
//column 13 is M
if(e.range.offset(0,-7).getValue()=="Closed") {
sh.hideRows(e.range.rowStart);
}
};
}
I've got a list of hyperlinks stored in a range and I would like to have the data validation in a different column allow you to choose from the link "text" and then paste the full cell formula. The way it works at the moment the data validation cell only contains the cell value.
Link to example sheet
Some sheet function code:
C2: =HYPERLINK("#rangeid=901904080","Cell E2")
C3: =HYPERLINK("#rangeid=951806747","Cell E3")
C4: =HYPERLINK("#rangeid=743771733","Cell E4")
Auto recorded script code:
function DV() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.getRange('C2').activate();
spreadsheet.getRange('A2:A').setDataValidation(SpreadsheetApp.newDataValidation()
.setAllowInvalid(false)
.requireValueInRange(spreadsheet.getRange('Sheet2!$C$2:$C'), true)
.build());
};
Is there something I can do to the script code to make it paste the formula in stead of the value? Or is the best option to try and trigger on when a new value is chosen and then do something like:
Att! Pseudo code
onEdit(e){
//pseudo code
if e.range in column A{
var sourceRange = sheet.getRange("C2:C")
var index = sourceRange.indexOf(e.range.getValue())
e.range.setFormula(sourceRange[index].getFormula())
}
}
It's a bit tricky, but I think I found the solution using the DataValidationBuilder. It's similar to yours but using getFormulas() along with the validation property requireValueInList() which asks for an array of Strings.
The main issue is when you select the formula, the "invalid rule" notification jumps in, as the formula changes the cell value to "Cell C3", for example. So in order to work around this paradox you need set setAllowInvalid(boolean) to false:
function DV(){
var spreadsheet = SpreadsheetApp.getActive();
var cells = spreadsheet.getRange('A2:A');
var rule = SpreadsheetApp.newDataValidation()
.requireValueInList(spreadsheet.getRange('C2:C').getFormulas())
.setAllowInvalid(false)
.build();
cells.setDataValidation(rule);
}
As the 500 items limit isn't acceptable in my case I have solved the problem by checking for a data validation rule on an edited cell and if one exists, swap the value for the data.
MWE:
function onEdit(e){
if (e.range.getDataValidation() != null){
swapValueForFormula(e.range);
}
function swapValueForFormula(cell){
var val = cell.getValue();
var rule = cell.getDataValidation();
var source = rule.getCriteriaValues()[0];
var vals = source.getValues();
var index = vals.join().split(",").indexOf(val);
if (index != -1){
var formula = source.getCell(index+1, 1).getFormula()
cell.setFormula(formula)
}
}
Thanks for all your comments and suggestions that lead me to this answer.
I am attempting to put some show/hide row logic into a google sheet based on a response from a data validation list.
If the user selects the value 'General Account Call' from the data validation list in cell C42 I would like to show rows 43 through to 53 and rows 78 through to 101. Also if a user ticks a check box in cell C40 I would like to show row C41.
I don't know if I can 'monitor' multiple cells with the onEdit function.
I have found a couple of similar(ish) scripts which hide a row based on a value in a cell in the same row and have tried amending them to no avail. I have then tried going back to basics and putting something to monitor a cell and hide a different row, again to no avail
function onEdit(e) {
var ss = SpreadsheetApp.getActive()
var sheet = SpreadsheetApp.getActiveSheet()
var cell = sheet.getRange('D39')
var cellContent = cell.getValue()
if(cellContent === Y) {
Sheet.hideRow(40)
}
}
Your code should be:
function onEdit() {
var ss = SpreadsheetApp.getActive();
var sheet = ss.getActiveSheet();
var cell = sheet.getRange('D39');
var cellContent = cell.getValue();
if(cellContent == 'Y') {
sheet.hideRows(11);
}
}
There were a few things wrong:
Even if the ss and sheet declaration work, you were getting the
Sheet from the SpreadsheetApp and not from ss, so ss was not
being used.
cellContent == 'Y' is the correct way to compare the cell to a String, if you remove the quotes, it will interpret it as a variable Y that doesn't exist. Also, === is not necessary as it checks the type and the value, and we only want the value. In fact, it will return false even if the values are the same but are a different type
You wrote Sheet.hideRow instead of sheet.hiderow. Javascript is case-sensitive, so be careful with that!
The method hideRow hides the rows in a given Range, so we have to use hideRows, were you can use the integer (11 in this case) to hide the entire row.
You didn't put any semicolons ;
You didn't get any of these errors as I suppose you were testing the code changing the value of D39. If you execute the code manually, all of these will show up.
So, in order to hide several rows depending of a few cells, you have to get the event information (e), and get the cell that is being edited.
Do an if like this:
var cell = e.range.getA1Notation(); //Gets the Cell you edited
var cell_value = e.range.getValue(); //Gets the value of the cell
if(cell == 'C42' && cell_value == 'General Account Call'){
sheet.showRows(43, 10);
sheet.showRows(78, 23);
}
if (cell == 'C40' && cell_value){ //The checkbox value returns true or false
sheet.showRows(41);
}
The second number in showRows is the number of rows that will be shown.
I am very new at writing code and have a limited understanding so please be gentle!
I have been trying to expand on the code made on this question.
I have had limited success and am now stuck, I was hoping someone would be kind enough to point me in the right direction or tell me what I am doing wrong.
So, the scenario: A need to have an auto-incrementing "Job Reference" for booking in netbook repairs to the IT dept I work for. This booking is made via a Google Form and I can get the code in the link to work perfectly but! I was hoping to have a little more than a simple count - 1,2,3,4,5 and so on. Ideally the job ref would be displayed as JR0001, JR0002 and so on.
So, my attempt at code!
The code which user: oneself submitted which works perfectly.
function onFormSubmit(e) {
// Get the active sheet
var sheet = SpreadsheetApp.getActiveSheet();
// Get the active row
var row = sheet.getActiveCell().getRowIndex();
// Get the next ID value. NOTE: This cell should be set to: =MAX(A:A)+1
var id = sheet.getRange("P1").getValue();
// Check of ID column is empty
if (sheet.getRange(row, 1).getValue() == "") {
// Set new ID value
sheet.getRange(row, 1).setValue(id);
}
}
The first thing I tried was to simply add another variable and add it to the .setValue
function onFormSubmit(e) {
// Get the active sheet
var sheet = SpreadsheetApp.getActiveSheet();
// Get the active row
var row = sheet.getActiveCell().getRowIndex();
// Get the next ID value. NOTE: This cell should be set to: =MAX(A:A)+1
var id = sheet.getRange("X1").getValue();
// Set Job Reference
var jobref = "JR";
// Check of ID column is empty
if (sheet.getRange(row, 1).getValue() == "") {
// Set new ID value
sheet.getRange(row, 1).setValue(jobref+id);
}
}
This worked as far as getting "JR1" instead of 1 but the auto-increment stopped working so for every form submitted I still had "JR1" - not really auto-increment!
I then tried setting up another .getValue from the sheet as the Job Ref
function onFormSubmit(e) {
// Get the active sheet
var sheet = SpreadsheetApp.getActiveSheet();
// Get the active row
var row = sheet.getActiveCell().getRowIndex();
// Get the next ID value. NOTE: This cell should be set to: =MAX(A:A)+1
var id = sheet.getRange("X1").getValue();
// Set Job Reference
var jobref = sheet.getRange("X2").getValue();
// Check of ID column is empty
if (sheet.getRange(row, 1).getValue() == "") {
// Set new ID value
sheet.getRange(row, 1).setValue(jobref+id);
}
}
Same result - a non incrementing "JR1"
I then tried concatenating the working incrementing number with my job ref cell and then calling that in the script.
function onFormSubmit(e) {
// Get the active sheet
var sheet = SpreadsheetApp.getActiveSheet();
// Set Job Reference
var jobref = sheet.getRange("X2").getValue();
// Get the active row
var row = sheet.getActiveCell().getRowIndex();
// Get the next ID value. NOTE: This cell should be set to: =MAX(A:A)+1
var id = sheet.getRange("X1").getValue();
// Check of ID column is empty
if (sheet.getRange(row, 1).getValue() == "") {
// Set new ID value
sheet.getRange(row, 1).setValue(jobref);
}
}
Same result the value doesn't increment
I don't understand why the number stops incrementing if I add other variables and don't understand how to add the leading zeros to the incrementing number. I get the feeling that I am trying to over complicate things!
So to sum up is there a way of getting an auto-incrementing ref that is 6 characters long - in this scenario first form JR0001 second submit JR0002 and so on.
I would really like some pointers on where I am going wrong if possible, I do want to learn but I am obviously missing some key principles.
here is a working solution that uses the "brand new" Utilities.formatString() that the GAS team just added a few days ago ;-)
function OnForm(){
var sh = SpreadsheetApp.getActiveSheet()
var startcell = sh.getRange('A1').getValue();
if(! startcell){sh.getRange('A1').setValue(1);return}; // this is only to handle initial situation when A1 is empty.
var colValues = sh.getRange('A1:A').getValues();// get all the values in column A in an array
var max=0;// define the max variable to a minimal value
for(var r in colValues){ // iterate the array
var vv=colValues[r][0].toString().replace(/[^0-9]/g,'');// remove the letters from the string to convert to number
if(Number(vv)>max){max=vv};// get the highest numeric value in th column, no matter what happens in the column... this runs at array level so it is very fast
}
max++ ; // increment to be 1 above max value
sh.getRange(sh.getLastRow()+1, 1).setValue(Utilities.formatString('JR%06d',max));// and write it back to sheet's last row.
}