I've seen many questions on here relating to this topic but most seem to stop after 2 scenarios.
I'm trying to write a formula to say something like this:
IF this value is between these two values, output A. If the same value is between these other two values, output B. If the same value is between yet a further two values, output C and if the same value is between a last two further values, output D.
Here's what I have so far:
=IF(AND(Sheet1!C2>'Control Sheet'!B2,Sheet1!C2<'Control Sheet'!C2),"A",IF(OR(Sheet1!C2>'Control Sheet'!B3,Sheet1!C2<'Control Sheet'!C3),"B",IF(OR(Sheet1!C2>'Control Sheet'!B4,Sheet1!C2<'Control Sheet'!C4),"C",IF(OR(Sheet1!C2>'Control Sheet'!B5,Sheet1!C2<'Control Sheet'!C5),"D",""))))
But it only outputs "A" or "B" and stays on "B" if the value should be "C" or "D".. if that makes sense.
Is this possible in Excel? If so, what have I done wrong?
Thanks :)
Yes, this is totally possible in excel. There's a slight mistake in your equation.
Look at this part of your equation:
IF(OR(Sheet1!C2>'Control Sheet'!B3,Sheet1!C2<'Control Sheet'!C3),"B",...
If the value is > the min value for B OR the value is < the max value for B then it outputs "B". So if the value doesn't fall within the range for A, then it will always meet these conditions for B.
The fix is to change the ORs to ANDs. The value must be > the min value AND < the max value.
=IF(AND(Sheet1!C2>'Control Sheet'!B2,Sheet1!C2<'Control Sheet'!C2),"A",IF(AND(Sheet1!C2>'Control Sheet'!B3,Sheet1!C2<'Control Sheet'!C3),"B",IF(AND(Sheet1!C2>'Control Sheet'!B4,Sheet1!C2<'Control Sheet'!C4),"C",IF(AND(Sheet1!C2>'Control Sheet'!B5,Sheet1!C2<'Control Sheet'!C5),"D",""))))
Related
I have a table on Excel with data as the following:
Meaning, I have different JPH based on the %SMALL unit and the number of active stations.
I need to create a matrix like the following (with %SMALL on horizontal and STATIONS on vertical axes):
And the formula for each cell should:
Take the input of Stations (column "B")
Check, for that specific Stations number, the amount of data on the other table (like make a filter on STATIONS for the specific number)
Perform an VLOOKUP for checking the JPH based on the %SMALL value on row 2
Interpolate for the exact JPH value, if not found on table
For now, I was able to create the last part (the VLOOKUP and the interpolation), with the following:
=IFERROR(VLOOKUP(C2;'EARLY-STATIONS'!$F:$H;3;FALSE);AVERAGE(OFFSET(INDEX('EARLY-STATIONS'!$H:$H;MATCH(C2;'EARLY-STATIONS'!$F:$F;1));0;0;2;1)))
The problem I'm facing is than with this, the calculation is not checking the number of stations, so the Iteration is not accurate.
Unfortunately I cannot use VBA macros to solve this.
Any clue?
This is an attempt because more clarity is needed in terms of all possible scenarios to consider, based on different input data and how to understand the "extrapolation" process. This approach understands as extrapolation the average of two values (lower and greater), but the idea can be customized to any other way to calculate it. Per tags listed in the question I assume there is no Excel version constraint. This is O365 solution:
=LET(sm, A2:A10, st, B2:B10, jph, C2:C10, smx, F1:J1, sty, E2:E4, NULL, "",
GETLk, LAMBDA(x,y,mode, FILTER(jph, (st=y)
* (sm = INDEX(sm, XMATCH(x, sm, mode))), NULL)),
GET, LAMBDA(x,y, LET(f, FILTER(jph, (jph=GETLk(x,y, 1))
+ (jph=GETLk(x,y, -1)), NULL), IF(#f=NULL, NULL, AVERAGE(f)))),
HREDUCE, LAMBDA(yi, DROP(REDUCE("", smx, LAMBDA(ac,x,
HSTACK(ac, GET(x, yi)))),,1)),
DROP(REDUCE("", sty, LAMBDA(ac,y, VSTACK(ac, HREDUCE(y)))),1))
The above formula spills the entire result, I don't think for this case you can use a LOOKUP-like function.
Here is the output:
The highlighted cells where the average is calculated.
Explanation
The main idea is to use DROP/REDUCE/HSTACK/VSTACK pattern to generate the grid. Check my answer to the following question: how to transform a table in Excel from vertical to horizontal but with different length on how to apply it.
We use two user LAMBDA functions to abstract some calculations:
GETLk(x,y,mode), filters jph name based on %SMALL and Stations columns values, based on input values x (x-axis value from the grid), y (y-axis value form the grid) respectively. The third input argument mode, is for doing the approximate search in XMATCH (1-next largest, -1 next smallest). In case the value exist in the input table, XMATCH returns the same value in both cases.
GET(x,y) has the logic to find the value or if the value doesn't exist to calculate the average. It uses the previous LAMBDA function GETLk. We filter for jph values that match the input values (x,y), but we use an OR condition in the FILTER (+), to select both lower or greater values. If the value exist, returns just one value otherwise two values are returned by FILTER (f). Finally if f is not empty we return the average, otherwise the value we setup as NULL.
HREDUCE: Concatenate the result by columns for a given row of the grid. Check the referred question for more information about it.
I have 2 columns, B(freq) and C(AvgValue), I want to find the corresponding freq(column B) for the largest AvgValue(column C) in the first 300 cells.
I used match method as D1=MATCH(MAX(C1:C300),C1:C300,0) and returns the row of the largest AvgValue, the value is 260. Now I can use E1=B260 to find the freq, but failed to use E1=B(D1). I also searched methods like =indirect() but not succeeded. Thank you!
0.101393946 8.75E-01
0.102807322 8.75E-01
0.104240401 8.76E-01
0.105693455 8.77E-01
0.107166765 8.79E-01
0.108660611 8.80E-01
0.110175281 8.81E-01
0.111711065 8.79E-01
...
If you have the input data in the range: A1:B10, then you can get the result combining INDEX and XMATCH as follow:
=INDEX(B1:B10, XMATCH(MAX(A1:A10), A1:A10))
Note: If the column A has more than one value with max value then you may want to concatenate the frequency values that correspond to max value as follow: =TEXTJOIN(",", ,FILTER(B1:B10, A1:A10=MAX(A1:A10))). Otherwise the previous approach (INDEX/XMATCH) returns the frequency of the first maximum value found.
This question relates to the Schematiq add-in for Microsoft Excel.
Using =tbl.Lookup(table, columnsToSearch, valuesToFind, resultColumn, [defaultValue]) the values in the valuesToFind column have a consistent 3 characters to the left and then varying characters after (e.g. 908-123456 or 908-321654 - i.e. 908 is always consistent)
How can I tell the function to lookup the value based on the first 3 characters only? The expected answer should be the sum of the results of the above, i.e. 500 + 300 = 800
tbl.Lookup() works by looking for an exact match - this helps ensure it's fast but in this case it means you need an extra step to calculate a column of lookup values, something like this:
A2: =tbl.CalculateColumn(A1, "code", "x => LEFT(x, 3)", "startOfCode")
This will give you a new column that you can use for the columnsToSearch argument, however tbl.Lookup() also looks for just one match - it doesn't know how to combine values together if there is more than one matching row in the table, so I think you also need one more step to group your table by the first 3 chars of the code, like this:
A3: =tbl.Group(A2, "startOfCode", "amount")
Because tbl.Group() adds values together by default, this will give you a table with a row for each distinct value of startOfCode and the subtotal of amount for each of those values. Finally, you can do the lookup exactly as you requested, which for your input table will return 800:
A4: =tbl.Lookup(A3, "startOfCode", "908", "amount")
Assume I have an input variable x and three parameters a,b,c such that:
Given b we have c = f(x,a,b) for some (known) function f
Given c we have b = g(x,a,c) for some (known, different) function g.
I want to model this in a spreadsheet (Excel for instance). More precisely, if the user provides x,a and b then c will be evaluated and if c is given then b will be evaluated. It seems like this cannot be achieved directly, since a cell can hold either a value or a formula.
Is there a canonical way to do this? If not, what would be a best-practice workaround (probably some VBA magic)?
You can separate input fields from the calculated values and add some validation that only one of the mutually exclusive field is used, e.g.:
in my example, I used following conditional formatting to highlight invalid input:
=AND($B$4<>"", $B$5<>"")
and I used following the formulas for calculated values:
=B2
=B3
=IF(AND($B$4<>"", $B$5<>""), "#ERROR: only 1 value can be specified",
IF($B$4<>"", $B$4, $B$5-1))
=IF(AND($B$4<>"", $B$5<>""), "#ERROR: only 1 value can be specified",
IF($B$5<>"", $B$5, $B$4+1))
more generally:
=if(error_condition, error_message, if(b_is_not_empty, b, g(x,a,c)))
I need to be able to search my whole table for a row that matches multiple criteria. We use a program that outputs data in the form of a .csv file. It has rows that separate sets of data, each of these headers don't have any columns that are unique in of them self but if i searched the table for multiple values i should be able to pinpoint each header row. I know i can use Application.WorksheetFunction.Match to return a row on a single criteria but i need to search on two three or four criteria.
In pseudo-code it would be something like this:
Return row number were column A = bill & column B = Woods & column C = some other data
We need to work with arrays:
There are 2 kinds of arrays:
numeric {1,0,1,1,1,0,0,1}
boolean {TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE}
to convert between them we can use:
MATCH function
MATCH(1,{1,0,1,1,1,0,0,1},0) -> will result {TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE}
simple multiplication
{TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE}*{TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE} -> will result {1,0,1,1,1,0,0,1}
you can can check an array in the match function, entering it like in the picture below, be warned that MATCH function WILL TREAT AN ARRAY AS AN "OR" FUNCTION (one match will result in true
ie:
MATCH(1,{1,0,1,1,1,0,0,1},0)=TRUE
, YOU MUST CTR+SHIFT+ENTER !!! FOR IT TO GIVE AN ARRAY BACK!!!
in the example below i show that i want to sum the hours of all the employees except the admin per case
we have 2 options, the long simple way, the complicated fast way:
long simple way
D2=SUMPRODUCT(C2:C9,(A2=A2:A9)*("admin"<>B2:B9)) <<- SUMPRODUCT makes a multiplication
basically A1={2,3,11,3,2,4,5,6}*{0,1,1,0,0,0,0,0} (IT MUST BE A NUMERIC ARRAY TO THE RIGHT IN SUMPRODUCT!!!)
ie: A1=2*0+3*1+11*1+3*0+2*0+4*0+5*0+6*0
this causes a problem because if you drag the cell to autocomplete the rest of the cells, it will edit the lower and higher values of
ie: D9=SUMPRODUCT(C9:C16,(A9=A9:A16)*("admin"<>B9:B16)), which is out of bounds
same as the above if you have a table and want to view the results in a diferent order
the fast complicated way
D3=SUMPRODUCT(INDIRECT("c2:c9"),(A3=INDIRECT("a2:a9"))*("admin"<>INDIRECT("b2:b9")))
it's the same, except that INDIRECT was used on the cells that we want not be modified when autocompleting or table reorderings
be warned that INDIRECT sometimes give VOLATILE ERROR,i recommend not using it on a single cell or using it only once in an array
f* c* i cant post pictures :(
table is:
case emplyee hours totalHoursPerCaseWithoutAdmin
1 admin 2 14
1 him 3 14
1 her 11 14
2 him 3 5
2 her 2 5
3 you 4 10
3 admin 5 10
3 her 6 10
and for the functions to check the arrays, open the insert function button (it looks like and fx) then doubleclick MATCH and then if you enter inside the Lookup_array a value like
A2=A2:A9 for our example it will give {TRUE,TRUE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE} that is because only the first 3 lines are from case=1
Something like this?
Assuming that you data in in A1:C20
I am looking for "Bill" in A, "Woods" in B and "some other data" in C
Change as applicable
=IF(INDEX(A1:A20,MATCH("Bill",A1:A20,0),1)="Bill",IF(INDEX(B1:B20,MATCH("Woods",B1:B20,0),1)="Woods",IF(INDEX(C1:C20,MATCH("some other data",C1:C20,0),1)="some other data",MATCH("Bill",A1:A20,0),"Not Found")))
SNAPSHOT
I would use this array* formula (for three criteria):
=MATCH(1,((Range1=Criterion1)*(Range2=Criterion2)*(Range3=Criterion3)),0)
*commit with Ctrl+Shift+Enter