UPDATE: Hide named ranges (columns) with dropdown in same sheet - google-apps-script

I am attempting to create a script for a dropdown selection in cell B2, that when selected for one, will hide columns corresponding two the other choices in the list sheet.
The dropdown in cell B2 is has as its data validation criteria the following list:
"NORMAL," "HARD," "MAX POINTS"
And the following column ranges in the sheet correspond to the selections in parentheses:
Columns D-K ("NORMAL"), Columns L-S ("HARD"), Columns T-AA ("MAX POINTS")
I would like the script to work such that selection of one of the dropdown choices will hide the column ranges that correspond to the two other dropdown choices (i.e., if you select "HARD" it will hide Columns D-K as well as T-AA).
What am I doing wrong here? I'm sure quite a bit of course.
link
MODIFIED SCRIPT: I got this to work properly for each when run separately, but it requires me to to unhide after each time, otherwise it compounds what is hidden. I have it set to trigger on edit. It's so close, is there something about the trigger or perhaps I need to somehow add something that resets it to unhide all before I can change the selection? (not sure how though)
var ss=SpreadsheetApp.getActive();
var value1 = "NORMAL";
var value2 = "HARD";
var value3 = "MAX POINTS";
var activeSheet = ss.getActiveSheet();
var cell = activeSheet.getRange("B2").getValue();
function HideColumn() {
if(cell == value1) {
activeSheet.hideColumns(12, (27-7+1));
}
else if(cell == value2) {
activeSheet.hideColumns(4, (14-7+1));
activeSheet.hideColumns(21, (14-7+1));
}
else if(cell == value3) {
activeSheet.hideColumns(4, (22-7+1));
}
}

You have a dropdown in Cell B2.
There are three options: "Normal", "Hard", and "Max Points".
Depending on the value selected, you want to show the columns for the selected value and hide the columns for the other options.
The script uses the switch statement Doc ref as an alternative to an IF statement.
To run this answer:
copy to the Project editor,
create an installable onEdit() trigger. (enables the script to run when the dropdown cell is edited; and enables Event objects to be used)
// running as an installable onEdit() trigger
// watching cell B2
function showHideColumns(e){
var sheetName = "Today's Matchups"
// Logger.log(JSON.stringify(e)) // DEBUG
if (e.range.columnStart ==2 && e.range.rowStart ==2 && e.range.getSheet().getName() == sheetName){
// correct sheet and correct cell
// Logger.log("DEBUG: correct sheet and correct cell")
}
else{
// not the correct sheet/cell
// Logger.log("DEBUG: not the correct sheet/cell")
return
}
var ss=SpreadsheetApp.getActiveSpreadsheet()
var sheet = ss.getSheetByName(sheetName)
var value1 = "NORMAL";
var value2 = "HARD";
var value3 = "MAX POINTS";
var value1ColStart = 4
var value2ColStart = 12
var value3ColStart = 20
var valueSetNumCols = 8
// Columns D-K ("NORMAL"),
// Columns L-S ("HARD"),
// Columns T-AA ("MAX POINTS")
var cell = e.value
// Logger.log("DEBUG: dropdown value = "+cell)
switch (cell) {
case value1:
// NORMAL
// show NORMAL, hide Hard & Max Points
// show all columns (including NORMAL)
sheet.showColumns(value1ColStart,24)
// hide Hard
sheet.hideColumns(value2ColStart, valueSetNumCols)
// hide MaxPoints
sheet. hideColumns(value3ColStart, valueSetNumCols)
break
case value2:
// HARD
// show HARD, hide Normal & Max Points
// show all Columns
sheet.showColumns(value1ColStart,24)
// hide Normal
sheet.hideColumns(value1ColStart, valueSetNumCols)
// hide MaxPoints
sheet. hideColumns(value3ColStart, valueSetNumCols)
break
default:
// Max Points
// show Max Points, hide Normal & Hard
// show all Columns
sheet.showColumns(value1ColStart,24)
// hide Normal
sheet.hideColumns(value1ColStart, valueSetNumCols)
// hide Hard
sheet. hideColumns(value2ColStart, valueSetNumCols)
}
}

Related

How to show specific columns based on cell value in google sheets

