Hi All I have been trying to use the formula below and to alter it for multiple conditions
{=INDEX($C$1:$C$51,SMALL(IF($A$1:$A$51="Adeline",ROW($A$1:$A$51),""),3),1)}
I have a table on sheet1 called Data and a page for calculations. There is a matching ID on both sheets though in the table on sheet1 an ID could be on multiple rows. Also the CODE column could contain in this case TEST2 multiple times for same ID but with different Values. I am trying to in this case find the 3rd value for this combination.
So I trying to find out a value based on ID and a column called Code but I would like the 3rd value
So I've tried altering the IF part of the statement
{=INDEX(Data[Value],SMALL(IF((Data[ID] =[#ID])*(Data[CODE] = "Test2") ,ROW($A$1:$A$51),""),3),1)}
and
{=INDEX(Data[Value],SMALL(IF((AND(Data[ID]=[#ID], Data[CODE] = "Test2") ,ROW($A$1:$A$51),""),3),1)}
Both Come up with errors - any advice or am I looking at this completely in the wrong way.
Sample Data
Calcs sheet
EDIT Change from Largest being the highest rank to Smallest being the highest rank
=IFERROR(AGGREGATE(15,6,1/(1/((Data[[ID]:[ID]]=Results[#[ID]:[ID]])*(Data[[Code]:[Code]]="Test 2")))*Data[[Value]:[Value]],COLUMNS($A:A)),"")
Notes:
We use multiplication of Booleans instead of an IF function
the 1/(1/(...)) formula part is a method of turning FALSE results from the Boolean multiplaction from 0 into a #DIV/0! error.
The AGGREGATE function provides a method of excluding the error results from the calculation.
Structured references have been changed to absolute references to allow dragging without changing the column names
The COLUMNS(... function will adjust to return {1,2,3] as you fill right to return the smallest; 2nd smallest, etc value
Note that with an absolute reference, the table name must be used even if the line is in the same table.
Related
My question is that I want to return a list of values in column B in sheet 2 (or in this case NBA Players) that contain the value "PG" in cell A3 in sheet 1, from column A in sheet 2. Not only do I want it to match "PG" but I also want the value to have a salary (Column C) that is between $7100 (Cell B2 in Sheet 1) and $8000 (Cell C2) in Sheet 1). Any help would be appreciated.
you are either going to need to use an array formula or a function that returns array like calculations. I will suggest using the AGGREGATE function. Avoid using full comm/row references within an array formula or a function performing array like calculations or you may wind up bogging down your system with excessive calculations.
The AGGREGATE function is made up a several individual functions. Depending which one you choose, it will perform array operations. I am going to suggest that formula 14. What the following example will do is generate a list of results sorted from smallest to largest that ignores error values, then return the first value from the list. The thing we will list is the row number for a row that matches your ALL your criteria. So the basics of AGGREGATE looks like this:
AGGREGATE(Formula #, Error/hidden handling #, Formula, parameter)
The hardest part of this is coming up with the right formula. In the numerator you put the thing you are looking for. In the denominator you place your TRUE/FALSE condition checks. Separate each condition check with *. * will act as an AND function. The thing that makes this work is that TRUE/FALSE convert to 1/0 when they are sent through a math operation. So anything you do not want is FALSE. and anything divided by FALSE becomes divide by 0 which in turn generates an error. Since AGGREGATE is set to ignore error, only things that meet your condition will exist in the list and since they are being divided by TRUE which is 1, your thing remains unchanged. So the aggregate function is going to start to look like:
AGGREGATE(14,6,ROW(some range)/((Condition 1)*Condition 2)*...*(Condition N)),1)
So as eluded to before, 14 set the AGGREGATE to sort a list in ascending order. 6 tells AGGREGATE to ignore errors, and the 1 tells AGGREGATE to return the first item in its sorted list. If it was 2 instead of 1 it would return the 2nd position. If you ask for a position that is greater than the number of items in the list, there will be an error produced by AGGREGATE which does not get ignored.
So now that there is some understanding of what AGGREGATE does lets see how we can apply this to your data. For starters lets assume your data is in rows 2:100 and row 1 is a header row. You will have to adjust the references to suit your data.
CONDITION 1
LEFT($A$2:$A$100,2)="PG"
Checks to see if the first two characters are PG. based on the data in your screen shot, PG was either to the left of the / or was the only entry. There was also an observation that there was only one / in the cells of column A. If you also need to check if it after the / and with the assumption that it can only be on one side and not both at the same time you could use this alternative for your condition check:
(LEFT($A$2:$A$100,2)="PG")+(RIGHT($A$2:$A$100,2)="PG")
In this case the + is performing the task of an OR function. The caveat mentioned earlier is important because if both sides are TRUE then you wind up with TRUE+TRUE which becomes 1+1 which is 2 and we only want to divide by 1 or 0. Though to counter that you could go with:
MIN((LEFT($A$2:$A$100,2)="PG")+(RIGHT($A$2:$A$100,2)="PG"),1)
CONDITION 2
Check that the salary in C is less than or equal a value 80000.
($C$2:$C$100<=80000)
CONDITION 3
Check that the salary in C is greater than or equal a value 71000.
($C$2:$C$100>=71000)
Now lets put this all together to get a list of row numbers that meet your conditions:
AGGREGATE(14,6,ROW($A$2:$A$100)/MIN((LEFT($A$2:$A$100,2)="PG")+(RIGHT($A$2:$A$100,2)="PG"),1)*($C$2:$C$100<=80000)*($C$2:$C$100>=71000),ROW(A1))
Now provided I did not screw up the bracketing in that formula, you can place that formula in a cell and copy it down until it produces errors. As you copy it down, the only thing that will change is the A1 in ROW(A1). It acts like a counter. 1,2,3 etc. so you will get a list of row numbers that meet your criteria. Now we need to convert those row numbers to names.
To find the names, the INDEX function is your friend here. Because it is not part of an array formula or inside a function performing array like calculations, full column reference can be used. So we take our formula that is generating row numbers and place it inside the INDEX function to give:
INDEX(B:B,Row Number)
INDEX(B:B,AGGREGATE(14,6,ROW($A$2:$A$100)/MIN((LEFT($A$2:$A$100,2)="PG")+(RIGHT($A$2:$A$100,2)="PG"),1)*($C$2:$C$100<=80000)*($C$2:$C$100>=71000),ROW(A1)))
Now if you hate seeing error codes when you have copied down further then results you can place the whole thing inside and IFERROR function to give:
IFERROR(formula,What to display in case of an error)
So for blank entries:
IFERROR(INDEX(B:B,AGGREGATE(14,6,ROW($A$2:$A$100)/MIN((LEFT($A$2:$A$100,2)="PG")+(RIGHT($A$2:$A$100,2)="PG"),1)*($C$2:$C$100<=80000)*($C$2:$C$100>=71000),ROW(A1))),"")
and custom message:
IFERROR(INDEX(B:B,AGGREGATE(14,6,ROW($A$2:$A$100)/MIN((LEFT($A$2:$A$100,2)="PG")+(RIGHT($A$2:$A$100,2)="PG"),1)*($C$2:$C$100<=80000)*($C$2:$C$100>=71000),ROW(A1))),"NOT FOUND")
So now you just need to adjust the references to suit your data. If your data is located on another sheet remember to include the sheet name. A reference to B3:C4 would become:
Sheet1!B3:C4
and if the sheet name has a space in it:
'Space Name'!B3:C4
The situation
In the sheet "Planning" I have an area that contains pairs of sessions (strings) and hours (numbers) in adjacent cells (e.g. D11 and E11, I12 and J12 etc.) One session can occur multiple times.
D11:E11 is | Foo | 8 |
I12:J12 is | Foo | 4 |
In another sheet, I want to find a session in the Planning sheet and return an array with all the hours booked on that session (to calculate a total)
I use an array formula with a conditional and intend to use the SMALL function to retrieve the results from the array
The problem
The following formula returns all the correct references to hours booked on "Foo", so far so good.
=IF(Planning!$D$11:$CV$18="Foo";ADDRESS(ROW(Planning!$D$11:$CV$18);COLUMN(Planning!$D$11:$CV$18)+1;;;"Planning"))
{"Planning!$E$11"\FALSE\FALSE\FALSE\FALSE\"Planning!$J$12"}
However, if I use the INDIRECT function to retrieve the values of those references, they always return the value of the first reference in the array ("Planning!$E$11")
=IF(Planning!$D$11:$CV$18="Foo";INDIRECT(ADDRESS(ROW(Planning!$D$11:$CV$18);COLUMN(Planning!$D$11:$CV$18)+1;;;"Planning")))
{8\FALSE\FALSE\FALSE\FALSE\8}
How do I retrieve the correct values? Or should I tackle the problem in a whole different way?
Screenshots
The planning sheet
The overview I want
Since I was mainly interested in the total of planned hours, I eventually used the following formula:
=SUM(SUM(INDIRECT(IF(Planning!$D$11:$CV$18="Foo";(ADDRESS(ROW(Planning!$D$11:$CV$18);COLUMN(Planning!$D$11:$CV$18)+1;;;"Planning"));"$U$19"))))
IF: Create the array with references to the Planning sheet if the string is found. If it's not found, add the reference $U$19.
Using INDIRECT, replace all references with the values in the Planning sheet. $U$19 contains the value 0.
Then use SUM twice to sum up all the values. I don't know why, but see
Is it possible to have array as an argument to INDIRECT(), so INDIRECT() returns array?
https://superuser.com/questions/1196243/simplify-a-sum-of-indirect-cell-values
Indirect doest work in most array formulas. If you give it a string that refers to an array, like "A1:A10" it it returns those cells as expected but thats about it. You can use that array as the input to another function but you cant send an array output from another function to INDIRECT(). (Or at least i have not figured out a way)
Try using the INDEX function with the ROW function.
INDIRECT("A1:A10") is similar to
INDEX(A:A,ROW(A1:A10))
However the former is less flexible.
Comsider:
INDEX(A:A,FILTER(ROW(A1:A10),NOT(ISBLANK(A1:A10))*ISNUMBER(A1:A10)))
This returns an array containing the numerical values in the range but does not treat an empty cell as zero. Watch your order of operations and parenthesis.
The product NOT(ISBLANK(A1:A10)*ISNUMBER(A1:A10) is the inner product of two vectors of boolean values.
ROW(A1:A10) creates a vector of row values of the of the elements in that range. Then filter throws out any where the corespinsing element of the boolean vector is 0. Index then returns an array of values of the cells in its range coresponding to those rows. The range given to INDEX could be any row in fact. Not just the one your selecting on. Using the entire column (for example A:A) allows excel to automatically update the references if you move the source data, for instance if you insert a header row. If you use a specific range you will need to add an offset to the row value and it will not automatically update refernces. (Without a far more complex formula)
I have an Excel file with 2 sheets - one sheet contains my items, prices, codes, etc. and the other sheet is for cross-matching with competitors.
I've included an Excel file and image below.
I want to be able to generate my code automatically when manually entering any of my competitor's codes. I was able to do INDEX/MATCH but I was only able to match with one column (I'm assuming they're all in one sheet to make it easier). Here is my formula:
=INDEX(C:C,MATCH(K2,E:E,0)
So this is looking only in E:E, when I tried to enter a different column such as C:C or D:D it returns an error.
I tried to do the MATCH as C:G but it gave an error right away.
The reason why match gave you error is because it's looking for an array and you put in multiple columns.
There is definitely a more elegant way to do this but this is the first one that I came up with.
=IFERROR(INDEX(B:B,MATCH(K2,C:C,0)),IFERROR(INDEX(B:B,MATCH(K2,D:D,0)),IFERROR(INDEX(B:B,MATCH(K2,E:E,0)),IFERROR(INDEX(B:B,MATCH(K2,F:F,0)),IFERROR(INDEX(B:B,MATCH(K2,G:G,0)),"")))))
Index/Match Combination
Please try this formula:
{=INDEX($B$2:$B$5,MATCH(1,(K2=$C$2:$C$5)+(K2=$D$2:$D$5)+(K2=$E$2:$E$5)+(K2=$F$2:$F$5)+(K2=$G$2:$G$5),0))}
Instruction: Paste the formula {without the curly brackets} to the formula bar and hit CTRL+SHIFT+ENTER while the cell is still active. This will create an array formula. Hence, the curly brackets. Please take note though that manually entering the curly brackets will not work.
Description:
The INDEX function returns a value or the reference to a value from within a table or range.1
The MATCH function searches for a specified item in a range of cells, and then returns the relative position of that item in the range.2
Syntax:
The INDEX function has two forms—Array and Reference form. We're going use the Reference form in this case.
INDEX(reference, row_num, [column_num], [area_num])1
MATCH(lookup_value, lookup_array, [match_type])2
Explanation:
To simplify, we're going to use this form:
INDEX(reference, MATCH(lookup_value, lookup_array, [match_type]))
The INDEX function returns a value from the reference My code column (B1:B5) based on the row_num argument, which serves as an index number to point to the right cell, and we're going to do that by substituting row_num with MATCH function.
MATCH function, on the other hand, returns the relative position of a value in competitorn column that matches the value in individual cells of the competitor code column.
To make it work with multiple lookup range, we're going to create arrays of boolean values (TRUE/FALSE, aka logical values) by comparing values from individual cells in competitor code column with values in individual competitorn columns. Now, we convert these boolean values into numerical values by performing a mathematical operation that does not alter its implied value (i.e. TRUE=1, FALSE=0). We're going to add these values directly to make it simple. The resulting array have four index with two possible values: 1 or 0. Since each item in MATCH's lookup_array is unique, then there can be only one TRUE or 1. The rest are FALSE or 0's. So, with that knowledge, we're going to use it as our lookup_value.
Let's dissect the formula:
=INDEX(B2:B5,MATCH(1,(K2=C2:C5)+(K2=D2:D5)+(K2=E2:E5)+(K2=F2:F5)+(K2=G2:G5),0))
My code 2 = INDEX({"My code 1";"My code 2";"My code 3";"My code 4"},MATCH)
My code 2 = INDEX({"My code 1";"My code 2";"My code 3";"My code 4"},(2))
2 = MATCH(1,(K2=C2:C5)+(K2=D2:D5)+(K2=E2:E5)+(K2=F2:F5)+(K2=G2:G5),0)
2 =MATCH(1,
{FALSE;FALSE;FALSE;FALSE}+
{FALSE;FALSE;FALSE;FALSE}+
{FALSE;FALSE;FALSE;FALSE}+
{FALSE;FALSE;FALSE;FALSE}+
{FALSE;TRUE;FALSE;FALSE},0))
OR
=MATCH(1,
{0;0;0;0}+
{0;0;0;0}+
{0;0;0;0}+
{0;0;0;0}+
{0;1;0;0},0))
=========
{0;1;0;0},0))
2 = MATCH(1,{0;1;0;0},0))
I hope this answer is helpful.
References and links:
INDEX function
MATCH function
Create an array formula
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 am trying to create a simple VLOOKUP function for my spreadsheet using the below:
In the first sheet
=VLOOKUP("Salary",'December 2015_natwest_download'!$D$4:$E$43,1,FALSE)
This is the sheet i am trying to reference:
The sheet I am trying reference:
Value Category
======= ==========
£530.00 Charlotte Owing
-£53.00 Gym
-£16.47 Water
-£67.00 Phone
-£11.01 Presents
-£14.40 Eating out
-£100.00 Food
-£65.00 Other
But when I put the VLOOKUP code into my excel, it returns NA. Can anyone see what is causing the error?
The VLOOKUP function is designed to lookup a value on the far left of a block of data and return a corresponding value from a column to the right.
If you need to lookup a value and return a value from a corresponding column to the left of the lookup column, you need to use an INDEX/MATCH function pair.
If you are returning numbers based on a condition (either in that column or another column) either the SUMIF or
SUMIFS function will do. Individual entries can be easily collected but if there is more than a single match to your condition, you will receive a sum total of the matching numbers.
The formulas in E4:F4 are,
=INDEX('December 2015_natwest_download'!A:A, MATCH(D4, 'December 2015_natwest_download'!B:B, 0))
=SUMIFS('December 2015_natwest_download'!A:A,'December 2015_natwest_download'!B:B, D4)
Note that the SUMIFS in F5 is returning two Gym entries.