Spotfire: Select data from column based on criteria - calculated-columns

I have a data table in Spotfire which contains two columns I'm interested in: Time (31/01/2015 for example), and Value (integer).
I want the most recent date (e.g. December 2015) to be set as the current time. Then I want to select Value based on previous 1 month, 3 months, 6 months etc. So if I want all the values for past 6 months it should Sum(Values) for Dec.2015, November.2015, October.2015, September.2015, August.2015 and return that.
So far I've only been able to accomplish this by manually performing the task in Excel before I insert it into Spotfire so is there any way to create a calculated column for each of the periods I want? (Past month, 3 months etc.)

There's likely a number of ways to solve this, but I'm going to give one suggestion and we'll see how it fits your specific case.
You can add a calculated column for each timespan you are interested in, defined like this:
Sum(if (DateAdd('month', 3, [Time]) >= Max([Time]), [Value], null))
This example would get you a column with all the values that have occured in the past 3 months, replace the number 3 in there to modify to the timespans you are interested in. A full sum of the calculated column would get you the total for that timespan.
Might be nicer to use a boolean column instead of duplicating the value column. Then your calculated columns would be defined as:
DateAdd('month', 3, [Time]) >= Max([Time])
When calculating totals you would then use an if statement using the calculated column, like this:
Sum(if([3Months],[Value],null))
where [3Months] is a boolean column.

Related

Get sum of cells containing "Vacation" except when related date matches certain day & month

