How to capture slicer value by DAX measure in all circumstances? Let's have sample data:
+-----------+---------+-------+
| category | species | units |
+-----------+---------+-------+
| fruit | apple | 1 |
| fruit | banana | 1 |
| vegetable | carrot | 1 |
| vegetable | potato | 1 |
+-----------+---------+-------+
I added two measures:
Measure 1:
species selected = SELECTEDVALUE(Table1[species])
Measure 2:
IsFiltered = ISFILTERED(Table1[species])
Case 1. All items in both slicers selected.
Case 2. (problematic case). Fruits selected and Carrots selected (it is possible when we untie slicers interactions).
In case when we select fruit category from one slicer and carrot from another slicer there is a problem. This set of items is obviously empty. However definitely carrot from species have been selected and it is confirmed by IsFiltered measure which evaluates to True. Is there a way to capture that value in DAX measure?
Since both the category and species slicers come from columns on the same table, if you have both fruit and carrot selected, then the resulting table is empty and any measures (except ones that remove both filters) will therefore be working with blanks. You cannot have both filters apply simultaneously an expect them to act independently (even if the two slicer visuals don't cross-filter).
If you don't want your species selected measure to be influenced by category, the simplest thing to do would be to turn off filtering (under Format > Edit interactions) from the category slicer to the visual containing species selected.
This isn't always what you want though, so another possibility is to create a new table for the species slicer which has no filtering relationship from Table1. This will allow you to work with the slicers selections separately if that's something you need to do. (I've definitely had to do this before when I wanted a slicer to behave more like a parameter than a filter.)
Edit: To do what I suggested, create a new Table2 in the query editor that references Table1, remove all columns other than species and remove duplicate if necessary. You should now have a single column table that is a list of unique species.
When you close and apply, Power BI will likely automatically create a relationship between the two tables, but you need to make sure it's exactly what you want. It needs to be a many to one relationship with a single filter direction.
Once this is done, you'll need to replace the Table1[species] slicer with Table2[species] slicer as well as change references in measures where necessary.
Related
I'm struggling to create a Measure that sums a column and have it filter out duplicate IDs while taking only the latest row.
For example, there is a table as such:
UID | Quantity | Status | StatusDate
aaa | 3 | Shipped | 11/1/2020
aaa | 3 | Delivered | 11/5/2020
bbb | 5 | Ordered | 10/29/2020
ccc | 8 | Shipped | 11/4/2020
So the idea would be to sum the quantity, but I would only want to count quantity for id "aaa" once and only count towards the latest status ("Delivered" in this case). I would make a visual that shows the quantities with status as its axis. I also need to add a date Slicer so I could go back in time. So, when I go before 11/5/2020, instead of "Delivered," it would switch back to "Shipped."
I tried several methods:
SUMMARIZE to a table filtering "MAX" date value if UID is the same. I found this doesn't work with the date slicer since it seems like it is not actually recalculating the filtering and just slicing away rows outside of the dates. Seems to be the same whether the SUMMARIZE is set as a new table or VAR in the Measure.
CALCULATE seems promising but I can't seem to figure out a syntax
that filters that I need. Example of one that doesn't work (I also tried SUMX instead of SUM but that doesn't work either):
CALCULATE(
SUM(Table1[Quantity]),
FILTER(Table1, [StatusDate]=MAXX(FILTER(Table1,[UID]=EARLIER([UID])),[StatusDate])
)
I also tried adding a column that states whether if the row is "old" as well as a numerical "rank" to the different statuses. But once again, I run into the issue where the date slicer is not exactly filtering to recalculate those columns. For example, if the date slicer is set to 11/3/2020, it should add "3" to "Shipped" instead of "Delivered." But instead of that, it just removes the row which tells me that it is not actually recalculating the columns (like #1).
Any help would be appreciated :-) Thank you!
You can try something like this:
Measure =
VAR d = LASTDATE(Table1[StatusDate])
VAR tb = SUMMARIZE(FILTER(Table1, Table1[StatusDate] <= d),
Table1[UID],
"last", LASTDATE(Table1[StatusDate]))
RETURN CALCULATE(SUM(Table1[Quantity]), TREATAS(tb, Table1[UID], Table1[StatusDate]))
The tb variable contains a table which has the latest date per UID. You then use that to filter your main table with the TREATAS function.
One other alternative is to create a table with the RANK function ordered by date and then doing a SUM over that table, where Rank = 1.
Hopefully a quick explanation of what I am hoping to accomplish followed by the approach we've been working on for over a year.
Desired Result
I have a table of SCD values with two columns, SCD_Valid_From and SCD_Valid_To. Is there a way to join a date table in my model (or simply use a slicer without a join) in order to be able to choose a specific date that is in between the two SCD columns and have that row of data returned?
Original Table
ID | SCD_Valid_From | SCR_Valid_To | Cost
1 2020-08-01 2020-08-03 5.00
Slicer date chosen is 2020-08-02. I would like this ID=1 record to be returned.
What We've Attempted So Far
We had a consultant come in and help us get Power BI launched last year. His solution was to create an expansion table that would contain a row for every ID/Date combination.
Expanded Original Table
ID | SCD_Valid_Date | Cost
1 2020-08-01 5.00
1 2020-08-02 5.00
1 2020-08-03 5.00
This was happening originally on the Power BI side, and we would use incremental refresh to control how much of this table was getting pushed each day. Long story short, this was extremely inefficient and made the refresh too slow to be effective - for 5 years' worth of data, we would need over 2000 rows per ID just to be able to select a dimensional record.
Is there a way to use a slicer where Power BI can select the records where that selected date falls between dates in two columns of a table?
Let me explain a workaround and I hope this will help you to solve your issue. Let me guess you have below 2 tables-
"Dates" table with column "Date" from where you are generating the date slicer.
"your_main_table" with with column "scd_valid_from" and "scd_valid_to".
Step-1: If you do not have relation between table "Dates" and "your_main_table", this is fine as other wise you have to create a new table like "Dates2". For this work around, you can not have relation between those tables.
In case you have already relation established between those tables, create a new custom table with this below code-
Dates2 =
SELECTCOLUMNS(
Dates,
"Date", Dates[Date]
)
From here, I will consider "Dates2" as source of your Date slicer. But if you have "Date" table with no relation with table "your_main_table", just consider "Dates" in place of "Dates2" in below measures creation. Now, Create these following 4 measures in your table "your_main_table"
1.
date_from_current_row = max(join_using_date_range[SCD_Valid_From])
2.
date_to_current_row = max(join_using_date_range[SCD_Valid_to])
3.
date_selected_in_slicer = SELECTEDVALUE(Dates2[Date])
4.
show_hide_row =
if(
[date_selected_in_slicer] >= [date_from_current_row]
&& [date_selected_in_slicer] <= [date_to_current_row]
,
1,
0
)
Now you have all instruments ready for play. Create your visual using columns from the table "your_main_table"
Final Step: Now just add a visual level filter with the measure "show_hide_row" and set value will show only when "show_hide_row = 1".
The final output will be something like below image-
I am using a Matrix in PowerBI to show the Sales Manager and Sales Reps down the rows, and the different ship method and source of the order across the columns and a count of unique orders in the values.
Below shows the table structure I have, and I want to switch between "Show Values As": the original values I calculate with my measure (count of unique orders) and % of Row Total.
Currently, my only solution is to create a second table showing the different values, but I think that's a cheap solution. I've seen solutions with helper tables but since my values are a measure I cannot invoke them in other measures, and as the sources or ship methods are filtered I want the % of row total to reflect the filter as well so using a countx formula won't account for that (if I housed it in a formula).
I'm still somewhat new to the software so please bear that in mind.
Source 1 | Source 2 | Source 3
| Next Day; Ground; 2 Day | Next Day; Ground; 2 Day | Next Day; Ground; 2 Day
+Manager 1|
Rep 1 |
Rep 2 |
+Manager 2|
Rep 1 |
Rep 2 |
Looks like the best solution for you is to create bookmarks. You can create two tables, one showing the values and the other showing the %. Position the tables such that, one table is exactly on top of the other. Then create two bookmarks, one showing Table1 and the other showing Table2 (while hiding the other table using the "Selection Pane"). You can then use the bookmarks in a button action to toggle between Value and % views. The following link should give you further details on bookmarks:
https://learn.microsoft.com/en-us/power-bi/desktop-bookmarks
You can also do this by creating a measure which switches between values and %, but the formatting is going to be a pain point. I think bookmarks is your best bet.
You can create a parameter table (with no relationships to other tables in your model) to use as a slicer and a measure that switches between the two calculations based on a slicer selection.
Let's suppose you have measures [OrderCount] and [OrderCount%Total]. Then create a new table to use as a parameter ParamMeasure with a single column
Measure
-------
Count
%Total
You can now put ParamMeasure[Measure] as a slicer on your report and substitute the following measure instead of the existing ones.
OrderSwitch =
IF (
SELECTEDVALUE ( ParamMeasure[Measure] ) = "Count",
[OrderCount],
[Order%Total]
)
This way you don't need to create multiple visuals and bookmarks.
I have a table of Enter and Exit time of some people like this:
Name | EnterTime | ExitTime
=============================
Tom | 13:52:00 | 20:55:00
Robert | 15:55:00 | 21:12:00
Sarah | 19:08:00 | 19:48:00
Jack | 16:54:00 | 17:32:00
I want to show the user that in a selected point of time who has presence.
In other word, I want to have a dateTime slicer that the user will pick a time and then the table got filtered to show only rows with:
EnterTime < selectedTime < ExitTime
This can be done with a few steps.
First, we need a list of dates to go into our slicer. If you're using a separate date table, then that's a great source. Otherwise, you can build one with DAX that will contain all the dates in your EnterTime and ExitTime columns.
Click on 'Create Table' in the modeling ribbon. Put in the following DAX:
DateListTable = UNION(
SELECTCOLUMNS('MyTable', "DateList", 'MyTable'[EnterTime]),
SELECTCOLUMNS('MyTable',"DateList", 'MyTable'[ExitTime])
)
You now have a slicer and a table visual. Select the slicer and then navigate into the Format Ribbon (it's only available when the visual is selected. Use Edit Interactions to turn off the Slicer's filtering on the table. Set it to no interaction (the circle with a diagonal line through it).
Create a new measure
ShowDate =
VAR SelectedDate = SELECTEDVALUE('DateListTable'[DateList], BLANK())
Return
if(SelectedDate >= Max('MyTable'[EnterTime ]) && SelectedDate <= max('MyTable'[ExitTime]), 1, 0)
Finally, filter your table visual on the new measure, ShowDate, for when it is 1.
So, we create an independent slicer with a complete list of dates. But we break any filter relationship between it and the table. Instead, we use 'SelectedValue' to capture the value chosen from the filter, and create a dax measure that shows '1' when the value in the filter is between EnterTime and Exit time. Filter on that dax measure, and we get our desired behavior.
I would like to set up initial value of lower category slicer whenever upper category slicer value changes. Suppose we have this data:
+----------------+----------------+-------+
| upper category | lower category | units |
+----------------+----------------+-------+
| fruit | apple | 1 |
| fruit | banana | 1 |
| vegetable | carrot | 1 |
| vegetable | potato | 1 |
+----------------+----------------+-------+
We add two slicer visuals to the report. It looks like this:
My desired results are this: Whenever the user selects fruit from upper category, then apple is selected from lower category slicer. So we end up with this:
Now the we click on vegetable in upper category slicer, and automatically carrot is selected as an initial filter value of lower category slicer. So we end up with this:
Summary:
Upper category slicer shows all items, regardless of lower category slicer choice.
Lower category slicer shows only applicable items, based on upper category slicer choice.
After selecting item from upper category slicer, always one initial aplicalble value of lower category slicer is selected.
After googling I have found this as a promising clue to the solution:
https://www.kasperonbi.com/embed-your-power-bi-report-with-predefined-filters/
I do not have to stick to slicer visual. It could be something else. What I want is to maintain this functionality. I could imagine that it could be accomplished with R visual by the concept expressed here: https://dataveld.com/2016/02/10/r-visuals-in-power-bi-beyond-plots/
Here is a start table code for your convenience:
let
Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WSisqzSxR0lFKLCjISQXShkqxOgjRpMQ8IIQLl6Wmp5YkJoEVJicWFeWXYJUqyC9JLMmHSMUCAA==", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type text) meta [Serialized.Text = true]) in type table [#"upper category" = _t, #"lower category" = _t, units = _t]),
#"Changed Type" = Table.TransformColumnTypes(Source,{{"upper category", type text}, {"lower category", type text}, {"units", Int64.Type}})
in
#"Changed Type"
I don't believe this is currently possible with the default slicer as there is no way to programmatically set a slicer selection, but this related idea is a popular request that is currently "under review".
You can fake it by using the Bookmarks, but you need to effectively build a 'Parent' slicer using bookmark icons that sets the state of the other slicers
Here's how that looks:
That 'Parent' slicer at the top should be hidden.
Here's what happens if I click on the i icon under Fruit:
...and here's what happens if I click the other bookmark:
You can actually ditch the icons and have 'Fruit' and 'Vegetable' text instead. Here's how that looks:
Nothing selected:
Fruit clicked
Vegetables clicked
...although in reality you may need to space the fake Slicer Items further apart, as the title bar of the bottom one can cause issues with the interactivity of the top one, even though you can't see it. Here's a picture in Edit mode, so you know what I mean:
Furthermore, I find the 'Pin Visual' tip annoying, and there isn't (yet) a way to turn this off:
You could get fancier and have some kind of visual effect that somehow highlights which item in the fake slicer is selected. But the down side is that this approach doesn't allow you to handle dynamic lists of Slicer Items...you've got to set up each in advance.