I use a Google SpreadSheet add-on to make Google Analytics Reports. My problem is that for each query this add-on creates a different sheet. I often have around 50 different sheet with data that must be compiled into a single sheet. For example:
I might have 3 sheets named: "Organic Data", "Direct Data" and "Other Data"
Each sheet has a different set of data that I want to compile into a single table in a 4th sheet called "Report". This table will have in its first column data from the "Organic Data" sheet, in its second column data from the "Direct Data" sheet and in its third column data from the "Other Data" sheet.
The way I´m doing this is by referencing the cells one by one. So in the "Report" sheet I will write =Organic Data!B4 and then drag to fill the other cells of the column, and then I would do this for the other sheets to fill up the other columns of the "Report" sheet.
The problem is that, as I´ve said, I often have more than 50 different sheets and referencing them can get quite hard.
I would like to do this dynamically. Have the names of the sheets on a cell and use that to reference the cells. For example:
In the "Report" sheet:
A1 = "Organic Data", B1 = "Direct Data", C1 = "Other Data"
In cell "Report!A2" I´ve tried writing =CONCAT("=",A1,"!","B4") hoping to get in this cell the value of the cell "Organic Data!B4", but instead I get the string "=Organic Data!B4, and not the value of the cell in "Organic Data" sheet.
I`ve made a custom formula to solve this problem:
function referenceSheet(sheetName, cellInput) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var cell = ""
var cell = sheetName+'!'+cellInput;
var value = ss.getRange(cell).getValue();
return value;
}
It works quite well. In my example above to get the value of the cell "Organic Data!B4" into the cell "Report!A2", I need to write on "Report!A2" the following:
"=referenceSheet(A1, cell("address",B4))"
and it will return the value of the cell "Organic Data!B4".
I do have some issues with this custom formula that I´ve made. Mainly, custom formulas don´t refresh onChange, so if I change the value of "Organic Data!B4", "Report!A2" will not change.
I would like to know if there´s a native formula that does something similar to my custom formula?
If not, what´s the best way to make my custom formula to refresh as I change the date from other cells?
Thank You Very Much!
I´ve posted the same question on Google Forums and got a nice answer.
There is a native formula call =INDIRECT
For my exemple it works like this:
=INDIRECT(CONCATENATE(A$1,"!",cell("address",$B4)),true)
Related
1st of all sorry for my poor english.
trying to put with a macro a formula into a cell to find the corrispective value of 2nd column in row with "Banana" in first column with VLOOKUP.
simple spreadsheet with a module sheet linked
function searchBanana() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.getRange('A5').activate();
spreadsheet.getCurrentCell().setFormula('=VLOOKUP("banana";fruit!A:D;2;FALSE)');
};
when I register the macro or I write the formula manually it works well,
if I create the formula by macro I got error on formula (just on spreadsheet view, not in code view). If I copy-paste the formula generated by the macro into another cell it work.
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
I am trying to copy data from a sheet (SheetA) to another sheet (SheetB)
However, I need the row of the cell to be copied (From Sheet A) to be based off of another cell.
For example:
SheetA has data on A1, A2, A3, A4 etc...
SheetB has a cell (B1) that a user types in a value.
When the script is run the data from SheetA will be copied from column A and a row based off of the value in B1 to SheetB.
So if a user types "5" into B1 and runs, the data from A5 will be copied from SheetA to A1 on sheetB
Here is a script that I have so far, how do I modify this correctly to complete the code?
//Moves data from SheetA -> SheetB;
SheetA.getRange("?").copyTo(SheetB.getRange("A1"));
What do I have to replace where the '("?")' is?
Thank you!
Using setValue() instead will be easier to implement and understand.
Try to implement like below:
Get the value of the input from SheetB
var inputValue = SheetB.getRange(SheetBRow, SheetBColumn).getValue();
-
Use the inputValue as a row parameter for getRange() to get the value
of a cell from SheetA
var SheetACellValue = SheetA.getRange(inputValue, SheetAColumn).getValue();
-
Set the value of a cell on SheetB using the value from SheetACellValue
Cell SheetBCell = SheetB.getRange(SheetBRow,SheetBColumn);
SheetBCell.setValue(SheetACellValue);
You can implement this by method chaining. I just divided each for a better view and understanding.
Assuming you defined SheetA and SheetB and the copyTo Range is fixed (A1) this is your code (following the syntax in your attempt):
SheetA.getRange('A'+SheetB.getRange('B1').getValue).copyTo(SheetB.getRange('A1'));
or (using setValue instead of copyTo because you are adressing one specific cell):
SheetB.getRange('B1').setValue(SheetA.getRange('A'+SheetB.getRange('B1').getValue));
This is basic knowledge when working with Apps Script and Sheets. I recommend you read up on the SpreadsheetApp Documentation.
Moreover this is a duplicate of so many similar questions. Next time search for your question using the google-apps-script tag.
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.
The problem:
When using IMPORTRANGE to pull data from a different spreadsheet, cells in the origin spreadsheet that contain a formule containing VLOOKUP often (but not always) return #N/A (ERROR: Did not find value 'xxx' in VLOOKUP evaluation). In the origin sheet the formulas are calculated correctly and showing a value though. This does not always happen, sometimes it does pull in the proper value.
The intent:
To take data from different spreadsheets, combine them in a different spreadsheet and do some calculations on them. And then pull info from this calculation spreadsheet (or from multiple calculation spreadsheets) into a reporting spreadsheet for some further calculations and formatting.
The set-up:
There are several source data spreadsheets,say dataspreadsheet1, dataspreadsheet2 and dataspreadsheet3. A calculation spreadsheet (calcspreadsheet) is created that creates a copy of sheet1 in each of the data spreadsheets and names these sheets datasheet1, datasheet2 and datasheet3 respectively. The IMPORTRANGE statement used for this is created as follows: importrange(+VLOOKUP("dataspreadsheet1",filelist!A1:C1000,3,FALSE),"sheet1!a1:Z1000") where
filelist!A1:C1000 is a sheet in calcspreadsheet that contains Name, Type and Id in respective columns.
The values in each of these sheets datasheet1-3 are then used for calculations in another sheet, calcsheet1 in the calcspreadsheet. As the main goal of this is to add up daily values from the 3 dataspreadsheets, but those sourcesheets do not all have the same data on the same line a VLOOKUP is used again to make sure additions for a date use the line for the date in datasheet1-3 regardless of its row number. E.g. VLOOKUP($A11,'datasheet1'!$A:$P,4) + VLOOKUP($A11,'datasheet2'!$A:$P,4) + VLOOKUP($A11,'datasheet3'!$A:$P,4) where column A is the date column in all sheets.
This appears to work fine, although upon opening calcspreadsheet it can take a long time for it to go through an update, during which time lots of #N/A's are displayed. Eventually it comes right though.
The problem arise when a reportspreadsheet is created that in turn used an IMPORTRANGE call to pull the info from calcsheet1 in order to be able to work with it. This often, but not always, results in the problem states at the start. The IMPORTRANGE call in this reportspreadsheet is generated in a similar way as that in the calcspreadsheet: =importrange(+VLOOKUP(calc!B1,sheetcodes!A1:C3000,3,FALSE),"sheet1!a1:Z1000") where calc!B1 contains the name of the source spreadsheet (in this calc that would be 'calcspreadsheet' and sheetcodes!A1:C3000 again contains a list of sheets with Name, Type and Id in respective columns
A work-around I tried:
What I did notice that IMPORTRANGE works better on cells that do not contain VLOOKUP So I tried to copy the content of calcsheet to another sheet in calcspreadsheet, called exportsheet but having only the values in there, not formulas and then use IMPORTRANGE on this exportsheet. The copy script used is as follows:
function exportPrep() {
// Get the active spreadsheet and the active sheet
//var ss = SpreadsheetApp.getActiveSpreadsheet();
//var sheet = ss.getSheetByName("stream");
//sheet.activate();
var source = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("calcsheet");
var sourceDataRange = source.getDataRange();
var sourceSheetValues = sourceDataRange.getValues();
var sourceRows = sourceDataRange.getNumRows();
var sourceColumns = sourceDataRange.getNumColumns();
var destination = SpreadsheetApp.getActiveSpreadsheet();
SpreadsheetApp.setActiveSheet(destination.setActiveSheet("exportsheet"));
destination.getDataRange().offset(0, 0, sourceRows, sourceColumns).setValues(sourceSheetValues);
}
This seemed to work, but unfortunately the copy script used to copy the value of calcsheet into exportsheet now showed the same behaviour, it would sometimes work and sometimes give the #N/A and so leaves me with the same problem.
My questions:
I've read various posts with similar issues and responses that mentioned this function was temperamental or had a bug. Other stated it is not possible to use dynamic references in IMPORTRANGE. Given that it sometimes works and sometimes not I suspect the function itself might be correct but that there are sync or time-out issues in the set-up.
How can I set up the above functionality. Either with the use of IMPORTRANGE and VLOOKUP at all with some changes/additions, or built in a different way from the get-go.
So I've not done this with importrange but I when I have this issue with Vlookup I wrap the vlookup in an IF and test for the #N/A.
Try something like: =IF(ISNA(VLOOKUP(...)),"",VLOOKUP(...))
=IFERROR(VLOOKUP(B81,'KAM_Q3_OPPS STAGE_(H/I/L/M/N)'!$F$3:$G$111,2,False),)
This is the best way I found to do it and the last two values [ , ) ] make the new output, in this case it is nothing.
IF you wanted 0 put in then you would do [ ,0) ]