Conditional formatting on Multiple Rows based on cell value - google-sheets

In my Google Form, I have custom formatting setup for my dropdown lists that will highlight the entire row based on the value chosen.
Custom formula is
=$B3="Highlight: 1 Row"
But how can I highlight multiple rows if I wanted to?
Google Sheet Example: Highlight Multiple Rows
Screenshot Example:
UPDATE (01-26-2017)
The purpose of this "multi row" feature will be used inside a more robust spreadsheet that generates Google Forms from a Google Sheet. For this particular use case, there are many different "dropdowns" for the user to choose from that control where the user can type. This can quickly become hard to navigate the longer your sheet becomes. The best way it seems to handle this is through conditional formatting.
Highlight Multiple Rows (Test Google Sheet)
Create Form From Sheet (YouTube Tutorial)
Create Form From Sheet (Google Sheet)
Create Form From Sheet (Google Script)

Use this custom formula
=$B$3="Highlight: 2 Row"
Make sure the range you want this rule to apply to, is two rows long
e.g: B3:Z4
Now when "Highlight: 2 Row" is entered in B3 two rows should be highlighted.
UPDATE:
Below is a google script that should work
function onEdit(e) {
var sh, colors, rows, rowsBefore;
sh = e.source.getActiveSheet();
colors = ["#fff2cc", "#fce5cd", "#d9ead3", "#cfe2f3"];
if (sh.getName() !== 'Example' || e.range.columnStart !== 2 || e.range.rowStart < 8 || typeof e.value == 'object') return;
rowsBefore = e.oldValue ? e.oldValue.replace(/\D/g, '') : 1;
rows = e.value.replace(/\D/g, '');
sh.getRange(e.range.rowStart, 4, rowsBefore, sh.getLastColumn()).setBackground("white")
sh.getRange(e.range.rowStart, 4, rows, sh.getLastColumn()).setBackground(colors[rows - 1])
}
Change sheet name (and range) to suit. Note that this script is on a simple onEdit trigger: it will be fired when an edit is done in col B of the sheet 'Example'. Do not try to run the script by clicking the 'play' button in the script editor as it will return an error. See if that helps ?

Related

QUERY IMPORTRANGE while keeping row position

