Extracting all rows based on a value of cell without VBA - excel

I'm really struggling to find an answer to this as online I've really only found VBA solutions to this problem which isn't what I wish to learn how to do.
THE PROBLEM
BLOOD NAME AGE GENDER
A David 18 Male
B Sarah 22 Female
O Lucy 32 Female
AB Steven 23 Male
O John 11 Male
B Mike 25 Male
AB Paul 24 Male
O Amy 23 Female
B Drake 22 Female
O Linda 11 Female
Very simply from the above dataset I wish to recreate this range but filter for only select BLOOD TYPE O.
MY ATTEMPTS
Started with a VLookup table however that stops at the first occurrence of O. Then tried incorporating IF/THEN/ELSE logic into a MATCH operand trying to locate the row numbers outputting to an array. (not gonna post my failed attempts) I did find a similarish problem online however they solved it via referencing the range manually using ROW(A1), ROW(A2) etc etc wasn't what I after.
Really want to learn how to do this type of iterative selections using Excel formulae only. Even if not solving the problem any direction towards resources where I can learn more about this type problem, would be still appreciated.

This does not use array formulas, but does use a helper column. Assuming data in cols A through D, in E2 enter:
=IF(A2="O",1+MAX($E$1:E1),"")
and copy down:
Each of the O rows is marked with a simple sequential value. This makes it easy for the usual MATCH() / INDEX() methods.
Pick some other cell and enter:
=IFERROR(INDEX(A:A,MATCH(ROWS($1:1),$E:$E,0)),"")
and copy this cell both across and down:

Here is a solution with array formulas. It will calculate extremely slowly, and honestly VBA is a much better solution. You will need to tell excel these are array formulas by hitting "Ctrl + Shift + Enter" after inputting the formulas, this will add the {} around the equation. Finally, drag down the array formulas to see the first "X" results with blood type "O":
First cell formula for "Blood" --> assumes blood is in column A of sheet1
{=IFERROR(INDEX(Sheet1!$A:$D,SMALL(IF(Sheet1!$A:$A="O",ROW(Sheet1!$A:$A)),ROW(1:1)),1,1),"")}
First cell formula for "Name" --> assumes name is in column B of sheet1
{=IFERROR(INDEX(Sheet1!$A:$D,SMALL(IF(Sheet1!$A:$A="O",ROW(Sheet1!$A:$A)),ROW(1:1)),2,1),"")}
First cell formula for "Age" --> assumes age is in column c of sheet1
{=IFERROR(INDEX(Sheet1!$A:$D,SMALL(IF(Sheet1!$A:$A="O",ROW(Sheet1!$A:$A)),ROW(1:1)),3,1),"")}
First cell formula for "Gender" --> assumes gender is in column d of sheet1
{=IFERROR(INDEX(Sheet1!$A:$D,SMALL(IF(Sheet1!$A:$A="O",ROW(Sheet1!$A:$A)),ROW(1:1)),4,1),"")}
Results:
BLOOD NAME AGE GENDER
O Lucy 32 Female
O John 11 Male
O Amy 23 Female
O Linda 11 Female

The following array formula can be put in row 2 (anywhere from column E onward) and copied across 3 columns and down as far as is necessary:
=IFERROR(INDEX(A:A,SMALL(IF(ISNUMBER(SEARCH("O",$A$2:$A$11)),ROW($A$2:$A$11),""),ROW()-1)),"")
This is entered using Ctrl + Shift + Enter and uses a fixed array (A2:A11). If your array is going to change size, you can make the reference to it dynamic by using INDIRECT and COUNTA so that it always encompasses the used range, like so:
=IFERROR(INDEX(A:A,SMALL(IF(ISNUMBER(SEARCH("O",INDIRECT("$A2:$A"&COUNTA(A:A)))),ROW(INDIRECT("$A2:$A"&COUNTA(A:A))),""),ROW()-1)),"")
What is happening:
The SEARCH function is looking for "O"s, then the IF returns the row number if an "O" was found and nothing if no "O" was found.
The SMALL function is looking for the nth instance of the results returned by the SEARCH function, where n = ROW()-1.
The INDEX function returns the nth value from the array A:A, B:B, etc, where n = the row number returned by the SMALL function.
The IFERROR function is not necessary but it makes for a cleaner dataset, all it does is replace the formulas that didn't return anything useful with a blank instead.

