Google spreadhseet EVAL function - google-apps-script

I have a google spreadsheet with different sheets, each one representing a different week.
For example:
1/12 - 1/16
1/19 - 1/23
I want to do a chart based on the content of those sheets. Is there any way I can make a formula and extract the name of the sheet from a content of a cell?
For example something like "=EVAL(A1)!$B$4", then I would have the content from "1/12 - 1/16"!$B$4 instead of having to go through each one of the weeks of the year manually.
Thanks for the help!

There’s no need to use AppScript, INDIRECT is enough to read a sheet name from a cell:
=INDIRECT(A1 & "!$B$4")
However, it looks like Andy’s answer is the way to go if you want to get the sheet name from its index rather than from a cell.

It'd be best to use AppScript. In Tools -> Script Editor make a new AppScript script:
function getSheetName(i) {
var s = SpreadsheetApp.getActiveSpreadsheet().getSheets()
return s[i].getName();
}
With that in your script, you can then use the custom function =getSheetName(<SHEETNUMBER>) and it will retrieve the sheet name based what sheet number it is (starting from 0). From there, just incorporate it into your formulas. You may need to use INDIRECT.
Example: =INDIRECT(getSheetName(1)&"!A1") to get cell A1 in the second sheet.

Related

Using setformulas to copy both values and formulas down a column