oversimplified i have two columns: Date and Text; I want to check my current amount of vacation days based on the first date in row 2, so i came up with the following formula:
="Available vacation days: "&YEARFRAC(A2;TODAY())*12*(25/12)
I calculate the fraction of the year based on the first date and todays date, multiply it by 12 to get months and multiply it again by the total amount of vacation days in my contract per month. Now i got another formula to collect me all cells in column B containing "Vacation", pretty straight forward:
=COUNTIF(B:B;"Vacation")
Now the interesting part - i got the formula who gives me a boolean if a datetime matches the 24th or 31st of december:
=AND(OR(DAY(A53)=24;DAY(A53)=31);MONTH(A53)=12)
I want to count vacation days happening on a 24th or 31st of december as a half-vacation day (0.5), and otherwise fully (as a 1). Then i want to combine my first statement with this result and subtract the used vacation days. I read about VLOOKUP and XLOOKUP but am unsure if this fits this purpose. I want to avoid having an extra column with my boolean returns and rather have this one cell giving me all the information combined.
Without introducing another column, and using DAY and MONTH
It's nearly impossible, and just unnecessarily so...
Please reconsider this, what will happen if you want to add 4th of July as a holiday?
Your formula =AND(OR(DAY(A53)=24;DAY(A53)=31);MONTH(A53)=12) only works for 1 row at a time. So, we can't ever use it with a list, because you will get the whole list as a result every single time. You can't divide them into smaller lists and join them together, there is no such functionality without VBA.
In the future, do not set arbitrary constraints like "no additional columns", you can hide them if you don't like them. And if you don't need them, remove unnecessary rows like non-vacation rows. They are irrelevant, so why not separate the two.
Just to prove my point, here's the solution you wanted:
Solution
=COUNTIFS(B2:B9;"Vacation") - (COUNT(IFERROR(FILTER(FILTER(FILTER(A2:A9;B2:B9="Vacation");MONTH(FILTER(A2:A9;B2:B9="Vacation"))=12);DAY(FILTER(FILTER(A2:A9;B2:B9="Vacation");MONTH(FILTER(A2:A9;B2:B9="Vacation"))=12))=31);0))+(COUNT(IFERROR(FILTER(FILTER(FILTER(A2:A9;B2:B9="Vacation");MONTH(FILTER(A2:A9;B2:B9="Vacation"))=12);DAY(FILTER(FILTER(A2:A9;B2:B9="Vacation");MONTH(FILTER(A2:A9;B2:B9="Vacation"))=12))=24);0))))*0,5
It works, but it's a pain to read, use and maintain.
A2:A9 refers to the dates column
B2:B9 refers to the text column
So in the future, the last thing you want to do is set arbitrary constraints. Furthermore, why use functions like MONTH and DAY when we can just read the text? That way you could even create a table of holidays to search for instead. That will be no fun task with this setup. (Oh, and if it's because of the year, just strip it away from the text when you want to know only the month and day.
Best of luck!

DAX for rolling seven day average to pivot chart by year

I'm trying to create a single pivot chart that will show separate years of data on the same date axis for a rolling 7-day average.
So, the x-axis will be text, 01-Jan to 31-Dec, and each year will be a separate series:
It has to be a text x-axis, as 01-Jan will be a category containing data for 01-Jan-2018, 01-Jan-2019, 01-Jan-2020...
In theory, the pivot table setup would have the column (series) as the Year, and the x-Axis (labels) as the date label (column Date).
The values are then from the DAX expression that creates the rolling 7-day average.
The source data (tblSource) has a single column of dates (Date2) that rolls over across years and has the column Year to break it down in the pivot.
The daily value is the one that is averaged (itself and the previous six days).
The 7-day average I normally use in DAX doesn't work here.
I need to have the Date column actually in the pivot rather than Date2, as the axis needs to be text to allow for multiple date years on the same x-axis point, but I can't get a DAX formula to work.
The other consideration is that the formula can't just consider a single year, as the rolling seven day average for 01-Jan-2018 includes the previous six days of 2017, for example.
This is the formula I usually use, but I can't manage to tweak it!
AVERAGEX (
DATESINPERIOD ( tblSource[Date2], LASTDATE ( tblSource[Date2] ), -7, DAY ),
[Sum of Daily Value]
)
But this is the output I get, and nothing has been averaged. I think it's because Date2 is being pivoted off Date, but I'm not sure how I get around that?
Can anybody offer me any help?
It's quite a frustrating problem as it would be trivial for me to do it using code, or doing it manually, but I really am trying to get better at DAX!
Thanks in advance!
Phil.
Update: Thanks to Joao for this.
=VAR d = MAX(tblSource[Date2])
RETURN CALCULATE(AVERAGE(tblSource[Daily Value]),
ALL(tblSource[Date]),
DATESINPERIOD(tblSource[Date2], d, -7, day),tblSource[Year]>0)
I had to use MAX rather than SELECTVALUE as Excel seems to lack that functionality.
I also had to unfilter the Year, so that the rolling average could be calculated from the previous year's date where neccessary.
Thanks.
When you run that measure, your table is being filtered by the date text at each point, so when you pass/create the DATESINPERIOD filter, it creates a table with the last 7 dates, but only one of them is actually available (the one relevant to your current data point).
You need to clear the filters on the table so that you have all the dates available, in order for you average to work. You can achieve this by changing the measure slightly:
VAR d = SELECTEDVALUE(tblSource[Date2])
RETURN CALCULATE(AVERAGE(tblSource[Daily Value]),
ALL(tblSource[Date]),
DATESINPERIOD(tblSource[Date2], d, -7, day))

Excel: Nesting two Nested IF statements inside one IF statement depending on Dropdown Box

I have 2 Nested IF Statements..
=IF($B3=$K$3,DATE(YEAR(D3)+$L$3,MONTH(D3)+$M$3,DAY(D3)),IF($B3=$K$4,DATE(YEAR(D3)+$L$4,MONTH(D3)+$M$4,DAY(D3)),IF($B3=$K$5,DATE(YEAR(D3)+$L$5,MONTH(D3)+$M$5,DAY(D3)),IF($B3=$K$6,DATE(YEAR(D3)+$L$6,MONTH(D3)+$M$6,DAY(D3)),""))))
and
=IF($C3=$O$3,DATE(YEAR(D3)+$P$3,MONTH(D3)+$Q$3,DAY(D3)),IF($C3=$O$4,DATE(YEAR(D3)+$P$4,MONTH(D3)+$Q$4,DAY(D3)),IF($C3=$O$5,DATE(YEAR(D3)+$P$5,MONTH(D3)+$Q$5,DAY(D3)),"")))
which work as required in two separate columns. What I would like is to Nest them again so that depending on the choice made from a Data Validation dropbox (Choice 1 or Choice 2, in the following) it either displays the date calculated from the first Choice, or from the second. This is what I have, but I can't get it to work. I think I need an OR in there, but I don't know where, as there are so many IFs already.
=IF($I$2=”Choice1”,IF($B3=$K$3,DATE(YEAR(D3)+$L$3,MONTH(D3)+$M$3,DAY(D3)),IF($B3=$K$4,DATE(YEAR(D3)+$L$4,MONTH(D3)+$M$4,DAY(D3)),IF($B3=$K$5,DATE(YEAR(D3)+$L$5,MONTH(D3)+$M$5,DAY(D3)),IF($B3=$K$6,DATE(YEAR(D3)+$L$6,MONTH(D3)+$M$6,DAY(D3)))),IF($I$2=”Choice2”,IF($C3=$O$3,DATE(YEAR(D3)+$P$3,MONTH(D3)+$Q$3,DAY(D3)),IF($C3=$O$4,DATE(YEAR(D3)+$P$4,MONTH(D3)+$Q$4,DAY(D3)),IF($C3=$O$5,DATE(YEAR(D3)+$P$5,MONTH(D3)+$Q$5,DAY(D3))),""))))))
If it was just one column of dates I can use this..
=IF($I$2="Choice 1",$E4, IF($I$2="Choice 2",$F4,""))
with a couple of helper columns, but I could have as many as 10, which would require 20 helper columns on a spreadsheet that's already 70 odd columns wide, which I'd rather avoid if possible. I've done this on a test worksheet, rather than mess about with the original for now.
EDIT Additional information as requested. (Edited to generic terms as it's a work item)
I have these columns
and using the following dropdown..
would like the date in "Choice 1 OR 2 Increase" to update depending on the selection of either "Choice 1" or Choice 2" information chosen from either of the two sets of Category dropdowns..
This formula takes the information from the first date dropdown and correctly calculates the new date..
=IF($B3=$K$3,DATE(YEAR(D3)+$L$3,MONTH(D3)+$M$3,DAY(D3)),IF($B3=$K$4,DATE(YEAR(D3)+$L$4,MONTH(D3)+$M$4,DAY(D3)),IF($B3=$K$5,DATE(YEAR(D3)+$L$5,MONTH(D3)+$M$5,DAY(D3)),IF($B3=$K$6,DATE(YEAR(D3)+$L$6,MONTH(D3)+$M$6,DAY(D3)),""))))
with Category 1 - 4, in that order, being the four date sections of this formula.
This formula takes the information from the second date dropdown and correctly calculates the new date..
=IF($C3=$O$3,DATE(YEAR(D3)+$P$3,MONTH(D3)+$Q$3,DAY(D3)),IF($C3=$O$4,DATE(YEAR(D3)+$P$4,MONTH(D3)+$Q$4,DAY(D3)),IF($C3=$O$5,DATE(YEAR(D3)+$P$5,MONTH(D3)+$Q$5,DAY(D3)),"")))
with Category 5-7, in that order being the three date sections of this formula.
Both formulas work correctly when used independently of each other to populate individual columns, and a third column can be used to get the date required (using the dates already provided separately in two "helper" columns) using the following formula..
=IF($I$2="Choice1",$E3, IF($I$2="Choice2",$F3,""))
What I would like is to be able to combine the actions of both of the above formulas somehow, so that by using the Choice 1/Choice 2 dropdown (Pic 2), it calculates the date depending on the choice in that dropdown box, and also the other two dropdown boxes (Pics 3 + 4) and populates the "Choice 1 OR 2 Increase" column (Pic 1)
If I was only using this one example, I'd just use the helper columns but there will be several, and the sheet is around 70 columns wide already. Combining (at least the actions of) these two formulas into one, will save a lot of extra columns.
I hope that's the information you require..
Thanks
Liam
I would set things up differently, and use a different formula.
Since your Categories and Choices do not overlap, I would combine all the categories into a single table.
eg:
Since both Years and Months can have a varying number of days, I'd suggest using EDATE for the additions.
I also used a Named Range for the Choice dropdown,
and a Table for the Category table.
Doing that, you can use this formula (assuming your data table is in A1:Cn)
=EDATE(C2,VLOOKUP(INDEX($A2:$B$5,1,MATCH(Choice,$A$1:$B$1,0)),Category,2,FALSE)*12 + VLOOKUP(INDEX($A2:$B$5,1,MATCH(Choice,$A$1:$B$1,0)),Category,3,FALSE))
The formula
MATCH decides which column of category choice to use
VLOOKUP to return the appropriate years and months
EDATE(Date, years*12 + months)
If you prefer to use your method of adding datevalues, you can apply the same methodology:
=DATE(YEAR(C2)+VLOOKUP(INDEX($A2:$B$5,1,MATCH(Choice,$A$1:$B$1,0)),Category,2,FALSE),MONTH(C2)+VLOOKUP(INDEX($A2:$B$5,1,MATCH(Choice,$A$1:$B$1,0)),Category,3,FALSE),DAY(C2))
Note that the two methods can give different results depending on the day of the month, and whether the end month has the same number of days as the start month.
eg:
31 January 2020 + 1 month --> 29 Feb 2020 vs 02 Mar 2020
31 January 2020 + 3 month --> 30 Apr 2020 vs 01 May 2020

Excel AVERAGEIFS else statement

I'm trying to perform an AVERAGEIFS formula on some data, but there are 2 possible results and as far as I can tell AVERAGEIFS doesn't deal with that situation.
I basically want to have an ELSE inside it.
At the moment I have 2 ranges of data:
The first column only contains values 'M-T' and 'F' (Mon-Thurs and Fri).
The second column contains a time.
The times on the rows with an 'F' value in column 1 are an hour behind the rest.
I want to take an average of all the times, adjusting for the hour delay on Fridays.
So for example I want it to take an average of all the times, but subtract 1 hour from the values which are in a row with an 'F' value in it.
The way I've been doing it so far is by having 2 separate results for each day, then averaging them again for a final one:
=AVERAGEIFS(G3:G172, B3:B172, "M-T")
=AVERAGEIFS(G3:G172, B3:B172, "F")
I want to combine this into just one result.
The closest I can get is the following:
=AVERAGE(IF(B3:B172="M-T",G3:G172,((G3:G172)-1/24)))
But this doesn't produce the correct result.
Any advice?
Try this
=(SUMPRODUCT(G3:G172)-(COUNTIF(B3:B172,"=F")/24))/COUNTIF(B3:B172,"<>""""")
EDIT
Explaining various steps in the formula as per sample data in the snapshot.
SUMPRODUCT(G3:G17) sums up all the value from G3 to G17. It gives a
value of 4.635416667. This after formatting to [h]:mm gives a value
of 111.15
OP desires that Friday time be one hour less. So I have kept one hour less for Friday's in the sample data. Similar SUMPRODUCT on H3:H17 leads to a value of 4.510416667. This after formatting to [h]:mm gives a value
of 108.15. Which is exactly three hours less for three occurrences of Fridays in the sample data.
=COUNTIF(B3:B17,"=F") counts the occurrences of Friday's in the B3:B17 range which are 3 occurrences.Hence 3 hours have to less. These hours are to be represented in terms of 24 hours hence the Function COUNTIF() value is divided by 24. This gives 0.125. Same is the difference of 4.635416667 and 4.510416667 i.e. 0.125
Demonstration column H is for illustrative purposes only. Infact Friday accounted values that is 108.15 in sample data has to be divided by total data points to get the AVERAGE. The occurrences of data points are calculated by =COUNTIF(B3:B17,"<>""""") with a check for empty columns.
Thus 108:15 divided by 15 data points give 7:13 in the answer.
Revised EDIT Based upon suggestions by #Tom Sharpe
#TomSharpe has been kind enough to point the shortcomings in the method proposed by me. COUNTIF(B3:B172,"<>""""") gives too many values and is not advised. Instead of it COUNTA(B3:B172) or COUNT(G3:G172) are preferable. Better Formula to get AVERAGE as per his suggestion gives very accurate results and is revised to:
=AVERAGE(IF(B3:B172="M-T",G3:G172,((G3:G172)-1/24)))
This is an Array Formula. It has to be entered with CSE and further cell to be formatted as time.
If your column of M-T and F is named Day and your column of times is named TIME then:
=SUMPRODUCT(((Day="M-T")*TIME + (Day="F")*(TIME-1/24)))/COUNT(TIME)
One simple solution would be to create a separate column that maps the time column and performs the adjustment there. Then average this new column.
Is that an option?
Ended up just combining the two averageifs. No idea why I didn't just do that from the start:
=((AVERAGEIFS(G$3:G171, $B$3:$B171, "F")-1/24)+AVERAGEIFS(G$3:G171, $B$3:$B171, "M-T"))/2

Working with an OLAP Cube in Excel; determine monthly values within a larger date range?

I've been working in an OLAP cube as a pivottable in excel for a while now, but more recently I'm trying to integrate some calculated measures to streamline some things, and I've hit a wall.
The cube has date filters set up that specify the month & year (they get more specific, but finer levels aren't used).
The rows will list individual projects, and the values can reflect 2 measures: one that reflects the average score for the date range, and another that reflects the number of observations the average is based on.
I would like to create a calculated measure that will display the average score for each project as long as 2 criteria are met:
There is a minimum of 100 observations for the whole date range
there are no months with zero observations across the date range specified in the pivottable.
I should also clarify that the date ranges I use will vary and length, and will not always end with the most recent month, but they will always be in increments of whole months.
I'm part of the way there, as a calculated measure based on this will provide me with the average only if there are enough observations for the date range:
IIF([Measures].[OBSERVATIONS]>=100,[Measures].[AVERAGE],"^^")
Now, I need to add the criteria of no months with zero observations.
I have attempted to use COUNT(), but in this form it ignores the date range set in the pivottable and returns a count of all of the months there is any value for the project, including zeros.
COUNT(([Calendar].[Calendar].[Month],[Measures].[OBSERVATIONS]),EXCLUDEEMPTY)
I tried determining the lowest number of observations in a month using this expression, but again it ignores the date range, and does not reflect empty cells:
MIN([Calendar].[Calendar].[Month],[Measures].[OBSERVATIONS])
I think CurrentMember is what I need to include, but I can't get it to work for me.
Assuming it's relevant, and I'm not sure the best way to explain the calendar hierarchy, so this reflects what I have:
The first calendar listing is the one used to filter the pivot table data, and it is also pulled into the mdx expressions above.
EDIT:
Thanks #SouravA for the reply. I tried a few things, and given that formatting in comments is limited, here's a rundown of what I did.
I'm getting an error message that says "Query(1,35) Parser: The syntax for 'WITH' is incorrect"
to make sure I'm using this correctly:
After making the changes below, I pasted the whole thing into the MDX: window from the 'calculated measures' tool in Excel.
I of course changed OBSERVATIONS and AVERAGE to the variable names in my cube.
I changed '[Project].[ProjectCode]' to '[Project].[ProjectName]', which is how my cube is set up.
On '[NewMeasure]' I changed it to the name I am using for the calculated measure.
on '[your cube]' I've tried a couple different things; the cube reference I use in the cube formulas in excel looks like this: 'Cubename NormativeCube', so I tried pasting that in the brackets with and without quotes, leaving the NormativeCube part off, and doing all that without the brackets.
I also modified the last line after 'WHERE' to reflect date ranges like this:
'[Calendar].[Calendar].[Month].&1&[2015]:[Calendar].[Calendar].[Month].&[12]&[2015]'
I've also set that as '[Calendar].[Month].[Month].&1:[Calendar].[Month].[Month].&[12]'
Also, one more question; will this work for any date range, or is it intended to be specified in the MDX? I need it to function based on the date range set by the cube filters.
EDIT 2:
I just needed to tweak this a tad by changing the '> 0' to '= 0', as the original solution only showed the average for those that did not have data for each month in the date range, and adjust one of the calendar set expressions or whatever.
IIF
(
[Measures].[OBSERVATIONS]>=100
AND
COUNT
(
FILTER
(
EXISTS
(
[Calendar].[Calendar].[Month].MEMBERS
,EXISTING [Calendar].[Calendar].[Month].MEMBERS
)
,[Measures].[OBSERVATIONS] = 0
)
) = 0
,[Measures].[AVERAGE]
,"^^"
)
EDIT 3:
Found a limitation;
the measure only works if the date range defined for the cube is in a whole increment of the calendar hierarchy; i.e. a single month, a single quarter, or a single year. doing 2 months, 2 quarters, 2 years, or breaking across 2 quarters or years will return the False outcome from the IIF() expression.
I played around with a few different ways to set it up, but can't get it to work.
EDIT 4:
Re: calendar hierarchy
Looking underneath [calendar].[calendar] there are 4 options: Year, Quarter, Month, & Date Key.
looking at the members under Year, Quarter, & Month, you can drill down all the way to the individual day.
The member properties under those 3 lists just the next level up the hierarchy
On Date Key, the member properties are as follows:
Month Name
Month of Year
Time Calcs (this doesn't do much to my knowledge)
Week of Year Week
EDIT 5:
So this is what worked (finally). I must have messed something up at some point, and editing the original formula caused the secondary issue I was having. Here's what worked for me.
IIF
(
[Measures].[OBSERVATIONS]>=100
AND
COUNT
(
FILTER
(
EXISTS
(
[Calendar].[Calendar].[Month].Members
,EXISTING [Calendar].[Calendar].Members
)
,[Measures].[OBSERVATIONS] = 0
)
) > 0
,[Measures].[AVERAGE]
,"^^"
)
Using the EXISTING clause comes in handy at times when you want your calculation to recognize a certain selection(context). Following code is self explanatory. Let me know if it works.
WITH SET ZeroObservationMonths AS
FILTER
(
EXISTS
(
[Calendar].[Calendar].[Month].MEMBERS
,EXISTING [Calendar].[Calendar].[Date].MEMBERS
)
,[Measures].[OBSERVATIONS] = 0
)
MEMBER Measures.NewMeasure AS
IIF
(
[Measures].[OBSERVATIONS]>=100 AND COUNT(ZeroObservationMonths) > 0
,[Measures].[AVERAGE]
,"^^"
)
SELECT [Project].[ProjectCode].MEMBERS ON 1,
Measures.[NewMeasure] ON 0
FROM [YourCube]
WHERE ({[Calendar].[Calendar].[Date].&D1: [Calendar].[Calendar].[Date].&D2})
EDIT:
If you're planning on creating the measure inside excel, just have the below MDX code in the text box for "New calculated measure"
IIF
(
[Measures].[OBSERVATIONS]>=100
AND
COUNT
(
FILTER
(
EXISTS
(
[Calendar].[Calendar].[Month].MEMBERS
,EXISTING [Calendar].[Calendar].[Date].MEMBERS
)
,[Measures].[OBSERVATIONS] = 0
)
) > 0
,[Measures].[AVERAGE]
,"^^"
)
EDIT 2: If the filtering can happen on any attribute, not just dates, replace EXISTING [Calendar].[Calendar].[Date].MEMBERS with EXISTING [Calendar].[Calendar].MEMBERS in the script above.

Resources