Try this standard formula:
= IFERROR( INDEX( A$2:A$11, AGGREGATE( 15, 6,
ROW($A:$A) / ( $A$2:$A$11 = "O" ), ROWS( $A$2:$A2 ) ) ), "" )
or if you want to limit the size of size of column A
= IFERROR( INDEX( A$2:A$11, AGGREGATE( 15, 6,
ROW($A$1:$A$11) / ( $A$2:$A$11 = "O" ), ROWS( $A$2:$A2 ) ) ), "" )
Enter the formula in G2 then copy it to G2:J10

Related

Sumproduct matching values in excel

I have two excel tables:
A B C D E
1 John 10 Mark 2
2 Tommy 20 Tommy 3
3 Jane 15 John 4
4 Kate 2
5 Jane 1
Is there a function to sumproduct values in colum B with those values in column E which match by name, i.e. 10*4 + 20*3 + 15*1 ?
You can use sumif for this and just sum up the results when you are done:
=B1 * sumif(D:D, A1, E:E)
Copy that down your sheet, and then add up the totals.
If you don't want a ton of formulas hanging out on your sheet, you could convert this to a CSE/Array formula:
=SUM($B$1:$B$3*SUMIF(D:D, $A$1:$A$3,E:E ))
Just enter that in and hit Ctrl+Shift+Enter to enter it. It will get curly braces around it, which means it's an Array formula.
Since you asked about sumproduct, we could use SUMPRODUCT
=SUMPRODUCT(($A$1:$A$5=A1)*$B$1:$B$5)*SUMPRODUCT(($D$1:$D$5=A1)*$E$1:$E$5)
Now that is assuming there are no repeats (all names are unique). In the event that names are not unique you will have those numbers added together then multiplied.
After you apply that to a column and copied down appropriately, lets say F1 to F3, in F5 you could get your final answer using:
=SUM(F1:F3)

Counting unique list of items from range based on criteria from other ranges

