Incorrect result for nested condition in MEDIAN-IF excel - excel

I have a following excel spreadsheet which consist of following fields:
Col A: Timestamp
Col B: Numerical result
Col C: Time duration taken for calculation of result
Now, I'm trying to find the median value of col C (Duration) for various month and year combinations.
e.g. For the month of march in 2019, what's the median value of duration?
I could've used the MEDIANIFS, but sadly it didn't exists. I'm trying the below thing also, but it's not giving the correct result(G1 is a drop-down which consists numerical valued years i.e. 2019, 2020 and so on)
MEDIAN(IF(YEAR(A3:A100) = G1, IF(MONTH(A3:A100) = 3, C3:C100)))
I also tried ANDing the conditions but it also didn't worked:
MEDIAN(IF((YEAR(A3:A100) = G1) * (MONTH(A3:A100) = 3), C3:C100))
If I put one condition inside the Median(If()), it's working fine. But, whenever I nest or concat conditions, it's not giving the correct result.
Any help/pointers will be highly appreciated.

Related

How to fix the #SPILL! Error by displaying only the second value?

I have a column with some info displayed like that:
Product Info
I am the 3rd product from 2020
I was created in 1995 and I went public in 2021
I am a not sure if I'm from 2019 2020 2021
I have a formula to extract the year in the above column that is:
=IFERROR(FILTERXML("<k><m>"&SUBSTITUTE([#[Product Name]]," ","</m><m>")&"</m></k>","//m[.=number() and string-length()=4]"),"")
The problem with this formula is that it works fine with the first case, but it gives me a #SPILL! Error on the other two cases. My ideal output would be:
Product Info
Year
I am the 3rd product from 2020
2020
I was created in 1995 and I went public in 2021
2021
I am a not sure if I'm from 2019 2020 2021
Basically, for the first case, just return the 4 digits. EVERY time that I only have one sequence of 4 digits, I want to return that sequence.
For the second case, I want to return ONLY the second year. EVERY time I have 2 sequences of 4 digits, I want to return ONLY the second year.
For the third case, I want to return nothing. EVERY time I have more than 2 sequences of 4 digits, I want to return blank.
The last thing I tried to add was position()>5 and that would cut off the 1995 in the second example, but I would continue having the Error on the third example. Also, my list is quite huge, and I am not sure if the position()>5 thing would work for ALL products that fall in the same second example.
I am not very good with XPATH, so any help would be greatly appreciated.
Thank you!
Disclaimer: Below solution is written on the assumption that when 'count of years < 3', return the last given year. If 'count >= 3' then only return the last year if years come in pairs of two. Hence the use of 'modulus 2 == 0'.‡
You can expand the xpath for sure if you so desire. However, I'd rewrite it a little bit. Each predicate, the structure between the opening and closing square brackets, is a filter of a given nodelist. To write multiple of these structures is in fact anding such predicates. To get a better understanding of what most common xpath 1.0 functions can do within FILTERXML(), I'd like to redirect you to this post.
So to write a consecutive pattern of predicates I'd opt for:
[.*0=0] - First return a filtered nodelist of all numbers where a node multiplied by zero equals zero;
[string-length()=4] - Then return only those that are 4 characters long‡‡;
[position() = last() and (position() = 1 or position() mod 2 = 0)] - The 3rd and last predicate is the trickiest for your query. This is done with a first check that position() = last() meaning the node needs to be the last node in the filtered nodelist of step 2 and (position() = 1 or position() mod 2 = 0) means we want to check that this node is also at the 1st index or the modulus 2 of the indexed position equals 0‡‡‡.
Formula in B2:
=IFERROR(FILTERXML("<t><s>"&SUBSTITUTE(A2," ","</s><s>")&"</s></t>","//s[.*0=0][string-length()=4][position() = last() and (position() = 1 or position() mod 2 = 0)]"),"")
Whilst the above would work for Excel 2013 and higher‡‡‡‡, you do talk about spilled behaviour. If you happen to work with the current channel in ms365 you could also try:
=LET(x,TEXTSPLIT(A2," "),y,--FILTER(x,ISNUMBER(-(x&"**0"))*(LEN(x)=4),{1,2,3}),z,COUNT(y),IF(OR(z=1,MOD(z,2)=0),TAKE(y,,-1),""))
‡ If you need to simply return the last year if 'count < 3' then you can use xpath "//s[.*0=0][string-length()=4][position()<3 and position() = last()]" or ms365 formula =LET(x,TEXTSPLIT(A2," "),y,FILTER(x,ISNUMBER(-(x&"**0"))*(LEN(x)=4),""),IF(COUNTA(y)>2,"",TAKE(y,,-1))).
‡‡ Note that you can be more strict about this if you'd wish to validate that a year is between say 1900-2050 or so. One could replace the 1st and 2nd predicate with [.*1>1899][.*1<2051].
‡‡‡ Note that the order or writing your and/or statements in xpath do matter. We need to use explicit parentheses to control the precedence. See this
‡‡‡‡ This is not true for Excel Online or Excel for Mac
Just add a simple clause to determine the number of returns, for example using ROWS (since by default FILTERXML returns a vertical array):
=LET(
ζ, FILTERXML(
"<k><m>" &
SUBSTITUTE(
[#[Product Name]],
" ",
"</m><m>"
) & "</m></k>",
"//m[.=number() and string-length()=4]"
),
ξ, ROWS(ζ),
IF(ξ > 2, "", INDEX(ζ, ξ))
)
Edit: I might prefer to avoid FILTERXML here:
=LET(
ζ, TEXTSPLIT([#[Product Name]], " "),
ξ, -(ζ & "**0"),
IF(COUNT(ξ) > 2, "", IFERROR(-LOOKUP(1, FILTER(ξ, LEN(ζ) = 4)), ""))
)
You can try the following using TEXTAFTER function. Assuming you have years at the end delimited by space. If that is not the case, the formula can be adapted to have additional checks (it is a number and four-digit, but strictly speaking a year can have less or more than 4 digits). Let me know if the previous assumption doesn't apply so I can try to adapt it. The following is an array version, so you can use the entire table column in case you are using excel tables:
=LET(in,A2:A4,last,TEXTAFTER(in," ",-1),
IF(ISNUMBER(1*TEXTAFTER(SUBSTITUTE(in," "&last,"")," ",-1)),"",last))
For the case of more than one year, it removes the last year found, and if the second search is a number, then it returns empty, otherwise returns the previous year found.

How to define an array of numbers with a formula

I have a project where I need to break people into 3 buckets with task lists that rotate quarterly (Phase A = task list 1, B = task list 2, C = task list 3). The goal here is to sort people into the buckets based on a departure date, with the ideal being that they would depart when they're in the C phase. I have a formula already set up that will tell me the number of quarters between the project start date and the person's departure date, so now I'm trying to figure out how to get Excel to tell me if a person's departure date falls within their bucket's C Phase.
I have this formula in a column called DEROSQtr:=ROUNDDOWN(DAYS360("1-Oct-2020",[#DEROS],FALSE)/90,0)
Now the easy way to approach this would be to build a static array and just see if that formula results in a value in the right array, where the numbers in the array define which quarter from Oct 2020 that the bucket's C Phase is going to be in:
ArrayA = {1;4;7;10;13;16} ArrayB = {2;5;8;11;14;17} ArrayC = {0;3;6;9;12;15}
The formula that pulls this all together is then:
=IF([#EFP]="A",IF(IFNA(MATCH([#DEROSQtr],ArrayA,0),-1)<>-1,TRUE,FALSE),IF([#EFP]="B",IF(IFNA(MATCH([#DEROSQtr],ArrayB,0),-1)<>-1,TRUE,FALSE),IF([#EFP]="C",IF(IFNA(MATCH([#DEROSQtr],ArrayC,0),-1)<>-1,TRUE,FALSE),"-")))
Now while this will work for as long as I build out the static array, I'm trying to figure out how to define each of these buckets with a formula that Excel can work with, i.e. bucket A hits phase C in 3n + 1 quarters where n is the number of cycles through all 3 phases, so ArrayA = 3n+1, ArrayB = 3n+2 and ArrayC = 3n. What I'm hunting for here is the best way to define each of the arrays as a formula.
After some additional digging and looking back at how to define each array, I came across the MOD() function in Excel. I was then able to rewrite the formula that does the checking as =IF([#EFP]="A",IF(MOD([#DEROSQtr]-1,3)=0,TRUE,FALSE),IF([#EFP]="B",IF(MOD([#DEROSQtr]-2,3)=0,TRUE,FALSE),IF([#EFP]="C",IF(MOD([#DEROSQtr],3)=0,TRUE,FALSE),"-"))), replacing ArrayA(3n+1) with MOD([#DEROSQtr]-1,3), ArrayB(3n+2) with MOD([#DEROSQtr]-2,3), and ArrayC(3n) with MOD([#DEROSQtr],3).
Since I do not have the data you are calculating your quarter, its difficult to give you exact answer. However, as I understand your have a column which has the formula to calculate the quarter say "Formula_Col"
Solution will be to add a new column and flag it based on the values in "Formula_Col".
If you can give some sample data I can provide exact answer.

Power BI first IF-Statement then the DAX-Formula

I am new to Power BI and have the following issue:
I tried to build a formula for a frequency counter. I got some examples from the web and I was able to build this working formula. The basic idea behind is to categorize an item with the values: daily, weekly or first time.
I tried to add an IF-Statement to the formula, that is checking a calculated column "Time frame", which shows the duration of an item in minutes.
Basically it should run this formula only if the Column "Time frame" is equal or bigger 1.
Now the formula gives to items with a Time frame of 0, the value first time. But they should be ignored or blanked.
Calculated column =
Var freqcount =
COUNTAX(FILTER(ALL('Count'),
AND([Date]>=DATEADD('Count'[Date],-6,DAY)&&[Date]<=EARLIER([Date]),[ID]=EARLIER('Count'[ID]))),ID])
return
if(freqcount>=4,"Daily",if(freqcount>=2,"Weekly",if(freqcount>=1,"First time","Inactive")))
I would be thankful, if someone could support me with this issue.
Edit: an ID can occur multiple times in my table but with different dates. But only once with the same date. For example:
ID 1, Date 01.01.2020
ID 1, Date 02.01.2020
ID 1, Date 03.01.2020
it is easier to use calculate:
Calculated column =
var rDate = yourTable[Date]
var rID = yourTable[ID]
var freqCount = CALCULATE(yourTable('Count'), FILTER(yourTable, rDate >= DATEADD(yourTable[Date], -6 , DAY) && rID = yourTable[ID] && yourTable['Time frame'] > 0))
return if(freqcount>=4,"Daily",if(freqcount>=2,"Weekly",if(freqcount>=1,"First time","Inactive")))
you see how I simply added the Time frame to the expression. Also I removed the use of earlier by using var's so it is better readable.

Multiple Vars for DateDiff VBA

I have a VBA script at the moment that reads in 6 values as integers. 3 values for date, month, and year and 3 of the same type from a different location. I'd like to take the values and check if there has been more than a year to pass between them. DateDiff seems like the easiest way to handle this, however that function reads in the values as one DateValue (ie March 20, 2015) and my values are returned individually (08,08,2015).
I wrote a function that stores each value into a var and then using those individually I concat them into a format that DateValue can use.
This works, however I am curious if there is another(better) way to handle this problem?
Thanks in advance.
The function DateSerial(2015,3,4) will return the date for 3/4/2015, and with both of your dates in that format, you can subtract the one date from the other, and if the (absolute value of the) difference is > 365 then you know that they are over a year apart.
Dim A As Date
A = DateSerial(2015, 3, 4)
Dim B As Date
B = DateSerial(2014, 3, 2)
Dim C As Integer
C = Abs(A - B)
MsgBox C & " days between"

Finding the next result from a MATCH

I am trying to produce a sorted table in excel, which depend on the selected year and category.
My methodology has been to sequentially find largest values in order, within the selected year and category parameters, doing the following:
Column E
{=LARGE(IF(('Master Data'!A$1:A$500 = $B$1) * ('Master Data'!B$1:B$500 = $B$2),'Master Data'!C$1:C$500), $B10)}
This works fine, $B$1$ is where I store the year, $B$2 is where I store the category, $B10 references a hard coded 1-25 in column B.
Column F
{=MATCH(E10,IF(('Master Data'!A$1:A$500 = $B$1) * ('Master Data'!B$1:B$500 = $B$2),'Master Data'!C$1:C$500),FALSE)}
This returns the row number of the result I need, which I then use in conjunction with INDEX to find related data.
The problem with this is that Match only returns the first row number, and if you have two results with the same value this clearly becomes an issue.
Column G
To resolve this I used an example from dailydoseofexcel which looks like this:
=IF(F10<>F11, F11, G10+MATCH(E11,INDIRECT("'Master Data'!C"&(G10+1)&":C500"),0))
This works to a limited extent, for my purposes, as it is unable to take into account the year and category filter I need to apply, so I tried:
{=IF(F10<>F11, F11, G10+MATCH(E11,IF((INDIRECT("'Master Data'!A"&(G10+1)&":A500") = $C$2) * (INDIRECT("'Master Data'!B"&(G10+1)&":B500") = $C$3), INDIRECT("'Master Data'!C"&(G10+1)&":C500")),0))}
But I am just getting #N/A as a result.
I think SUMPRODUCT may be what you are looking for:
Charley Kyd XL Legend: Use SUMPRODUCT to get the Last item in a list

Resources