I have two spreadsheets, one client facing and one internal facing, that use IMPORTRANGE and QUERY + IMPORTRANGE to display data between one another.
The internal sheet is used to write copies for social media posts, quality check them and give approval. Once approval is given the client sheet needs to update to show the copies on the identically named pages AND in the correct rows.
Approval is given by ticking a checkbox in the internal sheet and the QUERY + IMPORTRANGE formula then pulls that into the client sheet. However, my abilities stop where I have to display this in the correct row position no matter which of the tickboxes are checked.
=iferror(QUERY(IMPORTRANGE("https://docs.google.com/spreadsheets/d/1CIXhcuTigYbggmPjBKpvnH7P-cjBDQfSIcmKN6_0T5M/edit#gid=2018991957","Cloud in FS Survey!C2:N"),"SELECT Col1, Col2, Col3, Col4, Col5, Col6 WHERE Col11 = TRUE"),"No copies approved")
I've seen some discussions of having a second sheet for of the categories (there are 8 in the non-redacted document) and using VLOOKUP to match an ID to the imported row of data, hence I've created 'Row' columns in all tabs on both sheets with the unique row number. However, I want to avoid having hidden tabs in the client facing sheet where they can be revealed by the client.
Any assistance would be appreciated.
Many thanks,
Mark
There are 2 ways to deal with it. If you a add serial number in sheet 1 where approvals are given, you may add another element to your query by adding order by serial no. column ASC
Else you could do the same with order by date column ASC
This way new additions will add below the imported data because they will always be in chronology and not mess up the order of older data.
Having direct importranges where static data exists is always risky.
Alternately, you could also use ID thing without creating an additional hidden sheet, direct vlookups with importrange nested inside the vlookup.
For example, =arrayformula(vlookup(search key, importrangexxx, index, false)
The best solution would be to have a hidden sheet. But all of the above can be decent alternate if you're not dealing with thousands of rows.
If you don't want to use helper sheet or column, you can use Apps Script and onEdit Trigger.
Using onEdit Trigger, you can run a function automatically when a user click the checkbox. Inside that function is a list of commands that will write data to the client side.
Example:
To start with Apps Script:
Go to Tools -> Script Editor.
In your script editor, delete the code in Code.gs
Paste the code provided below.
Click Save.
Code:
function showToClientSide(e) {
var val = e.value;
var range = e.range;
var row = range.getRow();
var col = range.getColumn();
var sheet = range.getSheet();
var clientSS = SpreadsheetApp.openById("Insert Client Sheet ID here")
if(val == "TRUE" && row > 1 && col == 13){ // check if checkbox is checked
var data = sheet.getRange(row, 3, 1, 9).getValues(); //get data from internal
var sh = clientSS.getSheetByName("Cloud in FS Survey"); //client sheet
sh.getRange(row, 3, 1, 9).setValues(data); //write internal data to client
}else if(val == "FALSE" && row > 1 && col == 13){
var sh = clientSS.getSheetByName("Cloud in FS Survey"); //client
sh.getRange(row, 3, 1, 9).clearContent(); //delete data when unchecked
}
}
To setup your Installable Trigger (onEdit):
In the left menu of your Apps Script, click Triggers
Click Add Trigger
Copy the setup below.
Save and Authorize the script.
Testing:
Internal Sheet:
Client Sheet:
Checkbox checked:
Internal:
Client:
Checkbox unchecked:
Internal:
Client:
References:
Installable Triggers
Event Objects
Class Range
Class Sheet

Google Sheets - Auto import data from sheet 1 and not have it delete from the new sheet 2

I used IMPORTRANGE to connect my two google sheets. Sheet1 has information on things we need to order, Sheet2 is used as a storage for everything once it has been ordered. However, I want the data in Sheet1 to be deleted as it is ordered but then it deletes from Sheet2.
How can I get information from Sheet1 to auto copy to Sheet2 based on the Order#, and not be deleted when it is removed from Sheet1?
You need a script if you want to achieve that by deleting the rows in Sheet1.
If you want to use only Sheets standard formulas, there is another option that might satisfy the use case, but without actually deleting the rows from Sheet1.
What you need to do is add a new yes/no or checkbox column (named "deleted" or similar) to Sheet1. When you want to "delete" a row, you will just check the checkbox in that column.
On Sheet2 you will wrap the IMPORTRANGE into QUERY, something like
=QUERY(IMPORTRANGE(...), "select * where Col1=TRUE")
in case you first column in Sheet1 is a checkbox that is selected if a row is marked as "deleted".
If a script is an option, and you want the row actually deleted in Sheet1, and still can add a dedicated column for checkbox (preferably the first column), then this will solve your issue.
See Script and Output for reference.
Script
function onEdit(e) {
var range = e.range;
var value = e.value;
var sheet = range.getSheet();
// if checkbox checked is in Sheet1!A:A
if (sheet.getName() == 'Sheet1' && value == 'TRUE' && range.getColumn() == 1) {
// fetch what row number is ticked
row = range.getRow();
// append the data on the checked row on the last row of Sheet2
sheet.getParent().getSheetByName('Sheet2').appendRow(sheet.getRange(row, 2, 1, sheet.getLastColumn()).getValues().flat());
// delete row in Sheet1 afterwards
sheet.deleteRow(row);
}
}
Script above will transfer then delete the row upon checking the row's checkbox
Output:
Note:
Creating the script without adding a checkbox on the first column will have to be a bit harder and a hassle since onEdit doesn't hold the oldValue when deleting a row.
OnChange can detect deletion of row but still doesn't have the deleted values saved.

Google Sheets: Pop up message when a specific value is entered in a column

This is my first go at creating something in Apps Script for Google Sheets and I'm a bit stuck/overwhelmed. In the reading I've done I think what I'm attempting is rather basic. I'm just not getting to the solution, so I need a nudge...
Need:
I have a sheet that is tracking equipment that is checked out and returned to a central area.
The sheet has multiple pages with identical layouts.
On each page I have one column where (3) different options can be chosen from a dropdown list.
IN, OUT, and UNAVAILABLE
For each of the (3) entry options, I would like a popup message to appear when the entry is changed.
So in the range of F2:F100, if the entry is changed to "OUT" from "IN" I would like a pop-up to appear with a message of "Clear all fields to the right." and an "OK" button.
I have found a lot of examples to make a pop up when ANY field is changed, or when a sheet is opened. I'm stuck on limiting these pop-ups to only select fields/ranges/pages
Thank you all for the help.
SOLUTION
You can refer to this sample script below that runs via onEdit trigger, where the pop-up message will only run if any selected cell is under column F & if that cell's value was changed to "OUT" on any sheet on a spreadsheet file:
function onEdit() {
var ss = SpreadsheetApp.getActive();
//Check if selected cell is in column F (or col #6) was changed to "OUT"
if(ss.getActiveCell().getColumn() == 6 & ss.getRange(ss.getActiveCell().getA1Notation()).getValue() == "OUT"){
SpreadsheetApp.getUi().alert('Clear all fields to the right.');
}
}
If ever you need to add more conditions like if you only want to run the script to a specific sheet name, you can add ss.getSheetName() == '[Name of the sheet]' on the if condition separated by & sign, as seen on the sample below:
if(ss.getSheetName() == 'Sheet2' & ss.getActiveCell().getColumn() == 6 & ss.getRange(ss.getActiveCell().getA1Notation()).getValue() == "OUT"){
SpreadsheetApp.getUi().alert('Clear all fields to the right.');
}
Sample Result:
If a selected cell on col F is changed from IN to OUT via a drop-down option:
A pop-up message "Clear all fields to the right." will show on the sheet

Is is possible in google sheet to protect certain columns, but allow rows to be added/removed?

I'm using arrayformulas to populate certain columns of my sheet, depending on values in other sheets. Occasionally users accidentally will put some value in these columns, and this will stop arrayformula from working. I want to protect these columns, but still allow adding/editing/deleting rows.
Consider this example spreadsheet: I want Id row to be protected, but allow addition/deletion of rows.
https://docs.google.com/spreadsheets/d/1Dnj7OE5XZL09gllHVwPgv-5GRoM-lxVCxTCI_-kURdM/edit#gid=0
Is this possible at all with Google Sheets?
You can't directly disable input but you can use Data Validation instead
By going to Data > Data Validation and filling it with the following:
Cell range: YourSheet!C2:C
Criteria: Custom formula is - =C2:C = A2:A & "["&B2:B&"]"
On invalid data: Reject input
Appeareance: Optional message
Once you've done this, try to fill some cell in the C column and you'll see a message: There was a problem - Your optional message
As a different approach you can use Apps Script Simple Triggers
By going to Tools > Script Editor and copying the following code:
function onEdit(e) {
var column = e.range.getColumn();
var sheet = SpreadsheetApp.getActiveSheet();
if (column === 3) {
e.range.setValue("");
}
}
Which is more like an "undo" function.
References
Simple Triggers
Event Objects > onEdit
rows could be added by brute force with this formula:
=ARRAYFORMULA(ROW(INDIRECT("1:"&ROWS(A:A)+1)))
but escalation cant be controlled

Copying columns with a specific value from one sheet to another sheet

I am using Google Docs Sheet for editing
I want to find out a way to copy the "Name" and "Variety" columns into another sheet where the "Germination %" column is 0.
Is there a way to do it automatically?
An apps script solution, using the onEdit() trigger or a time-based one. Depending on the size of the Sheet I'd recommend using the time based one.
Eg.
function onEdit( e ){
rang = e.range.getRange();
if( rang.getColumn() == 9 && rang.value() == "0" )
SpreadshettApp.openById(newId).appendRow( e.source.getRange(rang.getRow(), 1, 1, -1).getValues() );
}
Or you could display the results using the FILTER function.

Resources