PROBLEM: In the below spreadsheet, cells C12:C17 (green) contain text imported from another spreadsheet (The "PARENT").
https://docs.google.com/spreadsheets/d/1brm0dHkXG1vxn2NQ7wGvEoayCdGYKsY4yA-MX4Jtt1w/edit#gid=396314711
Some cells have text. Some are blank. Some contain simple math (i.e 1+1), and others relational math (i.e. A1+B1). The DATA SET in the PARENT sheet are different than the CHILD sheet. I will eventually have to create a lot of CHILD sheets, each with their own unique DATA SET. The formulas on the PARENT sheet will change from time to time, so the solution isn't to just make a copy of the PARENT spreadsheet and turn it into a CHILD sheet.
I need to be able to create the formulas in the PARENT sheet, but when imported into the CHILD sheet, they need to be calculated using the data set on the CHILD sheet.
I'm trying to use a script that will take what is in the C12:C17 range, and make it an active formula in the corresponding D12:D17 cells. If the C column cell is a value, it should just put that value in there instead of making it into a formula.
I've made about a dozen attempts at the setFormulas script. All failed. At this point, I would say I'm "spit-balling", "flailing", and possibly "spiraling". The BEST I've been able to do is to get ONE cell to update (but only if a formula, not text).
I'm looking for a script that will take whatever is in cells C12:C17, and execute/evaluate them into cells D12:D17. If there are text/values in the C cell, then it should put that text/value in the corresponding D cell. If there is a formula in the C cell, it should make it execute in the corresponding D cell. There is no pattern on whether a cell will be a number, text, or formula.
I appreciate any help you can give.
FYI: The formulas/text in the C column were made by importing from the PARENT sheet. That range of cells in the PARENT sheet was made by the following formula:
=IFERROR(FORMULATEXT('P CUSTOMERS'!B12),'P CUSTOMERS'!B12)
Essentially, "If it's a formula, convert it into text. If it's not a formula , just put what is in the cell in the first place ."
I've been working on this for an embarrassing amount of time... (Not hours, not days, not weeks, but MONTHS!).
EDIT / UPDATE:
OK, Marti's scripts worked great in the example file. Moved it to another file, same conditions, and worked again.
THEN, I moved it to another file... Only difference I can tell is that it is MUCH larger.
EDIT SUMMARY:
Ran the script under these conditions.
Made table with formulas. Used FORMULATEXT on that table to convert into text. Imported that range to another sheet. Used an HLOOKUP formula to select which column I wanted to look at formulas for.
In the sample sheet (linked here: https://docs.google.com/spreadsheets/d/1cPSJMXNiKDnHCiUCGJ0iSjaoIiRLQldr1T5rClUUEm0/copy), it works.
But when I run the exact same series of events in another sheet, it fails to do anything. Process is the same, only the range is different. No other scripts on this sheet.
I trimmed down the second sheet so I can share (script still doesn't work).
https://docs.google.com/spreadsheets/d/1RRMy4RtF9CVSXw18bWg79Dh4nwHg8IN3wwhLb3QynvA/edit#gid=236899042
(Note: I can't force a copy, as this sheet requires authorizations from another file)
Here is a video better explaining the issue:
https://drive.google.com/file/d/1pjz_LilRReQlNt7p_4NhU3prtbcAhLah/view?usp=sharing
So, I'm trying to understand why it works in one, but not the other... And just as important, what can I do to make it work in 2nd sheet, which is actual goal.
You can simply use getValues together with setValues. setValues actually interprets values starting with = as formulas, and getValues actually doesn't add the ' before them. So you can simply chain them:
function computeValues() {
const ss = SpreadsheetApp.getActiveSpreadsheet()
const s = ss.getSheets()[0]
const src = s.getRange('C12:C')
const target = src.offset(0, 1)
target.setValues(src.getValues())
}
References
Range.getValues() (Apps Script reference)
Range.setValues(values) (Apps Script reference)
Range.offset(rowOffset, columnOffset) (Apps Script reference)
Martí nailed it...
function computeValues() {
const ss = SpreadsheetApp.getActiveSpreadsheet()
const s = ss.getSheets()[0]
const src = s.getRange('C12:C')
const target = src.offset(0, 1)
target.setValues(src.getValues())
}
I tested it, as written, by copy/paste. Worked 1st time.
I added in more formulas below the original range, just to see what the limits were (in cell C20), and re-ran it. Still worked.
I would have kept going in my setFormula direction for another few months. Not sure how I got it stuck in my head that was the only solution. This was the final major barrier in my project, and while I still have another few years of manual data entry and formula creation to do, THIS will be the key that makes it all work. THANK YOU!!!

Insert a reference to another cell programatically

I think this should be simple, but I have searched stackoverflow and the Spreadsheet Service documentation and cannot find a way to do it.
I have a spreadsheet with an app-script. The spreadsheet has a summary sheet and multiple data sheets. On the summary sheet, I need to reference cells on the data sheet, using formulas like:
[='DataSheet1'!C10], [='DataSheet1'!C11], [='DataSheet1'!C12]
[='DataSheet2'!C10], [='DataSheet2'!C11], [='DataSheet2'!C12]
...etc
Do I have to build these formulas programatically using string concatenation, or is there a better way?
Ideally I would like to just specify a source and destination range of the same size and have the references created automatically

How to use a formula written as a string in another cell [evaluate for Google Spreadsheet] [duplicate]

This question already has answers here:
Is there a way to evaluate a formula that is stored in a cell?
(13 answers)
Closed last month.
I read several old posts about Google Spreadsheet missing the evaluate function.
There is any solution in 2016?
The easiest example.
'A1' contains the following string: UNIQUE(C1:C5)
'B1' I want to evaluate in it the unique formula written in 'A1'.
I've tried concatenating in this way: 'B1' containing ="="&A1 but the outcome is the string =UNIQUE(C1:C5).
I've also tried the indirect formula.
Any suggestion to break last hopes, please?
Additional note
The aim is to write formulas in a spreadsheet and use these formulas by several other spreadsheets. Therefore, any change has to be done in one place.
Short answer
Use a script that includes something like var formula = origin.getValue() to get the string and something like destination.setFormula(formula) to return the formula.
Explanation
As was already mentioned by the OP, Google Sheets doesn't have a EVALUATE() built-in function. A custom function can't be used because custom functions can only return one or multiple values but can't modify other cell properties.
A script triggered by a custom menu, events or from the Google Apps Script editor could be used to update the formulas of the specified cells.
Since the formulas will be kept as strings, it could be more easy to keep them in the script rather than in the spreadsheet itself.
Example
The following is a very simple script that adds the specified formula to the active range.
function addFormula() {
var formula = '=UNIQUE(C1:C5)';
var range = SpreadsheetApp.getActiveRange();
range.setFormula(formula);
}
I have a solution for my own use case. My investment broker exports data to its users in (badly-formatted) Excel. I do my own analysis in Google Sheets. I have found copy/pasting entire sheets of data to be accident-prone.
I have partially automated updating each tab of the records. In the sheet where I maintain all the records, the First tab is named "Summary"
Save the broker's .xlsx data to Google Sheets (File | Save as Google Sheets);
In the tab named Summary, enter into a cell, say "Summary!A1" the URL of this Google Sheet;
In cell A2 enter: =Char(34)&","&CHAR(34)&"Balances!A1:L5"&Char(34)&")"
In the next tab, enter in cell A1: ="IMPORTRANGE("&Char(34)&Summary!A1&Summary!A2
The leading double quote ensures that the entry is saved as a text string.
Select and copy this text string
in cell A3, type an initial "=" + Paste Special.
This will produce an importrange of the desired text, starting at cell A3

Convert a text string to a formula in a spreadsheet

I'm trying to develop an interactive spreadsheet that creates a narrative for a budget document. There will be a variety of options. Once the user selects an item, it will help them calculate the total. I want to setup option boxes that they fill in. For example, four cells will be allowed for input B1:B4. I am going to name each of the four cells (i.e. A, B, C, D). In the reference document I want to write various formulas. In some cases I might need "(A+B)*C" in another I might need "A * B * C" or "(A+B+C)/D" ... The spreadsheet would lookup the text formula, and I want to then convert it. So in the case of the lookup finding "(A+B)*C" I want it to convert it to =(indirect(A)+indirect(B))*indirect(C) which would then get the values from A (which is B1), B (which is B2) and so on.
Essentially, I would like to use or create something that is exactly the opposite of Excel's FORMULATEXT() function. I would prefer to do this in Google Sheets but I am willing to use Excel if I need to. I have a very basic understanding of both Google's scripting and VBA, and am willing to create if necessary, but not even sure how to tackle it.
Suggestions?
I found a way to do it in Google Apps Script:
function reCalc() {
var sheet = SpreadsheetApp.getActiveSheet();
var src = sheet.getRange("J26"); // The cell which holds the formula
var str = src.getValue();
str = str.replace('A', 'indirect("OPTA")').replace('B', 'indirect("OPTB")').replace('C', 'indirect("OPTC")').replace('D', 'indirect("OPTD")').replace('ENR', 'indirect("ENR")');
var cell = sheet.getRange("J30"); // The cell where I want the results to be
cell.setFormula(str); // Setting the formula.
}
Thank you to SpiderPig for giving me the idea!

Read and write cell formulas from Google Apps Script custom function

I am trying to write a GAS spreadsheet custom function that copies cell content to other cells. And I need to fill the target cells not only with the data of the source cell, but with its formula content (if it has any).
Now, I already know that this is basically impossible through custom functions as they always receive the result of cell calculations but not the cell formulas themselves, and they also cannot return formulas for their target cells.
On the other hand there are functions to read and write cell formulas, e.g. Range.getFormula() and Range.setFormula() which seem to make my endeavor possible. I simply have to find another way of calling them. UPDATE: Meanwhile I found that custom formulas in fact can read formulas using getFormula(), but they definitely don't have permission to write formulas into cells using setFormula().
My question is...
What would be the most elegant method to create something equivalent to a custom function that reads and writes formula content of cells? I think I could use an onEdit function that updates my target cells after each spreadsheet edit, but that would mean that I have to hard code the coordinates of the target cell range, which seems very hacky and would require code changes every time the target range is moved (e.g. when rows are inserted above it).
UPDATE: Example
An example would be a custom function that is able to read multiple ranges of cells (each range given as a distinct function parameter) and returns a joined range of cells.
=rangeJoin(A1:B10;D1:E15)
...would read the two ranges of size 2x10 and 2x15 and would fill a target range of size 2x25 with the subsequent cell contents of both ranges. The target range would start at the cell that contains rangeJoin and would spread 2 cells to the right and 25 cells down (as usual for a custom function). The custom function (or similar mechanism) should be able to copy formulas, so a cell containing =hyperlink("http://www.google.com";"Google") should appear in the target range as a hyperlink and not as a text cell with the naked word 'Google'.
Agree with "Mogsdad"
ie. this custom function works:
function myGrid() {
return [[1,2],[3,"http://www.google.com"]];
}
but, custom functions can't write formulas to a sheet. See https://developers.google.com/apps-script/execution_custom_functions#permissions
As a workaround, you could use a "Trigger", such as a time based trigger, as "Mogsdad" suggests.