I've found the following formula which works great when you are searching within the same sheet in Excel. So this formula works when I want excel to return the last value in row 3.
={INDIRECT(ADDRESS(3,MAX((3:3<>"")*COLUMN(3:3)),1))}
I'm struggling to use it when I want excel to return the last value in row 3 of a different worksheet. Can anyone help?
Thanks
RP
There is no need for INDIRECT in this case.
For working with different worksheets, you have to refer the worksheet within the cell addresses.
{=INDEX(Sheet1!3:3,,MAX((Sheet1!3:3<>"")*COLUMN(Sheet1!3:3)))}
Without using array formulas the same could be achieved with:
=INDEX(Sheet1!3:3,,LOOKUP(2,1/(Sheet1!3:3<>""),COLUMN(Sheet1!3:3)))
But this is basing on a strange not really documented behavior of LOOKUP which takes {1; #DIV/0; 1; 1; #DIV/0} as a sorted array.
The INDEX variants return a cell reference. So we can build dynamic ranges like:
Sheet1!A3:INDEX(Sheet1!3:3,,LOOKUP(2,1/(Sheet1!3:3<>""),COLUMN(Sheet1!3:3)))
If you are only interested in the last value
=LOOKUP(2,1/(Sheet1!3:3<>""),Sheet1!3:3)
will also suffice. But this returns the value only, not the reference.
Pro and cons for the array formula in this case:
pro: It works like it is documented. (Sheet1!3:3<>"") returns TRUE or FALSE and TRUE * COLUMN(Sheet1!3:3) gets COLUMN(Sheet1!3:3) while FALSE * COLUMN(Sheet1!3:3) gets 0. So the MAX then is the biggest column number where (Sheet1!3:3<>"").
con: It is slow. Not unusable in this case, because we work only on all cells in a row. But if we would apply this on all cells in a column, then it would be unusable slow.
Related
I have this formula that works on Google Sheets:
=IF(ISERROR(
INDEX(Students!$A:$H,SMALL(IF(Students!$G:$G=$B$1,ROW(Students!$G:$G)),ROW(1:1)),C$1)),"DELETE",
INDEX(Students!$A:$H,SMALL(IF(Students!$G:$G=$B$1,ROW(Students!$G:$G)),ROW(1:1)),C$1))
It's returning a draggable list of students based on B1 (C1 selects the column)
However, when I download the .xlsx from Google Sheets and opened in in MS Excel, it does not return the students. It returns the 1 row (the header) and nothing else.
What can cause it?
EDIT: added snapshot
It's an array formula, which Google is smart to recognise without the explicit use of ARRAYFORMULA, While Excel isn't. You need to enter the formula with CTRL
+SHIFT+ENTER. The formula should be automatically enclosed in flower brackets { } , if you did it correctly.
The short answer is that you have to put it in as an array formula in Excel (shown here with some dummy data)
But the reason why you just get the first row is much less obvious (to me at any rate)
When you have a range and use it in formula like =G:G, Excel selects a different cell from the range depending where you put the formula (I forget what this mechanism is called?) so in this case the formula in B2 picks up 6-loyalty from Students!G2 and the IF statement gives TRUE and you end up with the smallest of (row) 1, which is just 1, so you get the first row. If you try to get the second smallest, you end up with an error.
I am trying to get some code working but when I change a target cell into a range of cells I get an error #VALUE!
this code works
=IF(AND(A1=Sheet2!A2,B1=Sheet2!B2),"TRUE","FALSE")
but if I add a range I get #VALUE! Error
=IF(AND(A1=Sheet2!A2:A10,B1=Sheet2!B2:B10),"TRUE","FALSE")
Update : Here is an example of what I am trying to achieve
Any help would be much appreciated
Many Thanks,
And
Different approach from your logic statement. Instead it looks through your table and match the name with the row and the column with the date selected and the pulls the value at that location.
=INDEX($B$7:$G$8,MATCH($B3,$A$7:$A$8,0),MATCH(C$1,$B$6:$G$6,0))
IMPORTANT: The names in you B3:B4 area have to be unique and spelled identical to your A7:A8 area. That included trailing or leading spaces that you may accidentally drop in.
Adjust reference ranges to match your need if tables are on different sheets of your workbook.
THIS IS AN ARRAY FORMULA - Hit Ctrl+Shift+Enter While still in the formula bar
=INDEX(B2:B10,SMALL(IF(A2:A10=A1,IF(B2:B10="ONCALL",ROW(A2:A10)-1)),1))
=INDEX(B2:B10, - Look through B2:B10 and return the row number calulcaulated by:
SMALL(IF(A2:A10=A1,
IF(B2:B10="ONCALL",
ROW(A2:A10)-1)),1))
This is building an array of row numbers minus 1 where both IF statements are true (Date matches and "ONCALL" present), SMALL then returns the nth value in ascending order - I have asked for the 1st match (or the smallest row number) which INDEX then uses to return the result.
I have the following formula to return the value of the last value in a column:
=LOOKUP(2,1/(D:D<>""),D:D)
What I need now is to return the value of the cell adjacent to it as well. (It will not necessarily be the last value in that column and the info in Column D could have duplicates.
If your data looks like this:
A 1
A 2
A 3
B 4
B 5
B 6
C 7
To get last value this will do the trick:
=INDIRECT("B"&COUNTA(A:A))
And to get last where value is A:
=INDIRECT("B"&MATCH("A",A1:A7,0)+COUNTIF(A1:A7,"A")-1)
Just use next column:
=LOOKUP(2,1/(D:D<>""),E:E)
Ok, So I have found an answer by playing around with array formulas.
The problem was that this is a stock control sheet where there are changes made at multiple times, each recorded in the next available row. There is always a date (Column E) but not necessarily a Supplier, as it might be stock moving out. When a Supplier delivers, the Supplier name is recorded in Column D. In D1 the last supplier is then shown with the following formula.
=LOOKUP(2,1/(D:D<>""),D:D)
I want to then see what date it was last received. The formula I found that works is as follows (Array Formula):
=INDEX(E:E,MAX(IF(D:D=D1,ROW(D:D)-ROW(INDEX(D:D,1,1))+1)))
This is generally how I do it:
=XMATCH(FALSE,ISBLANK(A:A),0,-1)
This is what each part does:
Parameter
Explanation
FALSE
Instructs Excel to find the first instance of FALSE that it finds
ISBLANK(A:A)
Takes in the column A:A and notionally assigns a value to every item in the column
0
Means we want an exact match. Probably not necessary to put in, but I think it's good practice anyway
-1
Instructs Excel to start the search at the bottom/right of the range and work up/left. If you change this to 1 (the default), Excel will begin the search at the top/left and work down/right
So, taken together, this will search from the bottom of the column A:A, until Excel finds the first cell that is not blank, and return that cell.
Also, yes, this equation can be changed to a row format (e.g. 1:1), and can take a smaller range (e.g. A1:A20), but it cannot take a 2-dimensional range (e.g. A1:B20).
As a practical matter, this approach is much faster than other approaches (and much faster than you'd think, given it's evaluating against every row/column in the range), and won't get fooled by columns that have empty spaces in them (like with a COUNTA style approach).
Good Evening.
I am trying to get my formulas to ignore hidden rows in a filtered table. I have attempted some of the tricks shown here, but I haven't been successful.
The CSV I get from BigFix (network management tool) looks something like:
The applications column lists the applications in the same cell. As a result, when I do a count function to identify the issues, I have to use a wildcard (I'm searching for the results in a different tab).
=COUNTIF('Input Data'!C:C,"*"&Results!A2&"*")
I want to be able to filter the table on the first tab, and have the formula results show up accurately on the 2nd tab.
Any ideas?
UPDATE:
I feel more information would help. The reason I want the "results" tab to update automatically is that I plan to build graphs out of the information on that tab. I would love to be able to filter the table in the 'input data' to include only Department A and have the graph autoupdate to Department A's info.
The excel files I'm working with have up to a thousand entries, and I'm trying to get graphs I can copy/paste to put into a presentation as efficiently as possible.
=SUMPRODUCT(SUBTOTAL(3,OFFSET('Input Data'!C:C,ROW('Input Data'!C:C)-MIN(ROW('Input Data'!C:C)),,1))*(ISNUMBER(SEARCH(A2,'Input Data'!C:C))))
In the above formula Restrict the C:C to your actual data range or use a named range to identify the Actual Data Range.
Edit
Above formula should be replaced with 103 instead of 3 as pointed by Jeep
=SUMPRODUCT(SUBTOTAL(103,OFFSET('Input Data'!C:C,ROW('Input Data'!C:C)-MIN(ROW('Input Data'!C:C)),,1))*(ISNUMBER(SEARCH(A2,'Input Data'!C:C))))
In the above formula Restrict the C:C to your actual data range or use a named range to identify the Actual Data Range.
Adding Explanation based on OP's Request.
In the above formula Used Sumproduct() Subtotal() Offset() Min() Row() IsNumber() Search() function combinations for arriving your expected result.
Row() - Will get the Row Number of a given range
Min() - Will get the Minimum Value of a given Numbers
Offset() - Is used to redirect the reference to each cell of a given range.
Subtotal() - Is used to find the (un)hidden state of redirected reference.
Search() - Is used to find the specific text in a given range (Not case sensitive) will result Number or error.
IsNumber() Is Used to check whether search returns Number or error. So Isnumber will return boolean True/False as result.
Column-C Column-D
Data For Filtering
a 1
b 1
a 1
a 2
a 2
The above data starts from 1st Row with headers in the 1st Row. Assume that I filtered D column With 1. Using the below formula will result 2.
=SUMPRODUCT(SUBTOTAL(103,OFFSET('Input Data'!C2:C6,ROW('Input Data'!C2:C6)-MIN(ROW('Input Data'!C2:C6)),,1))*(ISNUMBER(SEARCH("a",'Input Data'!C2:C6))))
ROW('Input Data'!C2:C6) = {2;3;4;5;6}
MIN(ROW('Input Data'!C2:C6)) = 2
ROW('Input Data'!C2:C6)-MIN(ROW('Input Data'!C2:C6)) should be read as
{2;3;4;5;6}-2 = {0;1;2;3;4}
OFFSET('Input Data'!C2:C6,ROW('Input Data'!C2:C6)-MIN(ROW('Input Data'!C2:C6)),,1) = 'Input Data'!C2,'Input Data'!C3,'Input Data'!C4,'Input Data'!C5,'Input Data'!C6
SUBTOTAL(103,OFFSET('Input Data'!C2:C6,ROW('Input Data'!C2:C6)-MIN(ROW('Input Data'!C2:C6)),,1)) should be read as
SUBTOTAL(103,'Input Data'!C2,'Input Data'!C3,'Input Data'!C4,'Input Data'!C5,'Input Data'!C6) = {1;1;1;0;0}
Subtotal() arrived the visible state of each (cell) reference.
SEARCH("a",'Input Data'!C2:C6) = {1;#VALUE!;1;1;1}
ISNUMBER(SEARCH("a",'Input Data'!C2:C6)) should be read as
ISNUMBER({1;#VALUE!;1;1;1}) = {TRUE;FALSE;TRUE;TRUE;TRUE}
SUBTOTAL(103,OFFSET('Input Data'!C2:C6,ROW('Input Data'!C2:C6)-MIN(ROW('Input Data'!C2:C6)),,1)) = {1;1;1;0;0}
(ISNUMBER(SEARCH("a",'Input Data'!C2:C6))) = {TRUE;FALSE;TRUE;TRUE;TRUE}
{1;1;1;0;0}*{TRUE;FALSE;TRUE;TRUE;TRUE} = {1;0;1;0;0}
SUMPRODUCT({1;0;1;0;0}) = 2
Used Sumproduct() to avoid Array Entry and also to do the Array Formula Task (Looping through the range of cells) and Sumproduct() will result the Sum of the passed values.
Instead of filtering the source data, use the Countifs function and add the filter conditions to the Countifs.
I've searched for an answer for this for awhile now but haven't had any luck. It's a bit difficult to put into words, so please let me know if anything's unclear.
What I want is a way to perform conditional statements on two columns. When both conditions are true, I want to return the value from a third column that is in the same row as where these conditions were met. So if the conditions are true in D5 and C5, I want to return the value from Q5 into the cell with the formula. The conditional statements are easy enough but I haven't figured out the last step yet.
If I use the following formula, I get 1 in the cell with the formula, which is right.
=IF(AND('Stata Output'!D2:D6='Backcheck schedule and results'!C2, 'Stata Output'!C2:C6=1),1,0)
However, replacing 1 in the formula with the range of cells that I want to pull the value from gives me a zero every time, which I know is wrong. For this latter formula I'm using:
=IF(AND('Stata Output'!D2:D6='Backcheck schedule and results'!C2, 'Stata Output'!C2:C6=1),'Stata Output'!Q2:Q5,0)
Any ideas on where I'm messing up?
Thanks!
Give this a shot - I'm sure there is a simpler way but it seems to get the job done (make sure to enter as an array formula with Control+Shift+Enter):
=INDEX('Stata Output'!$D$2:$Q$6,MATCH(1,(--('Stata Output'!$C$2:$C$6=1)*--('Stata Output'!$D$2:$D$6="Backcheck schedule and results")),0),14)
What this does is take your entire table as the range (first argument to INDEX, then uses MATCH to find the row where both of your conditions are met (in this case, column C must be 1 and the corresponding value in column D must be Backcheck schedule and results). You then search the resulting array for 1 (which indicates the match) and return column 14 (which represents column Q in our table). You can continue to add filters inside the MATCH() function as needed.
Note that this will match only the first 'hit'.
Looks like AND isn't working correctly in array formulas, so I would use this:
=IF(('Stata Output'!D2:D6='Backcheck schedule and results'!C2)*('Stata Output'!C2:C6=1)=1,'Stata Output'!Q2:Q5,0)
This will give you a new results column, that will be filled from the Q2:Q6 column for every matching row.
To use it, you should select all of the results column, input the formula and then use CTRL+SHIFT+ENTER.
Just make sure to use use ranges of the same size.
Try the following formula:
=LOOKUP(2,1/('Stata Output'!D2:D6='Backcheck schedule and results'!C2)/('Stata Output'!C2:C6=1),'Stata Output'!Q2:Q5)
If there is more than one row where both conditions are satisfied, this formula will return the col Q value from the last of those.