Google Sheets - How to allow multiple matches in conditional formatting - google-sheets

Would it be possible for Google Sheets not to stop conditional formatting rules even after it hits its first match?
The problem:
I have a column of numerical values whose text are color coded based on its values, e.g. black if less than 10k, green if 10k to less than 20k, blue if between 20k and 30k, and so on.
The same cell values change text format to bold if the the assignee is Bob, italics if Alice, and underlined if Foo. (We should be using custom formula in conditional formatting to do this.)
The same cell values change background color depending how far today's date is from the deadline. (Like above, custom formula is used.)
Of course, conditional formatting by design stops and then applies the formatting once it hits the first matching rule. Can there be a workaround / hack for this? We can of course individually write all the matches bound by the AND function, but that will be writing formulas for a permutation of possibilities.

I'm not sure if you are familiar but you can write custom scripts in the backend of most Google products with the Google Script language (based on JavaScript). Using this you can programmatically build conditional formatting rules. Here is the link to the documentation. You will certainly need to change the code below to what you need, here is a rough idea:
let sheet = SpreadsheetApp.getActiveSheet();
let range = sheet.getRange("A1:B3");
let rules = sheet.getConditionalFormatRules();
// this is the loop to make all of the rules
let maxVal = 1000;
low = 1;
high = 10;
let colors = ['red','orange','yellow','green','blue','purple'];
for (let i=0; i < colors.length; i++) {
let rule = SpreadsheetApp.newConditionalFormatRule()
.whenNumberBetween(low,high)
.setBackground(colors[i])
.setRanges([range])
.build();
rules.push(rule);
//changes the low and high for the loop
low = high + 1;
high = high + 10;
sheet.setConditionalFormatRules(rules);
The code will set a different background colors for every interval. You can extend the code for as much as you need without needing to manually setting all of the rules.

Related

Google Sheets IF AND OR Logic

I am making a scoring system on Google sheets and I am struggling with the logic I need for the final step.
This question might be related, but I can't seem to apply the logic.
There are a number of chemicals tested and for each an amount detected (AD) si given, and each has a benchmark amount allowed (AL). From AL and AD we calculate AD/AL= %AL.
The Total Score (TS) is calculated based on an additive and weighted formula that takes into consideration the individual %ALs, but I won't go into that formula.
The final step is for me to "calculate" the Display Score (DS), which has some rules to it, and this is where I need the logic. The rules are as follows:
If any of the %Als are over 100 (this is will make TS>100 too) and DS should show "100+"
If none of the %ALs are over 99, (TS may be above or below 100) then DS can NOT be over 99, so it should show TS, maxing out at 99.
I want to do this within the sheet itself. I think the correct tool is logic operators IF, AND, OR.
I have made many attempts, these are some: (I am replacing cell references with the acronyms I used above)
=IF(TS>100,"100+",TS)
=IF(OR(AND(MAX(RANGE_OF_%ALS)<100,TS>99),(AND(MAX(RANGE_OF_%ALS)>100,TS>100)),99,"100+"))
I have also tried to think about how I would solve this in Python (just to explore it, I don't want to use Python for the solution). This was my attempt:
if Max%AL<100:
if TS<100:
print(TS)
else:
print("99")
else:
if TS>100:
print("100+")
Those are my attempts at thinking through the problem. I would appreciate some help.
This is a link to a copy of my sheet: https://docs.google.com/spreadsheets/d/1ZBnaFUepVdduEE2GBdxf5iEsfDsFNPIYhrhblHDHEYs/edit?usp=sharing
Please try:
=if(max(RANGE_OF_%ALS)>1,"100+",if(max(RANGE_OF_%ALS)<=0.99,MIN(TS,0.99),"?"))

How to prevent Google sheets from rounding large integers in calculations

Whenever I try to perform a calculation with a large number result,
26^14
spreadsheets automatically rewrite it in scientific notation, not saving the excluded numbers and cutting it off.
6.451E+19
To get around this, I have to manually type in the answer.
64509974703297150976
This works for displaying the number, but whenever I try to multiply this number in another cell, sheets will perform the calculation on the rounded number form of the scientific notation number.
64509974703297200000 * 2 = 129019949406594000000
This is the number I get instead of the desired:
64509974703297150976 * 2 = 129019949406594301952
Exact numbers are required and this is just getting really frustrating. I would really like to have the answer to stop google sheets from doing this as soon as possible (duh).
Since Google Sheets use JavaScript, you may copy a library and use it.
Here is the link to library with description on how to use:
https://github.com/peterolson/BigInteger.js
Step 1
Go here and copy the code into your Script Editor:
https://github.com/peterolson/BigInteger.js/blob/master/BigInteger.min.js
Step 2
Write your own custom function like this:
function bigIntPow(a, b)
{
return bigInt(a).pow(b).toString();
}
Step 3
Use the function from Sheet:
=bigIntPow(26,14)
The result is text: 64509974703297150976

Iterative programming using PCollectionViews

I wish to create a PCollection of say one hundred thousand objects (maybe even a million) such that I apply an operation on it a million times in a for-loop on the same data, but with DIFFERENT values for the PCollectionView calculated on each iteration of the loop. Is this a use-case that df can handle reasonably well? Is there a better way to achieve this? My concerns is that PCollectionView has too much overhead, but it could be that that used to be a problem a year ago but now this a use-case that DF can support well. In my case, I can hardcode the number of iterations of the for-loop (as I believe that DF can't handle the situation in which the number of iterations is dynamically determined at run-time.) Here's some pseudocode:
PCollection<KV<Integer,RowVector>> rowVectors = ...
PCollectionView<Map<Integer, Float>> vectorX;
for (int i=0; i < 1000000; i++) {
PCollection<KV<Integer,Float>> dotProducts =
rowVectors.apply(ParDo.of(new DoDotProduct().withSideInputs(vectorX));
vectorX = dotProducts.apply(View.asMap());
}
Unfortunately we only support up to 1000 transformations / stages. This would require 1000000 (or whatever your forloop iterates over) stages.
Also you are correct in that we don't allow changes to the graph after the pipeline begins running.
If you want to do less than 1000 iterations, then using a map side input can work but you have to limit the number of map lookups you do per RowVector. You can do this by ensuring that each lookup has the whole column instead of walking the map for each RowVector. In this case you'd represent your matrix as a PCollectionView of a Map<ColumnIndex, Iterable<RowIndex, RowValue>>

limit UITextField to specific number

I have a UITextField and I want to limit the user to only input decimal numbers that are between 0.0 and 24.00.
The main idea is that user is entering Hours in that field. So It can't go over 24 hours in a day.
is it possible to automatically enter a decimal after 2 digits? So when a user enter "18" for example, a decimal "." automatically shows up.
Right now, I am limiting the user to only enter full hours. So they can only enter 2 digits. I really need to change that. This is what I have now.
txtFld_Hours.ShouldChangeCharacters = (textField, range, replacementString) => {
var newLength = textField.Text.Length + replacementString.Length - range.Length;
return newLength <= 2;
};
Thank you for your time.
Everything is possible of course, but like other people mentioned, it would be much better to use UIDatePicker control for a time picker (it even handles localisation for you on iOS, as some countries use 12-hour time with AM/PM marker for example). Even MonoTouch documentation says there are differences between platforms and you should structure your code in a way that only the difference in UI code is written for each platform, but all other code is common to all platforms.
But if you absolutely have to do this on your own, this requires a bit more complex solution, so we cannot write this for you directly. Search over GitHub for some code samples, I am sure that you can easily convert Objective-C into MonoTouch, since it is supposed to be a 1:1 mapping of the API.
Here are a few things on where to start:
See IUITextFieldDelegate interface documentation (which you already know about)
Update the ShouldBeginEditing method with code that will handle the dot.
When 2 characters are reached, add the dot programatically and move the cursor behind the dot using SelectedTextRange property.
The maximum length of the text, should now be 5.
Handle the automatic removal of the dot when text length is 3 and user taps backspace.
Following this and you should have your own UITextField with your custom hour picker.

Getting length of vector in SPSS

I have an sav file with plenty of variables. What I would like to do now is create macros/routines that detect basic properties of a range of item sets, using SPSS syntax.
COMPUTE scale_vars_01 = v_28 TO v_240.
The code above is intended to define a range of items which I would like to observe in further detail. How can I get the number of elements in the "array" scale_vars_01, as an integer?
Thanks for info. (as you see, the SPSS syntax is still kind of strange to me and I am thinking about using Python instead, but that might be too much overhead for my relatively simple purposes).
One way is to use COUNT, such as:
COUNT Total = v_28 TO v_240 (LO THRU HI).
This will count all of the valid values in the vector. This will not work if the vector contains mixed types (e.g. string and numeric) or if the vector has missing values. An inefficient way to get the entire count using DO REPEAT is below:
DO IF $casenum = 1.
COMPUTE Total = 0.
DO REPEAT V = v_28 TO V240.
COMPUTE Total = Total + 1.
END REPEAT.
ELSE.
COMPUTE Total = LAG(Total).
END IF.
This will work for mixed type variables, and will count fields with missing values. (The DO IF would work the same for COUNT, this forces a data pass, but for large datasets and large lists will only evaluate for the first case.)
Python is probably the most efficient way to do this though - and I see no reason not to use it if you are familiar with it.
BEGIN PROGRAM.
import spss
beg = 'X1'
end = 'X10'
MyVars = []
for i in xrange(spss.GetVariableCount()):
x = spss.GetVariableName(i)
MyVars.append(x)
len = MyVars.index(end) - MyVars.index(beg) + 1
print len
END PROGRAM.
Statistics has a built-in macro facility that could be used to define sets of variables, but the Python apis provide much more powerful ways to access and use the metadata. And there is an extension command SPSSINC SELECT VARIABLES that can define macros based on variable metadata such as patterns in names, measurement level, type, and other properties. It generates a macro listing these variables that can then be used in standard syntax.

Resources