I have a Google Sheets document and there is a dynamic list that gets created in a certain range (J19:L26) that has some personal data in it. Is there a way to make a checkbox or something quick I can click (even a button?) that can set the text to white or background to black to hide it to onlookers? I currently have the checkbox in cell M17
I have the following code that executes fine but then when I check the box in M17 nothing happens. Maybe I missed a step somewhere? I am new to Google sheets coding. I just wrote the function, tested it Runs, then closed it. Maybe I am just missing a step(s) in implementing the function to my sheet or my function Runs but doesn't do what I need it to?
function Privacy() {
var TheBoard = SpreadsheetApp.getActiveSpreadsheet();
var TheRange = TheBoard.getRange("Board!J19:L26");
if(TheBoard.getRange("Board!M17") == "TRUE")
{
TheBoard.getRange(TheRange).setFontColor('white');
}
}
There are a few things to correct. Here's a list:
When getting the status of the checkbox you're using TheBoard.getRange("Board!M17"). The getRange() method returns a reference to the range, not the value. After getting the range you can use getValue() on it to retrieve the values, so it should be TheBoard.getRange("Board!M17").getValue(), which will return true or false depending on the status of the checkbox.
You're comparing the value of the checkbox to == "TRUE". That makes it a string, and the checkbox value returns a boolean. In Javascript you're supposed to declare booleans as true or false, lowercase without quotes. That means the comparison should be == true instead.
The line TheBoard.getRange(TheRange).setFontColor('white'); returns an error. This is because getRange() expects a range in A1 notation or the coordinates to the row and column, but you're plugging TheRange into it, which is already a Range object. You already defined TheRange, so you don't need to "get" it again. The line should be just TheRange.setFontColor('white');
If you want to make the script run automatically when you click the checkbox you need to set it up as an onEdit() trigger. Then within the trigger check if the field that was edited was the checkbox before proceeding.
It's probably better to create a separate variable for the Sheet to avoid having to specify it in every range call.
May be a nitpick, but capitalizing variables makes the formatting color them like Classes, which may become confusing so I advise not doing that.
That said, here's the script with all the corrections:
function onEdit(e) {
if (e.range.getA1Notation() == "M17") {
var theBoard = SpreadsheetApp.getActiveSpreadsheet();
var theSheet = theBoard.getSheetByName("Board")
var theRange = theSheet.getRange("J19:L26");
if (theBoard.getRange("M17").getValue() == true) {
theRange.setFontColor('white');
} else {
theRange.setFontColor('black');
}
}
}
I recommend you familiarize yourself with the official documentation to better understand how each method works and apply them correctly.
Sources:
Sheet Class
Range Class
Triggers
I have some scripting to format cell color. I would like to use LIKE to search inside the string (cell value). I am having a hard time finding something that works. I am very much new to Google Apps Script\Java.
Basically I want an if statement for a cell value, if it contains the word "extra" with anything before or after it. So it would match for 1extra and extra1, with any number of characters before or after.
Thanks for any help!
If you just want to check if a certain string is present, then you can use match
Script:
function myFunction() {
var sheet = SpreadsheetApp.getActiveSheet();
var A1_A6 = sheet.getRange("A1:A6").getValues();
// loop values of A1:A6
A1_A6.forEach(x => {
// since x is in [x] form, we get its first and only element
cell = x[0];
// if cell value has "extra" in it
// added i modifier since you want to match "123Extra123"
if(cell.match(/.*extra.*/i))
Logger.log(`"${cell}" matches.`);
});
}
Sample Data:
Output:
Note:
.* surrounding "extra" means that any number of any character (it will match any string, be it very long, or none at all)
modifier i after /.*extra.*/ means it will match regardless of the case (case insensitive - e.g. will match even if we want is "extra" and the one in the string is "Extra"). If you want to only match the exact string "extra", remove the i.
Reference:
match
I have a Google spreadsheet named "Words" with a number of words which are divided into categories.
2)
In Google spreadsheet named "UNIQUE + MANUALLY" I make a unique list in (UNIQUE category) from category in "Words".
To the unique list I would like to have attached a manual word.
How do I get column (MANUALLY Category groups) to follow (UNIQUE category) so the list does not change when new words and categories are added?
Answer:
You can use a script on button click to run the query and statically add the text into the desired cells.
The Idea:
The idea is very similar to how the formula currently works:
Get a list of all words
Remove duplicates and blank cells
Alphabetise them
Insert them into the correct column
Code Example:
Assuming that your column is 'UNIQUE + MANUALLY'!B2:B and the words are all in 'words'!A2:A:
function getUniqueWords() {
const ss = SpreadsheetApp.getActiveSpreadsheet()
const wordsSheet = ss.getSheetByName("words")
const destSheet = ss.getSheetByName("UNIQUE + MANUALLY")
const wordsToSort = wordsSheet.getRange("B2:B").getValues()
.flat().filter(function (el) {
return el != ""
}).filter(function (v, i, s) {
return s.indexOf(v) === i
}).sort().map(x => [x])
destSheet.getRange("A2:A").clear()
destSheet.getRange(2, 1, wordsToSort.length, 1).setValues(wordsToSort)
}
You can add this script to your Sheet by following the Tools > Script editor menu item, pasting this function into the editor, and saving the script. Make sure to press Run at least once to authorise the script so that it can run on your behalf.
If you want to add this to a button click in the Sheet itself, you can create a Drawing or add an image into a Sheet from the Insert menu item, and then with the image loaded into the sheet, you can click it, select the vertical ellipsis menu (⋮) which appears in the top-right of the image, select Assign script and in the dialog box enter the function name (in this case, getUniqueWords, without the succeeding ()).
This is my scenario:
I have a Google Form, and the values are added to a SpreadSheet. I have an Apps Script started with function onFormSubmit(event)
I get the values from the Form with var Variable = event.namedValues["Question 1"];
I use the value of this variables with some "if statements".
This Apps Script has been running OK, but i'm still making changes to add new functionalities (adding more questions on the Form, new functions on the Script), but suddenly in one of the variables starts to appear a comma into the values from this variable.
After checking all the Script, i decided to copy all the script to a new one. And when I used this new scenario (same content of files), the mysterious comma disappeared. I continued with new developments, but after some new changes (newer ones) the comma started to appear on one of the variables in their values. And after some new changes the comma moved from adding at the begging of the value, started to appear at the end.
I have checked the values on the spreadsheet, and they appear with no comma, the comma only appears when i use the values of that variable on the script.
I print the value with Logger.log(Variable) after i save the value from the event, and the comma is there, so i don't think that my code is adding this comma.
Any idea why is this happening? Is there a way to check on the value of a variable a character (in this case the comma) inside the Script? Something like Replace(Variable,",",""), with this i can check all the values got from the event before i start using them inside the Script. Commas aren't used on the values of the variables.
THESE ARE THE LINES AFFECTED (The script has more than 500 lines):
function onFormSubmit(event){
var Variable = event.namedValues["Question 1"];
Logger.log("Value after event" + Variable);
if (Variable == "AAAA"){
// do "something";
}
else {
// do "something different"
}
}
As the comma appears the if statement never gets a TRUE because the value starts to be "AAAA," so the do "something" never happens.
Answers:
Any idea why is this happening?
There might be some typos out there that needs to be cleaned. It would be better if you could also provide your code or at least how you wrote it.
Is there a way to check on the value of a variable a character (in this case the comma) inside the Script?
You can check the presence of a character/string in a variable by using includes.
var string = "I am Iron man,";
var hasComma = string.includes(","); // True
If you want to replace all the instances of comma, then use replace
// Replace all commas with blank
var string = string.replace(",", ""); // "I am Iron man"
EDIT:
Since e.namedValues["Question 1"] returns an object, you need to change the variable into string and then use the replace function
Code:
var Variable = e.namedValues["Question 1"];
Variable = String(Variable).replace(",", "");
Logger.log("Value after event: " + Variable);
if (Variable == "AAAA"){
// do "something";
}
else {
// do "something different";
}
References:
includes
replace
In a Google Docs spreadsheet, I'm looking for something like =EVAL(A1) where A1 is set to "=1+2".
I found out that in MS Excel there is an EVALUATE() function (which seems a bit tricky to use properly). But I could not find anything similar in Google Docs.
I also searched through the function list, but could not find anything helpful...
No, there's no equivalent to Excel's EVALUATE() in Google Sheets.
There's long history behind this one, see this old post for instance.
If you're just interested in simple math (as shown in your question), that can be done easily with a custom function.
function doMath( formula ) {
// Strip leading "=" if there
if (formula.charAt(0) === '=') formula = formula.substring(1);
return eval(formula)
}
For example, with your A1, put =doMath(A1) in another cell, and it will be 3.
I know this an old post. I'm just wondering, why nobody suggested:
myCell.getValue();
This will give you the result of the formula in myCell (3 in your example).
If you want to write the result to the cell (instead of the formula), you could use:
function fixFormula(myCell) {
myCell.setValue(myCell.getValue());
}
Short answer
As was mentioned previously, Google Sheets doesn't have a built-in EVALUATE function, but Google Sheets could be extended to add this function. Fortunately some SocialCalc files could be used to make this easier.
Script
On Google spreadsheet I'm sharing my progress. At this time I added the SocialCalc files that I think that are required and a couple of functions, and several test cases.
NOTES:
Google Sheets specific functions like FILTER, UNIQUE, among others are not available in SocialCalc as well as other functions like SIGN.
I think that the SocialCalc file should be replaced by those on https://github.com/marcelklehr/socialcalc as it looks to be updated recently. H/T to eddyparkinson (see https://stackoverflow.com/a/16329364/1595451)
Uses
The EVALUATE function on the linked file could be used as a custom function.
Example 1
A1: '=1+2 (please note the use of an apostrophe to make the formula be treated by Google Sheets as a string.
B1 formula:
=EVALUATE(A1)
B1 display value:
3
Example 2
To "EVALUATE" a formula like =VLOOKUP(2,A1:B3,2), at this time we need to use the "advanced" parameters. See the following example:
B1: '=VLOOKUP(2,A1:B3,2)
C1 formula:
=EVALUATE(B1,"data","A1:B3")
C1 display value:
B
Code.gs
/**
*
* Evaluates a string formula
*
* #param {"=1+1"} formula Formula string
* #param {"Tests"} sheetName Target sheet.
* #param {"A1"} coord Target cell.
*
* #customfunction
*
*/
function EVALUATE(formula,sheetName,coord){
// SocialCalc Sheet object
var scSheet = new SocialCalc.Sheet();
if(sheetName && coord){
// Pass values from a Google sheet to a SocialCalc sheet
GS_TO_SC(scSheet,coord,sheetName);
}
var parseinfo = SocialCalc.Formula.ParseFormulaIntoTokens(formula.substring(1));
var value = SocialCalc.Formula.evaluate_parsed_formula(parseinfo,scSheet,1); // parse formula, allowing range return
if(value.type != 'e'){
return value.value;
} else {
return value.error;
}
}
/**
*
* Pass the Google spreadsheet values of the specified range
* to a SocialCalc sheet
*
* See Cell Class on socialcalc-3 for details
*
*/
function GS_TO_SC(scSheet,coord,sheetName){
var ss = SpreadsheetApp.getActiveSpreadsheet();
if(sheetName){
var sheet = ss.getSheetByName(sheetName);
var range = sheet.getRange(coord);
} else {
var range = ss.getRange(coord);
}
var rows = range.getNumRows();
var columns = range.getNumColumns();
var cell,A1Notation,dtype,value,vtype;
// Double loop to pass cells in range to SocialCalc sheet
for(var row = 1; row <= rows; row++){
for(var column = 1; column <= columns; column++){
cell = range.getCell(row,column);
A1Notation = cell.getA1Notation();
value = cell.getValue();
if(cell.isBlank()){
dtype = 'b';
vtype = 'b';
} else {
switch(typeof value){
case 'string':
dtype = 't';
vtype = 't';
break;
case 'date':
case 'number':
dtype = 'v'
vtype = 'n';
break;
}
}
scSheet.cells[A1Notation] = {
datavalue: value,
datatype: dtype,
valuetype: vtype
}
}
}
}
formula1.gs
https://github.com/DanBricklin/socialcalc/blob/master/formula1.js
socialcalcconstants.gs
https://github.com/DanBricklin/socialcalc/blob/master/socialcalcconstants.js
socialcalc-3.gs
https://github.com/DanBricklin/socialcalc/blob/master/socialcalc-3.js
If you want to evaluate simple math(like A1: "(1+2)*9/3"), you can use query:
=query(,"Select "&A1&" label "&A1&" ''",0)
Basic math sent to query's select is evaluated by query.
Copy and paste the formulas:
Maybe you can copy and paste the formulas you need from "jQuery.sheet". Moved to:
https://github.com/Spreadsheets/WickedGrid
Looks to be all "open source"
Wont fix the issue
Also: The issue "Enable scripts to use standard spreadsheet functions" is marked as "Wont fix", see https://code.google.com/p/google-apps-script-issues/issues/detail?id=26
Ethercalc
there is a google like opensource spreadsheet called Ethercalc
GUI Code:
https://github.com/audreyt/ethercalc
Formulas: https://github.com/marcelklehr/socialcalc
Demo - on sandstorm:
https://apps.sandstorm.io/app/a0n6hwm32zjsrzes8gnjg734dh6jwt7x83xdgytspe761pe2asw0
In the case of evaluating a function like
"=GoogleFinance("usdeur","price",date(2013,12,1),date(2013,12,16))"
This can be done this without evaluate by directly referring to other cells like this:
=GoogleFinance(A10,"price",E3,E6)
Simple hack to evaluate formulas in google spreadsheet:
select cells or columns with formulas
go Edit -> Find and replace...
check "Also search in formulas"
replace "=" to "=="
replace back "==" to "="
in the same "Find and replace" window uncheck "Also search in formulas"
formulas will evaluate! :)
Thank you for user3626588's workaround here and it does indeed work. Based off your instructions it looks like it can be simplified even further.
In Cell B1 Enter the following:="=sum(A1:A5)"
In Cell C1 Set a data validation and select B1 with dropdown option.
Now select C1 and select the formula from the dropdown, it will sum any values between A1 through A5 automatically.
I have a sheet where I was creating a complicated formula for multiple values and this process worked!
Thank you once again as I was trying to avoid a script since I have data that is being pulled by another program on my worksheet. Script function do not always run automatically in those situations.
Here is the trick. Insert formula in the required cell, then get retrieve that cell value and replace the already inserted formula with this new value.
function calculateFormula(row, col){
var spreadsheet = SpreadsheetApp.getActive();
var sheet = spreadsheet.getSheetByName("Sheet Name");
sheet.getRange(row,col).setValue("=sum(D6,C12:C14)");
sheetData = sheet.getDataRange().getValues();
var newValue = sheetData[row-1][col-1];
sheet.getRange(row,col).setValue(newValue);
}
How about just converting a column of expressions which are not preceded by a "+"?
92/120
67/85
etc.
It's a bit of a hack, but this works
get the formula from the cell;
set the formula back again; then
get the value from the cell.
var cell = sheet.getRange("A1");
var formula = cell.getFormula();
cell.setFormula(formula);
var fileCell = cell.getValue();
Awesome work around for google not having evaluate(). I have looked all around and besides script have found no other way to have a formula as a string on one sheet then use that formula on another. In fact everything I've seen says you can't. Would be helpfull if anyone reading this could repost around if they come to an appropriate question since I must have read a half dozen posts saying it wasn't possible before I just rolled up my sleaves and done done it. :) It still has a little clunkyness since you need two cells in the spreadsheet you want the formula to execute, but here goes.
Ok, some set up. We'll call the spreadsheet with the formula as string SpreadsheetA, call the tab the formula is on TabAA, the Spreadsheet you want to call and execute said formula SpreadsheetB. I'll use a multi-tab example, so say you want the sum of A1:A5 on SpreadsheetB tab: TabBA to be calculated on SpreadsheetB tab: TabBB cell A1. Also call the URL of spreadsheet A: URLA
So, in Spreadsheet A Tab: TabAA cell A1 put ="=sum(TabBB!A1:A5)", therefore the cell will display: =sum(A1:A5). Note: you don't need any $ in formula. Then in Spreadsheet B, Tab: TabBB, cell A2 put: =Query(Importrange("URLA","TabAA!A1"),"select Col1 where Col1 <> ''"). That cell will now display =sum(TabBA!A1:A5). Next to that, cell A1 of Spreadsheet B tab: TabBB, create a dropdown of the cell with the formula in B2 (right click cell A1, select data validation, for Criteria select: List from range, enter B2 in box to right). That cell should now be summing SpreadsheetB, TabBA, range A1:A5
Hope that was clear, I'm rather novice at this. Also important, obviously you would only do this in cases where you wanted to choose from multiple formulas on spreadsheetA, instead of TabAA!A1 say you had another formula in A2 also so your query would be =Query(Importrange("URLA","TabAA!A1:A2"). I understand in the simplistic case given you would simply put the formula where you needed the sum.
Edit: Something I noticed, was when I wanted to use a formula with double quotes the above scenario didn't work because when you wrapped the formula with double quotes in double quotes you get an error since you need single quotes inside double quotes. The example I was trying: if(counta(iferror(query(B15:C,"select C where C = 'Rapid Shot' and B = true")))>0,Core!$C$18+$C$10&" / ",)&Core!$C$18+$C$10&if(Core!$C$18>5," / "&Core!$C$18-5+$C$10,)&if(Core!$C$18>10," / "&Core!$C$18-10+$C$10,)&if(Core!$C$18>15," / "&Core!$C$18-15+$C$10,)
In that case I put another formula into Spreadsheet A TabAA cell A2 that read ="="&A1. Then, ajusted the importrange referance in spreadsheet B to reference that cell instead.
BTW, this absolutly works so if you can't get it let me know where your having problems, I don't do a lot of colaboration so maybe I'm not saying something clear or using the right / best terminollagy but again I've seen many posts saying this was impossible and no one saying they had found another way.
Thanx ~ K to the D zizzle.
Here is the working trick to evaluate the concatenated formula string. Use the formula cell as a data validation source for the target cell. Maybe it is not a fully automated solution. But evaluating refreshed formulas has been stripped down to just one click. You just need to reselect the value from the validation box when it is necessary. Many thanks to #Aurielle Perlmann and #user3626588 for the idea.
As an example, when you have set up dynamic multiple concatenations of such below formula in another sheet, this will work well with selecting validation option.
In my case, pressing enter twice is not userfriendly.
=({FILTER(IMPORTRANGE("https://docs.google.com/spreadsheets/d/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/edit"; "EXPENSES!A2:P"); INDEX(IMPORTRANGE("https://docs.google.com/spreadsheets/d/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/edit"; "EXPENSES!A2:P"); 0; 1) <> ""); FILTER(IMPORTRANGE("https://docs.google.com/spreadsheets/d/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/edit"; "EXPENSES!A2:P"); INDEX(IMPORTRANGE("https://docs.google.com/spreadsheets/d/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/edit"; "EXPENSES!A2:P"); 0; 1) <> ""); FILTER(IMPORTRANGE("https://docs.google.com/spreadsheets/d/cccccccccccccccccccccccccccccccccccccccccc/edit"; "EXPENSES!A2:P"); INDEX(IMPORTRANGE("https://docs.google.com/spreadsheets/d/cccccccccccccccccccccccccccccccccccccccccc/edit"; "EXPENSES!A2:P"); 0; 1) <> "")})
[enter image description here]
[enter image description here]