I'm trying to write script that will achieve the following logic:
If cell J1 has a value of 1, show columns 1-10. If cell J1 has a value of 2, show columns 1-18. If cell J1 has a value of 3, show columns 1-26. If cell J1 has a value of 4, show columns 1-36.
Here' what I have so far:
function onOpen(e) {
hideVersions_(e);
}
function hideVersions_() {
// get current sheet
var sheet = e.source.getActiveSheet();
// get row and column of edited cell
var row = e.range.getRow();
var col = e.range.getColumn();
if (col == 10 && row == 1 && sheet.getSheetName() == 'Design') {
if (e.value === "2") {
sheet.hideColumns(19, 17); // hide column 19-36 (S-AJ)
sheet.showColumns(1,17); // show column 1-18 (A-R)
}
if (e.value === "3") {
sheet.hideColumns(27, 9); // hide column 27-36 (AB-AJ)
sheet.showColumns(1,25); // show column 1-26 (A-AA)
}
if (e.value === "4")
sheet.showColumns(1,35); // show column 1-36 (A-AJ)
}
else {
sheet.hideColumns(11, 25); // hide column 11-36 (K-AJ)
sheet.showColumns(1,9); // show column 1-10 (A-J)
}
}
As I tried to get this to work I noticed you had an Underscore on your Function Name
function hideVersions_() {
That kept me from running and testing that Function.
You also Passed e from the onOpen Event into the hideVersion Function, but did not declare e as a parameter.
Instead of the onOpen Event do you want to use the onChange Event? Even though you might be making other changes we can modify the script to only look at cell J1 on a specific sheet. You'll notice in the code below I added an if statement to check if e is Null, this allowed me to test the file in the editor with out the triggering event.
I think your logic in your if statement can be simplified, not sure why you are checking if the sheet is a certain sheet of the spreadsheet. I also tend to grab the Value I want instead of letting the e event be the most recently edited cell. This is why I removed the row and col check from your first if statement.
In your if statements you "stringed" your values, but I am assuming you are putting numbers into the cell, and therefore your === is expecting numbers on both sides. Removing the quotes fixed that issue.
In your if statements you hide the new cells and then show cells, I think this can be simplified by Showing all cells and then hiding the new cells.
Below is the code that I got to work that completes what you asked for:
function onOpen(e)
{
hideVersions(e);
}
function hideVersions(e)
{
// get current sheet
if ( e == null) // When you run this Function in Editor
{
var sheet = SpreadsheetApp.getActiveSheet();
}
else
{
var sheet = e.source.getActiveSheet();
}
// get Control Cell J1
var controlValue = sheet.getRange(1,10).getValue(); // J1 is Row 1 Col 10
Logger.log(controlValue);
var lastColumn = sheet.getLastColumn();
if (sheet.getSheetName() == 'Design')
{ //since we grabed the cell explicitly, only Need to check SheetName
if (controlValue === 2)
{
Logger.log("Hiding s-AJ");
sheet.showColumns(1, lastColumn); // show All
sheet.hideColumns(19, 17); // hide column 19-36 (S-AJ)
}
if (controlValue === 3)
{
Logger.log("Hiding AB-AJ");
sheet.showColumns(1, lastColumn) //Show All
sheet.hideColumns(27, 9); // hide column 27-36 (AB-AJ)
}
if (controlValue === 4)
{
Logger.log("Showing all");
sheet.showColumns(1,lastColumn); // show all
}
else
{
Logger.log("Hiding K-AJ");
sheet.showColumns(1, lastColumn); // Show All
sheet.hideColumns(11, 25); // hide column 11-36 (K-AJ)
}
}
}
This is what the onOpen() event object looks like:
{"authMode":"LIMITED","range":{"columnEnd":1,"columnStart":1,"rowEnd":1,"rowStart":1},"user":{"email":"redacted","nickname":"redacted"},"source":{}}
Please note: no e.value

Googlesheet dropdown list to show/hide rows

I want to have various cells that have a dropdownlist to show/hide certain rows
I have the following table
If I select A2 (dropdownlist with AMERICAS_a and AMERICAS_s), with the _s option, I want to hide only rows 3 to 6
If I select A7 (dropdownlist with EUROPE_a and EUROPE_s), with the _s option, I want to hide only rows 8 to 12
I am using an Appscript which works only for 1 of the continent. I want to make it work for any of the Watchcell
function onEdit(a) {
var watchSheet = "Sheet1";
var watchCell = "A2";
var sheet = a.range.getSheet();
if (sheet.getName() !== watchSheet ||
a.range.getA1Notation() !== watchCell) {
return;
}
sheet.hideRows(2, 5);
switch (a.value) {
case "AMERICAS_a":
sheet.showRows(2, 5);
break;
case "AMERICAS_s":
sheet.showRows(2, 1);
break;
default:
}
}
But I am unsure how to add A7 as another watchcell. I have repeated the function onEdit(e) but only the last onEdit function works.
I believe your goal is as follows.
Your Spreadsheet has the data validation rules for several cells in the column "A".
When the value of the dropdown list is changed, you want to run the script.
For example, when the suffix letters of the value of the dropdown list are _s, you want to hide rows until the next dropdown list.
For example, when the suffix letters of the value of the dropdown list are _a, you want to show rows until the next dropdown list.
Modification points:
In your showing script, in the case of both values of AMERICAS_a and AMERICAS_s, the rows are shown.
From your question, I thought that when the position of data validation rules is retrieved, the script might become simple.
When these points are reflected in a sample script, it becomes as follows.
Modified script:
function onEdit(e) {
const sheetName = "Sheet1"; // Please set the sheet name.
const { range, value } = e;
const sheet = range.getSheet();
const row = range.rowStart;
const datavalidations = sheet.getRange("A1:A" + sheet.getLastRow()).getDataValidations();
if (sheet.getSheetName() != sheetName || !datavalidations[row - 1][0]) return;
datavalidations.splice(0, row);
const n = datavalidations.findIndex(([a]) => a);
sheet[value.slice(-2) == "_s" ? "hideRows" : "showRows"](row + 1, n > -1 ? n : datavalidations.length);
}
Testing:
When this script is used, the following result is obtained.
Note:
This sample script is for your sample showing Spreadsheet. So, when you change the structure of the Spreadsheet, this script might not be able to be used. Please be careful about this.
When this script is directly run with the script editor, an error like TypeError: Cannot destructure property 'range' of 'e' as it is undefined. occurs. Please be careful about this. Please change the dropdown list of the column "A".
References:
Simple Triggers
hideRows(rowIndex, numRows)
showRows(rowIndex, numRows)

automatically move to the next cell on the page

I have a spreadsheet I designed in Google Sheets to input data at work and then a formula that determines if the part needs to be replaced and provides the part number required. I need either a macro or appScript that will start with a certain cell on the same sheet, highlight it, allow me to type a value in it, then either by pressing the ENTER or TAB key to move to the next cell on the page (Not necessarily the next door cell, but a cell in another column and/or row), -AND- based on a data validation check box determine which cells are selected. How do I write either a macro or appScript to do what I need? Which would be easier?
Reference
sheet.setActiveSelection()
Script:
Try
function onEdit(event){
var sh = event.source.getActiveSheet();
var rng = event.source.getActiveRange();
if (sh.getName() == 'mySheetName'){ // adapt
var addresses = ["E7","H7","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]);
}
}
}
Note:
This way you can determine the order in which the cells are selected.
If you have a script that copies cells into a master data sheet, you can take advantage of the range list. (by the way, you can find here how to transfer the data).
In case of protected sheet:
If your sheet is protected, except for the cells that need to be filled in, you can use a script that will search for them and reorganize them.
function onEdit(event) {
var sh = event.source.getActiveSheet();
var rng = event.source.getActiveRange();
if (sh.getName() == 'mySheetName') { // adapt
var addresses = listOfUnprotectedRanges()
var values = addresses.join().split(",");
var item = values.indexOf(rng.getA1Notation());
if (item < addresses.length - 1) {
sh.setActiveSelection(addresses[item + 1]);
}
}
}
function listOfUnprotectedRanges() {
var p = SpreadsheetApp.getActiveSheet().getProtections(SpreadsheetApp.ProtectionType.SHEET)[0];
var ranges = p.getUnprotectedRanges().map(r => [r.getA1Notation(), r.getRow(), r.getColumn()])
ranges = ranges.sort(function (a, b) { return a[2] - b[2]; }); // sort by columns
ranges = ranges.sort(function (a, b) { return a[1] - b[1]; }); // sort by ranges first
return ranges.map(r => r[0])
}

How do you show/hide rows based on a particular cell value?

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.

Apply conditional formatting

I have checked multiple threads for the result I am looking for and have not had any luck.
What I am trying to accomplish is change a cells font color and size based on a specific value. (if col B1:B equals "Changes:", change font to red and bold)
I was able to get the following to work:
function onEdit(e) {
if (e) {
var ss = e.source.getActiveSheet();
var r = e.source.getActiveRange();
// If you want to be specific
// do not work in first row
// do not work in other sheets except "Sheet3"
if (r.getRow() != 1 && ss.getName() == "Sheet3") {
// E.g. status column is 2nd (B)
status = ss.getRange(r.getRow(), 2).getValue();
// Specify the range with which You want to highlight
// with some reading of API you can easily modify the range selection properties
// (e.g. to automatically select all columns)
rowRange = ss.getRange(r.getRow(),1,1,19);
// This changes font color
if (status == 'CHANGES:') {
rowRange.setFontColor("#FF0000");
rowRange.setFontWeight("bold");
} else if (status == 'DELETIONS:') {
rowRange.setFontColor("##FF0000");
rowRange.setFontWeight("bold");
// DEFAULT
} else if (status == '') {
rowRange.setFontColor("#000000");
}
}
}
}
The problem with my script is I want it to run on a trigger ("on Open" or "on Change"), not "on Edit". I use a script to copy data from Sheet1 and paste it to Sheet3. After the copy/paste script runs, I want the formatting script to run on Sheet3 and edit the cells per the above.