I have a file with data in the following format:
text value1 value2
Given value 1 and value 2 meet some criteria, find all the unique text values.
The exact data looks like this:
john 10 20
john 15 35
mark 20 10
mark 25 15
tom 25 40
lee 16 50
If val 1 <=25 and value 2 <=35 the number of unique text = 2 (john and mark)
I have to do this using formulas not filters.
I've been trying combinations of frequency, countifs, sumproducts and a whole range of other methods and can't seem to hit what I'm looking for.
Assuming that text, value1, and value2 are in columns A, B, and C respectively ...
In D1, enter the formula =IF(AND(B1<=25,C1<=35),A1,"") and copy it down the column
Use the formula =SUMPRODUCT((D:D<>"")/COUNTIF(D:D,D:D&"")) for your answer
If you want to list the unique values rather than count them, something like this:-
=IFERROR(INDEX(A$2:A$7,MATCH(0,IF((B$2:B$7>25)+(C$2:C$7>35),1,COUNTIF(E$1:E2,A$2:A$7)),0)),"")
entered as an array formula starting in E2 ( and assuming that you are using columns A,B and C for your data.
See this reference for explanation.
The following formula will do what you are asking:
=SUM(IF(FREQUENCY(IF(B2:B7<=25,IF(C2:C7<=35,MATCH(A2:A7,A2:A7,0),""),""),IF(B2:B7<=25,IF(C2:C7<=35,MATCH(A2:A7,A2:A7,0),""),""))>0,1))
This is an array formula so confirm it with Ctrl-Shift-Enter.
I referred to this webpage.
Also found a shorter one:
=SUM(--(FREQUENCY(IF(B2:B7<=25,IF(C2:C7<=35,COUNTIF(A2:A7,"<"&A2:A7),""),""),COUNTIF(A2:A7,"<"&A2:A7))>0))
Found and modified from hre.

Count data if row is true excel

I have this Data:
var number
a 1
a 4
a 30
b 4
b 50
b 6
b 4
ab 1
I need to find the sum of each time a (var occurs X the number next column right) in excel.
In the case above the answer would be:
a = 36
b = 65
How can I write a formula for this in excel? Can I do this in excel?
Since you are counting the last one as well, I would use this formula:
=SUMIF(A:A,"*"&D2&"*",B:B)
Here, there is the value a in cell B2 and I can drag the formula down for B instead of typing a whole new formula. Handy if you have many like those to look for.
I assume that you have the table you published above in cells A1:B8. In order to do the calculating you would like to do you need to use the array-functionality in Excel. The following syntax in a cell will do:
=SUM(IF("a"=A1:A8,B1:B8))
However, instead of ENTER you need to press COMMAND+SHIFT+ENTER (I am on a Mac so it might be that Windows has a slightly different key combo. The result is that the formula now reads like:
{=SUM(IF("a"=A1:A8,B1:B8))}
This will give you 35 and not 36, but in a similar manner you could sum all the columns with 'ab' and then add that up to the sum of the 'a' columns.
Good luck!

Find what cell another cell is referencing

I want to know what column a cell is referring to. Based on the cell it refers to, a different formula will apply.
example:
A B C D E F G
HIGH LOW Choice Gaude
Terry 20 50 50 LOW
Tom 40 1212 1212 LOW
James 101010 121 101010 HIGH
Serra 5 5 HIGH
Sam 50 50 50 LOW
cell E formula
=c2
=c3
=b4
=b5
=b6
cell G formula
=IF(F8=D8,"LOW","HIGH")
The problem is that Sam is meant to be High.
I hope my example helps you understand my predicament.
Are you manually entering the formula in the Choice column E? Maybe it's better to make the Gaude column drive the Choice column instead:
Cell E formula
= If(Exact(G2, "HIGH"), B2, C2)
And instead of changing the referenced column in E, just change G cells to LOW or HIGH as you require.
If I read your quextion correctly, you want a formula that can analyse the formuala contained in another cell, and tell what column it refers to.
You will need a UDF for thism such as
Function WhatColumn(r1 As Range) As Variant
WhatColumn = Range(r1.Formula).Column
End Function
This will return a column number (2 for column B)
You would use this like
=IF(E8=2,"HIGH","LOW")
so if cell E8 contains =B8 WhatColumn will return 2

Return value of last match

I need a formula to return the value of Data for the last match of "Text". Row number is also acceptable. Macro is NOT acceptable. Name column is unsorted and cannot be sorted!
Only column "Name" is used as lookup value. I would rather use a/multiple helper column(s) instead of an array formula.
Row Name Data
1 Joe 10
2 Tom 20
3 Eva 30
4 Adam 40
5 Tom 21
LARGE only works with numbers, and VLOOKUP only returns the first match. LOOKUP only works sometimes, so its out too.
So if I wanted the last match for "Tom" then it should return "21".
Array formulas could be avoided with a helper column.
Suppose to have in F1 the name to match (i.e. Tom)
In the helper column row C2 enter
=IF(A2<>$F$1,0,row())
Then copy the formulas along your data.
Now the column C contains 0 for the unmatched names and the row number for the matched ones. Maxing the column yield the row of the solution.
Now the result is simple a matter of using the correct offset with the function offset:
=OFFSET(B1,max(C:C)-1,0)
PS: my copy of excel is in italian, so I can't test this english translaction of the formulas.
I think it's the easiest way to make it.
=LOOKUP("Tom";A2:B7)
Create a column with an array formula (enter it with Ctrl+Shift+Enter):
=VLOOKUP(MAX(IF($B$2:$B$6=B2, $A$2:A$6, 0)), $A$2:$C$6, 3, FALSE)
To make sure you did it right, click on the cell, and the formula should be shown encased in curly brackets ({}).
Note: This assumes that "Row" is in A1.
I have come up with a solution, but it requires that numbers in Data are concurrent, like so
Name Data
Joe 1
Tom 1
Eva 1
Adam 1
Tom 2
Tom 3
Eva 2
But thats okay, since that my data looks like that anyway. So if Name is used before then it must be the old highest +1 aka concurrent.
Name is A1 and Data is B1, and this formula goes into C2:
FLOOR(SQRT(2*SUMIF(A2:A7,A2,B2:B7)),1)

Resources