I am trying to apply conditional formatting to more than one range. The formatting is always the same but the cell that contains the condition is not.
For example:
`=OR($B$11="金",$B$11="木")` //this custom formula applies to range C5:Q14
'=OR($B$22="金",$B$22="木") //this custom formula applies to range C16:Q25
The first formula checks the cell B11 for condition
The second formula checks the cell B22 for the condition
It works as intended. However I have to set up many such ranges and if I copy or paste, the formatting ranges just get added to the ones already in the formula and they all check the same cell for the condition. I can achieve what I need if I set the condition for every range manually but I would like to know if there is a better way via sheets formula or a script if formulas are not viable.
Please see the sheet for the example
https://docs.google.com/spreadsheets/d/1G0eUibjNKlZ1fDm9id5SPFNlF392cuEPzNDMB8E5jyU/edit?usp=sharing
I see 3 possible abstractions of your problem.
1) Conditional formatting by groups of rows of known length. 2) How to identify the row index of the top of a section in a copy-paste friendly way if helper column is permitted. 3) Detect the top most non-blank cell in a column above a particular row.
Of course, 3) is most general. But if you only need 1) or 2), it's better to use simpler solutions. So I'll comment on each.
Conditional formatting by groups of rows of known length
Use a combination of index and match. (If the requirement grows more complicated, also consider using indirect.)
For example, if you need rows in groups of 11 to refer to the head row, you can do
=match(index($A:$A,floor(row(B1)/11)*11+1,1),{"金";"木"},0)
in B1:C11; given that you have weekday character in A:A every 11 rows.
Recall that in Conditional Formatting, we specify a (fixed) range and a formula that refers to relative ranges. Google Sheet will then iterate the cell indices over the (fixed) range -- meaning, starting with the top-left most cell, when you move down 1 row, the (relative) ranges in the formula will all have row index adds +1; when you move right 1 column, the (relative) ranges in the formula will all have column index adds +1. $ sign functions normally.
The only (relative) range in the formula that is free to iterate is B1. Thus what happens here is that: as you move along (fixed) range B1:C11, for example when you reach C10, the (relative) range in the formula becomes C10 (coincidentally) because C10 is 9 rows down and 1 column right from the top-left most cell in range B1:C11.
Test:
Input
Result
Identify/Designate row index of the top of a section
If you can use a helper column, there is an easy way to designate a row index as a function of the position of a section.
For example, let's say your section spans B1:D10. You want to be able to copy-paste this section to B21:D21 and you want everything else to keep.
It's simple if you can tolerate using A:A just for labeling the top of the section.
You do not need to know the number of rows per section ahead of time.
In A1, input =row(A1). In A2, input =A1. Now drag the formula across your section, ie. to A10.
Now you can put conditional formatting in C1:D10 as simply
=match(index($B:$B,A1,1),{"金";"木"},0)
and of course you can use simpler formulas for string comparison.
Detect the top most non-blank cell in a column above a particular row
If you don't have a fixed template for your section with known number of rows, and you need to keep your sheet clean of helper columns, then the only way is to detect the last non-empty cell above a given row in the column you have your weekday characters.
A number of variations are possible here. You can detect non-empty cell. Or you can detect the presence of a string from a list of string. You can retrieve the content of the cell or you can get the row index. etc. We are going to do the simplest thing here.
Suppose you have your weekday characters in A:A and you need conditional formatting in B:C. Then, in Conditional Formatting tab, put range as B:C, and formula as follows.
=match(+SORT($A$1:$A1,$A$1:$A1<>"",,ROW($A$1:$A1),),{"金";"木"},0)
What happens here is that +SORT($A$1:$A1,$A$1:$A1<>"",,ROW($A$1:$A1),) will pick out the content of the last non-empty cell in column A relative to the row in question.
Here is how SORT achieves the result for us:
The 2nd input of SORT will evaluate into a column of boolean with TRUE meaning non-empty. $A$1:$A1 relative to B1:C means to pick out cells in A1:A above and including the cell in question. Leaving the 3rd input empty means descending, which in turn means TRUE comes before FALSE. + tells Google Sheet to output the first element in an array output. Up to this point, +SORT($A$1:$A1,$A$1:$A1<>"",) will output the top-most non-empty cell. Within all the non-empty cells, you want the last one. Hence, the 4th input for row index and 5th input for descending. The non-empty cell with the highest row index in A1:A is the cell you want.
It is up to you as the Asker to identify the exact requirements for your task at hand.
I would say it is important that the Asker abstracts the requirements and state them in the question --- as opposed to seeking how to assess the task at hand in answers.
That is what often distinguishes a programming question that everyone else can search easily, thus learn and adapt from vs an outsourcing query.
Apps Script Solution
AFAIK the best way is with Apps Script
With a script like this:
function createRule() {
// Get Ranges
var sheet = SpreadsheetApp.getActiveSheet();
var cellToWatch = sheet.getActiveCell()
var rangeForRule = cellToWatch.offset(-6, 1, 10, 15)
// Create absolute Cell reference
var cellNotation = cellToWatch.getA1Notation()
var patt = /([a-zA-Z]+)([\d]+)/
var result = patt.exec(cellNotation)
var absoluteRef = "$" + result[1] + "$" + result[2]
// Create Conditional Formatting rule
var rule = SpreadsheetApp.newConditionalFormatRule()
.whenFormulaSatisfied('=OR('+ absoluteRef +'="金",'+ absoluteRef +'="木")')
.setBackground("#00FF00")
.setRanges([rangeForRule, cellToWatch])
.build();
var rules = sheet.getConditionalFormatRules();
rules.push(rule);
sheet.setConditionalFormatRules(rules);
}
This script
Assumes that your sheet will always have exactly the same format
Needs you to select the cell with the criteria, like this:
At the moment you need to run from the script editor
It chooses a range to apply the formatting rule based on the position of the selected cell. var rangeForRule = cellToWatch.offset(-6, 1, 10, 15)
It gets the A1 notation of the selected cell and using RegEx, makes an absolute version of the A1 notation. A1 => $A$1
It creates a conditional formatting rule using the references it has just built.
You will need to modify the HEX value of the color to suit your needs "#00FF00"
You could make this a custom sidebar on your spreadsheet, so that creating this rule is just a couple mouse clicks.
References
Apps Script Main Page
RegEx
Sheets Range Object
Conditional Format Rule Builder
Conditional Format Rule Class
I have a table in MySQL (really is a "View") that I changed the Name. It was used in a Calc spreadsheet Control (Text box and clicked on it) to update some cell contents. After the Name change Calc control does not work. I searched Internet, played with Calc all day and could not a fix so far. Basically, in "Define Database Range" window the "Source" section on the bottom is empty, and it is not editable. The macro runs without error but produces nothing. Why is the "Source" empty, and how to set it up to the proper source?
Finally figured out - maybe not the best solution.
Data>Define range>Select the range with problem (source missing for some reason)
Data>Define range: recreate the same range with desired name
Ctrl+Shift+F4 will open up Mysql data source; select the desired table or query; content will appear in the top right window
Click on the top left corner of the output table; Data-to-text icon will appear in row above
Click on Data-to-text icon and the table will be inserted into the active range in the spreadsheet
Now the Data>Define range selected range will have the proper SOURCE filled in as the data source of the range
Last, I had to recreate the macro that is assigned to the Text box Control. The macro is Data>Select Range + Data>Refresh Range + whatever else...
Now my original method of clicking on the text box to refresh data in the spreadsheet from MySQL works again!
I'm trying to do a macro in google sheets where I select a point in column N (in this case N100) and then simulate control up button to move up to the next available value in column N. But when I do this, I see the cell that's activated is the top of the column (looks like control up is pressed twice).
The code I have is below, any ideas on why this seems to be the case?
function ClearFormq() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Team1");
sheet.getRange("N100").activate()
sheet.getCurrentCell().getNextDataCell(SpreadsheetApp.Direction.UP).activate();
}
Thanks!
I have two sheets: Sheet1 & Sheet2
Sheet1 has Dropdown menu "Dropdown_1" with choices: a,b,c
Sheet2 has "Dropdown_2"u, also with choices: a,b,c
Sheet2 has also a cell linked to the Dropdown menu of Sheet1 "Link_dropdown_1" showing the current selection.
Is there a way how i can update the selection of "Dropdown_2" based on the value in "Link_dropdown_1"? I don't want to synchronise the two dropdown menus bidirectional - just from Sheet1 -> Sheet2. In case my explanation is hard to understand - here is the example in sheets:
example sheet
Update:
Looking for a way to update a Dropdown Menu not a simple cell!
For example: "a" gets selected in "Dropdown_1" --> automatically select "a" in "Dropdown_2" as well.
Update 2:
Maybe my previous explanations were really misleading but i am NOT looking for a dynamically created dropdown menu or similar. I want to synchronise choices/selection of two dropdown menus that contain the same values.
Hope this makes it clear:
I use "Value_Dropdown_A" for some sorting in Sheet2. In case it its not needed for synchronising "Dropdown_A" to "Dropdown_B" just ignore it...
I'm new to the world of google sheets. I was able to program very simple routines in Excel. Sorry if I couldn't find the answer anywhere on this site.
My question is simple, has 2 parts:
I would like to prompt a question box on opening the google sheet, asking a numeric value, after answering this, storing the numeric value to a specific cell, e.g. B3.
I would like to have a button on multiple pages of the sheet, prompting the same question box to edit the value.
Background:
I'm a medical doctor, I've created a sheet with many medications for small children in emergency situations. I would like a ask the user the age (and maybe later the weight, it's now calculated) of the child, so the age and weight are correct on all pages and the user is not in a hurry to find the right cell. If the user would like to edit the age, he uses the button, available on all sheets.
First, with the following function you can ask the user for the age and set it to a specific cell in a specific sheet:
function promptUserAge()
{
// Prompt for the value
var age = SpreadsheetApp.getUi().prompt("Please enter the age.").getResponseText();
// Get the sheet that you want store the value in and set the value in the cell B3
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Patient Information").getRange("B3").setValue( age );
}
Now, since you used the phrase
so the age and weight are correct on all pages
I am not sure if you are going to set the value in multiple sheets, and are you going to do that with Sheets functions or app script. That is why I am going to include the method to set the value in all sheets, in specific cell:
function promptUserAge()
{
// Prompt for the value
var age = SpreadsheetApp.getUi().prompt("Please enter the age.").getResponseText();
//Get all pages in spreadsheet and iterate through
var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
for(var i = 0; i < sheets.length; i++ )
{
//Set the value in the cell B3 of the page
sheets[i].getRange("B3").setValue( age );
}
}
To get the prompt to pop-up when user opens the Spreadsheet you use call it in the onOpen function:
function onOpen(e)
{
promptUserAge();
}
And now, the part where you add the button to edit the value.
You could add a custom menu that would appear in the Spreadsheet's toolbar with a custom menu like this :
function createMenu()
{
SpreadsheetApp.getUi().createMenu("Fill information")
.addItem("Age", "promptUserAge")
.addToUi();
}
This is a good way if your users know what to look for, meaning that you have told them the custom menu exists. From my experience, some people have trouble finding the menu even if you tell them it is there, so since your background suggests you want to create an easy and fast way I would use the second method:
You could insert an image to the Spreadsheet by navigating from it's toolbar: Insert -> Image. Insert an Image that says 'Push here to edit information' in a very clear way and right click the image. You get the borders to edit the image size and in it's upper-right corner appears three dots. You click the dots and then "Assign script...". To the prompt, insert the function name without the parenthesis. In this example you would insert:
promptUserAge
Now the image works as a button to call the function.
I hope this helped.