I am trying to use a formula that uses INDEX function. In order to generalize for all the lines that sometimes may contain information from another sheet and sometimes they may not.
That's why I get an ISREF error within the cells because the corresponding cells in the other sheet can't be referenced.
I want to display a default value instead of the ISREF error message. I tried using ISREF function itself within an IF condition but it doesn't work on the same cell. It only references another cell because it is a cell checking function and it doesn't check the output of a formula.
I tried also ISERROR function but it didn't work also. Here's a snippet of the formula that I am putting within my cell:'
INDEX(Plagesuivi; $Q203; 9)
Plagesuivi is a named range
$Q203 contains the row number (that I fetch dynamically and correctly)
9 is the column number
P.S. The indexing is working fine with cells that do appear is the named range: Plagesuivi
I would go with iferror() like this:
=iferror(INDEX(Plagesuivi;$Q203;9);0)
Or replace the 0 with ""
After trial and error the best way to avoid all sorts of errors is:
= IF($Q203=""; 0; IFERROR(INDEX(Plagesuivi; $Q203; 9); 0))
IFERROR checks for all sorts of unpredictable errrors it is a safe-guard against unpredicted cases where it takes 0 by default.
IF in the second case checks whether the referencing content of Q203 is empty or not, in case it is empty the cell takes 0 by default else it gets the output of the false case formula.
To give some detail, I am using Google Forms + Google Sheets to make an easy database that collects all the bank information I put in (Income, savings, expenses, etc.) and I can keep track of details with easy sorting.
I'm stuck on a formula that I can't seem to figure out. Before I go in to specific details of my code I will give a small explanation. The cell I am trying to populate [with the formula] is supposed to take 2 pieces of information from the form response sheet (I will refer to it as 'rawdata') and produce a value (number) from another cell in 'rawdata'.
So in 'rawdata' I have a column (B) that has a value of "Expense" or "Income" for a form response line. I have a column (D) in 'rawdata' that has the value of "Amount" for the number submitted.
Cells in reference in 'rawdata':
B9 = "Expense"
D9 = 67.37
Now, due to the original 'rawdata' being a form response sheet it inserts new rows every response, so my attempt at just calling direction to the cell fails upon a new response submission because it increments on its own. So that being a solution is out of the question.
So, for every other cell I am using to display values from 'rawdata' in an organized sheet I use =INDEX() to pull the value from that exact row and column, instead of the cell reference and it has worked so far.
=INDEX(rawdata!$B:$B,ROW(9:9)) displays "Expense" from 'rawdata' in B9 as a result. So the rest of the cells are formulated this way and I have had no issues.
When I got to the amount, I used an =IF() formula to pull the value from the D column and to display it either as a negative or positive depending on what column B states.
=IF(rawdata!B8="Expense", -rawdata!$D9, rawdata!$D9) displays -67.37 as a result.
But since I can't use this formula to fill empty cells for future use I have to find another way to do so. I figure;
=IF(=INDEX(rawdata!$B:$B,ROW(9:9)) = "Expense", =INDEX(-rawdata!$D:$D,ROW(9:9)), =INDEX(rawdata!$D:$D,ROW(9:9)))
is my solution to the problem, because to me it makes sense. But it fails and gives me a Parse Error.
So when I try to run the first =INDEX() with the values of 1 or 0 being the outcome of the =IF() it also fails, so I create a new column in the sorted table to pull the data of "Expense" or "Income" so I can reference that.
Cell in 'processeddata':
E9 = "Expense"
=IF(E9="Expense", 1, 0) displays 1 as its result, so I figure this is the solution to my problem.
=IF(E9="Expense", =INDEX(-rawdata!$D:$D,ROW(9:9)), =INDEX(rawdata!$D:$D,ROW(9:9)))
displays #ERROR with the description Parse Error.
=INDEX(-rawdata!$D:$D,ROW(9:9)) displays -67.37
=INDEX(rawdata!$D:$D,ROW(9:9)) displays 67.37
I'm at a loss for what to do now. I've exhausted myself with tons of searching on here and all over google, tried using things like INDEX and MATCH, VLOOKUP, etc but can't solve this to save my life. Does anyone here have a clue how I can solve this with a cell reference that won't increment when new rows are added in 'rawdata'?
PS. I've also attempted using =VALUE() to try and convert the =INDEX() to a number but no luck.
Your formula has superfluous equals signs (=). Try Insert > Column and this formula in row 8 of the new column:
=arrayformula( if(rawdata!B8:B = "Expense", -rawdata!D8:D, rawdata!D8:D) )
Your formula has some equal signs in it that are probably the issue.
Instead of this:
IF(=INDEX(rawdata!$B:$B,ROW(9:9)) = "Expense", =INDEX(-rawdata!$D:$D,ROW(9:9)), =INDEX(rawdata!$D:$D,ROW(9:9)))
try this:
IF(INDEX(rawdata!$B:$B,ROW(9:9)) = "Expense", INDEX(-rawdata!$D:$D,ROW(9:9)), INDEX(rawdata!$D:$D,ROW(9:9)))
Also, an array formula is a great tool for Form data calculations. In this file you can see a formula in Column F that does a calculation in each row of the responses sheet from this form, it will continue to update as new entries are made. Feel free to enter submit some form responses.
The following illustration should help:
Here is what I found for Google Sheets:
To get the current sheet name in Google sheets, the following simple script can help you without entering the name manually, please do as this:
Click Tools > Script editor
In the opened project window, copy and paste the below script code into the blank Code window, see screenshot:
......................
function sheetName() {
return SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getName();
}
Then save the code window, and go back to the sheet that you want to get its name, then enter this formula: =sheetName() in a cell, and press Enter key, the sheet name will be displayed at once.
See this link with added screenshots: https://www.extendoffice.com/documents/excel/5222-google-sheets-get-list-of-sheets.html
You have 2 options, and I am not sure if I am a fan of either of them, but that is my opinion. You may feel differently:
Option 1: Force the function to run.
A function in a cell does not run unless it references a cell that has changed. Changing a sheet name does not trigger any functions in the spreadsheet. But we can force the function to run by passing a range to it and whenever an item in that range changes, the function will trigger.
You can use the below script to create a custom function which will retrieve the name:
function mySheetName() {
var key = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getName();
return key;
}
and in the cell place the following:
=mySheetName(A1:Z)
Now if any value in a cell in that passed range changes the script will run. This takes a second to run the script and sets a message in the cell each time any value is changed so this could become annoying very quickly. As already mentioned, it also requires a change in the range to cause it to trigger, so not really helpful on a fairly static file.
Option 2: Use the OnChange Event
While the run time feels better than the above option, and this does not depend on a value changing in the spreadsheet's cells, I do not like this because it forces where the name goes. You could use a Utilities sheet to define this location in various sheets if you wish. Below is the basic idea and may get you started if you like this option.
The OnChange event is triggered when the sheet name is changed. You can make the code below more sophisticated to check for errors, check the sheet ID to only work on a given sheet, etc. The basic code, however, is:
function setSheetName(e) {
var key = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getName();
SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange('K1').setValue(key);
}
Once you have saved the code, in the script editor set the Current Project's On Change Trigger to this function. It will write the sheet name to cell K1 on any change event. To set the trigger, select Current project's triggers under the Edit menu.
If you reference the sheet from another sheet, you can get the sheet name using the CELL function. You can then use regex to extract out the sheet name.
=REGEXREPLACE(CELL("address",'SHEET NAME'!A1),"'?([^']+)'?!.*","$1")
update:
The formula will automatically update 'SHEET NAME' with future changes, but you will need to reference a cell (such as A1) on that sheet when the formula is originally entered.
Not using script:
I think I've found a stupid workaround using =cell() and a helper sheet. Thus avoiding custom functions and apps script.
=cell("address",[reference]) will provide you with a string reference (i.e. "$A$1") to the address of the cell referred to. Problem is it will not provide the sheet reference unless the cell is in a different sheet!
So:
where
This also works for named sheets. Then by all means adjust to work for your use case.
Source: https://docs.google.com/spreadsheets/d/1_iTD6if3Br6nV5Bn5vd0E0xRCKcXhJLZOQqkuSWvDtE/edit#gid=1898848593
EDIT:
I've added another workaround in the document that makes use of =formulatext() and some traditional text functions. By referencing to a cell in the current sheet using it's full address, i.e. Sheet1A1 you are able to use formulatext() to extract only the sheet name.
Here is my proposal for a script which returns the name of the sheet from its position in the sheet list in parameter. If no parameter is provided, the current sheet name is returned.
function sheetName(idx) {
if (!idx)
return SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getName();
else {
var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
var idx = parseInt(idx);
if (isNaN(idx) || idx < 1 || sheets.length < idx)
throw "Invalid parameter (it should be a number from 0 to "+sheets.length+")";
return sheets[idx-1].getName();
}
}
You can then use it in a cell like any function
=sheetName() // display current sheet name
=sheetName(1) // display first sheet name
=sheetName(5) // display 5th sheet name
As described by other answers, you need to add this code in a script with :
Tools > Script editor
An old thread, but a useful one... so here's some additional code.
First, in response to Craig's point about the regex being overly greedy and failing for sheet names containing a single quote, this should do the trick (replace 'SHEETNAME'!A1 with your own sheet & cell reference):
=IF(TODAY()=TODAY(), SUBSTITUTE(REGEXREPLACE(CELL("address",'SHEETNAME'!A1),"'?(.+?)'?!\$.*","$1"),"''","'", ""), "")
It uses a lazy match (the ".+?") to find a character string (squotes included) that may or may not be enclosed by squotes but is definitely terminated by bang dollar ("!$") followed by any number of characters. Google Sheets actually protects squotes within a sheet name by appending another squote (as in ''), so the SUBSTITUTE is needed to reduce these back to single squotes.
The formula also allows for sheet names that contain bangs ("!"), but will fail for names using bang dollars ("!$") - if you really need to make your sheet names to look like full absolute cell references then put a separating character between the bang and the dollar (such as a space).
Note that it will only work correctly when pointed at a different sheet from the one that the formula resides! This is because CELL("address" returns just the cell reference (not the sheet name) when used on the same sheet. If you need a sheet to show its own name then put the formula in a cell on another sheet, point it at your target sheet, and then reference the formula cell from the target sheet. I often have a "Meta" sheet in my workbooks to hold settings, common values, database matching criteria, etc so that's also where I put this formula.
As others have said many times above, Google Sheets will only notice changes to the sheet name if you set the workbook's recalculation to "On change and every minute" which you can find on the File|Settings|Calculation menu. It can take up to a whole minute for the change to be picked up.
Secondly, if like me you happen to need an inter-operable formula that works on both Google Sheets and Excel (which for older versions at least doesn't have the REGEXREPLACE function), try:
=IF(IFERROR(INFO("release"), 0)=0, IF(TODAY()=TODAY(), SUBSTITUTE(REGEXREPLACE(CELL("address",'SHEETNAME'!A1),"'?(.+?)'?!\$.*","$1"),"''","'", ""), ""), MID(CELL("filename",'SHEETNAME'!A1),FIND("]",CELL("filename",'SHEETNAME'!A1))+1,255))
This uses INFO("release") to determine which platform we are on... Excel returns a number >0 whereas Google Sheets does not implement the INFO function and generates an error which the formula traps into a 0 and uses for numerical comparison. The Google code branch is as above.
For clarity and completeness, this is the Excel-only version (which does correctly return the name of the sheet it resides on):
=MID(CELL("filename",'SHEETNAME'!A1),FIND("]",CELL("filename",'SHEETNAME'!A1))+1,255)
It looks for the "]" filename terminator in the output of CELL("filename" and extracts the sheet name from the remaining part of the string using the MID function. Excel doesn't allow sheet names to contain "]" so this works for all possible sheet names. In the inter-operable version, Excel is happy to be fed a call to the non-existent REGEXREPLACE function because it never gets to execute the Google code branch.
I have a sheet that is made to used by others and I have quite a few indirect() references around, so I need to formulaically handle a changed sheet tab name.
I used the formula from JohnP2 (below) but was having trouble because it didn't update automatically when a sheet name was changed. You need to go to the actual formula, make an arbitrary change and refresh to run it again.
=REGEXREPLACE(CELL("address",'SHEET NAME'!A1),"'?([^']+)'?!.*","$1")
I solved this by using info found in this solution on how to force a function to refresh. It may not be the most elegant solution, but it forced Sheets to pay attention to this cell and update it regularly, so that it catches an updated sheet title.
=IF(TODAY()=TODAY(), REGEXREPLACE(CELL("address",'SHEET NAME'!A1),"'?([^']+)'?!.*","$1"), "")
Using this, Sheets know to refresh this cell every time you make a change, which results in the address being updated whenever it gets renamed by a user.
I got this to finally work in a semi-automatic fashion without the use of scripts... but it does take up 3 cells to pull it off. Borrowing from a bit from previous answers, I start with a cell that has nothing more than =NOW() it in to show the time. For example, we'll put this into cell A1...
=NOW()
This function updates automatically every minute. In the next cell, put a pointer formula using the sheets own name to point to the previous cell. For example, we'll put this in A2...
='Sheet Name'!A1
Cell formatting aside, cell A1 and A2 should at this point display the same content... namely the current time.
And, the last cell is the part I'm borrowing from previous solutions using a regex expression to pull the fomula from the second cell and then strip out the name of the sheet from said formula. For example, we'll put this into cell A3...
=REGEXREPLACE(FORMULATEXT(A2),"='?([^']+)'?!.*","$1")
At this point, the resultant value displayed in A3 should be the name of the sheet.
From my experience, as soon as the name of the sheet is changed, the formula in A2 is immediately updated. However that's not enough to trigger A3 to update. But, every minute when cell A1 recalculates the time, the result of the formula in cell A2 is subsequently updated and then that in turn triggers A3 to update with the new sheet name. It's not a compact solution... but it does seem to work.
To match rare sheets names like:
Wow!
Oh'Really!
''!
use the formula:
=SUBSTITUTE(REGEXEXTRACT(CELL("address";Sheet500!A1);"'?((?U).*)'?!\$[A-Za-z]+\$\d+$");"''";"'")
or
=IF(NOW();SUBSTITUTE(REGEXEXTRACT(FORMULATEXT(A1);"='?((?U).*)'?![A-Za-z]+\d+$");"''";"'")) if A1 is formula reference to your sheet.
if you want to use build-in functions:
=REGEXEXTRACT(cell("address";'Sheet1'!A1);"^'(.*)'!\$A\$1$")
Explanation:
cell("address";'Sheet1'!A1) gives you the address of the sheet, output is 'Sheet1'!$A$1. Now we need to extract the actual sheet name from this output. I'm using REGEXEXTRACT to match it by regex ^'(.*)'!\$A\$1$, but you can either use more/less specific regex or use functions like SUBSTITUTE or REPLACE
I have a spreadsheet where I have data from a bank account. Each bank transaction has a date and an indication if that transaction is already done or if it's just expected. When it's already done, it must be added to the total balance up to date. If not, then the total balance up to date must be blank. I need to autofilter the data, so I can filter and order it depending on date or other conditions, that's why I've been using this formula:
=IF(D3="Y";B3+INDIRECT(ADDRESS(ROW()-1;COLUMN()));"")
Problem here is that when the cell above is blank, total sum resets and it starts from the value of that transaction. I need a formula that ignores the upper blank cells, and sums all cells above that are not blank plus the amount of that transaction.
Besides, once I change the "N" in "Done" Column to a "Y" I need the formula to update and show the correct balance.
I share an example sheet for better understanding https://docs.google.com/spreadsheets/d/1_gk0YaziUhOZfRbrlfHizMrVu6OT7njIaTUyQaE6Lbs/edit?usp=sharing
Ok I THINK I understand what your going for - please let me know if I am confused, but I added an example on your sheet.... basically what I ended up doing was including one of your conditionals, but then also adding another function to exclude the blank rows by way of filter , index and counta It looks more complicated than it is because I nested it all back into one formula:
=IF(I3="Y";sum(G3;index(filter(indirect("F2:"&address(row()-1;column();4));ISNUMBER(indirect("F2:"&address(row()-1;column();4))));counta(filter(indirect("F2:"&address(row()-1;column();4));ISNUMBER(indirect("F2:"&address(row()-1;column();4)))))););)
To work it from the inside out - the way I am excluding the blank rows is by using FILTER to get all the rows from the first row with a value ( Like A2 in your example) and using INDIRECT and ADDRESS to end the array I want to include exactly one cell above the current cell.
Then I use the condition that the range I built has a number value in it, there fore excluding the blanks.
In order to get the last value available, I use COUNTA to find out the total rows in the filter, then wrap the formula with INDEX to use the counta value as the row to return (which automatically is the last row available above the current cell)
Try this in A3 and copy down:
=IF(D3="Y";B3+INDIRECT(ADDRESS(ROW()-1;COLUMN()));A2+0)
If you want to display the "N" rows as blank, add a column (B) fill in the header and the starting number (5000) then put this in B3:
=if(E3="N";"";A3)
Copy it down then hide column A.
I have two columns I do the sumproduct operation on them this way:
=SUMPRODUCT(I37:I61, **D37:D61**)
and it works perfectly well - I put the result in the cell I8
but when I copy this function to cell J8
it transfers to:
=SUMPRODUCT(J37:J61, **E37:E61**)
I want TO FIX one array, so my function would look like
=SUMPRODUCT(J37:J61, D37:D61)
I hope it's clear what do I want to achieve :)
are there any ways to do so?
Not sure about google spreadsheet, but in microsoft Excel you would need to use below formula for ur use. I think same will work in Google Spreadsheet too.
=SUMPRODUCT(I37:I61, $D37:$D61)
Notice '$' which says not to translate D when you do copy-paste.
I would used named ranges to avoid any confusion. Here are the steps
1) Select the range D37:D61
2) give the name a range by tying in a name to the left hand side of the fx near where you insert the formula
3) let's call that range DATA1
4) then use the formula =SUMPRODUCT(I37:I61, DATA1)
5) when you copy this formula over to next cells it should show as =SUMPRODUCT(J37:J61, DATA1)
Let me know how you get on.