I have a hierarchical matrix with a corresponding chart from this table:
let
t0 = Table.FromRows(
{
{"2020-01-01", "1", "10", 10},
{"2020-01-02", "1", "10", 3},
{"2020-01-01", "1", "11", 8},
{"2020-01-02", "1", "11", 15},
{"2020-01-01", "2", "20", 5},
{"2020-01-02", "2", "20", 9},
{"2020-01-01", "2", "21", 13},
{"2020-01-02", "2", "21", 12}
},
{"day", "cat", "subcat", "amount"}
),
t1 = Table.TransformColumnTypes(t0, {{"amount", Int64.Type}})
in
t1
I can make the page start the chart showing the line for each category, which is what I want, by choosing the category as the legend
Now I want that when I click on the category line in the matrix the chart dynamicaly shows the lines for the subcategories of that category. Is it possible or is there another approach leading to the same result?
I'm not sure if it's possible to do drill down within the visual like that but you can make it work if you have filtering from a slicer or another visual.
First, create a new independent table to use on the x-axis that has both cat and subcat:
CatSubcat = UNION ( VALUES ( t1[cat] ), VALUES ( t1[subcat] ) )
Then we need a corresponding measure to go with it that switches between cat and subcat:
Measure =
IF (
HASONEVALUE ( t1[cat] ),
CALCULATE ( SUM ( t1[amount] ), t1[subcat] IN VALUES ( CatSubcat[cat] ) ),
CALCULATE ( SUM ( t1[amount] ), t1[cat] IN VALUES ( CatSubcat[cat] ) )
)
If nothing is filtered, it should look like this:
If you filter using the matrix to the left (or via a slicer on t1[cat]), you get this:
For more than two levels, this related post may be of use.
Related
I have a table that contains 3 columns:
Order
Date
State
Each row / record shows if the state was changed:
Now I would like to calculate the number of order that are below state 3 for each date in the calendar.
In the example above you can see there is nor entry for order 100 for 07.01.2022. But for this date the order is still below 3 as you can see in the record before.
How would you do that?
I think this might be better to do in PowerQuery.
Suppose the table mentioned in your question is order_state:
let
Source = Table.FromRows(
{
{100, 1, "1/1/2022"},
{100, 2, "1/5/2022"},
{100, 3, "1/8/2022"},
{101, 1, "1/5/2022"},
{101, 2, "1/6/2022"},
{101, 3, "1/7/2022"},
{102, 1, "1/7/2022"},
{102, 2, "1/9/2022"},
{102, 3, "1/10/2022"}
},
{"Order", "Status", "Date"}
),
#"Changed Type" = Table.TransformColumnTypes(Source,{{"Date", type date}})
in
#"Changed Type"
Then I believe you can calculate what you want with a query like this:
let
start_date = List.Min(order_state[Date]),
end_date = List.Max(order_state[Date]),
days = Duration.Days(end_date - start_date),
dates = Table.FromList(List.Dates(start_date,days,#duration(1, 0, 0, 0)), Splitter.SplitByNothing(), {"Date"}, null, ExtraValues.Error),
joined = Table.AddColumn(
dates,
"order_state_rows",
(current) => Table.RowCount(
Table.Distinct(
Table.SelectColumns(
Table.SelectRows(
order_state,
(row) => (row[Date] <= current[Date] and row[Status] <> 3)
)
,{"Order"}
)
)
)
)
in
joined
Which gives this result:
I have created a Dax code that counts up numbers of SKU in our company based on some filters. Right now i have the following code + helper columns in my dataset, that does the job correct.
Number of Active SKU =
CALCULATE( COUNTROWS('Item'),
FILTER('Item','Item'[Helpcolumn3] = 1 ),
FILTER('SKUInfo',SKUInfo[StockKeeping] = "1" ),
NOT('Item'[SKUStatus] IN { "P", "U", "X", "Z" } ) )
Helpcolumn3 consists of three calculated columns in my dataset, with about 1 million rows.
HelpColumn1= IF('Item'[SKULevel] IN {"1","2","3","4","5","6"} && 'Item'[SKUCode] IN{"A","B","C","D","G"},1,0)
HelpColumn2= IF('Item'[SKUCode] ="K", 1, 0 )
HelColumn3 = 'Item'[HelpColumn1] + 'Item'[HelpColumn2]
The reason behind the extra help columns were that i could not figure out how to incorporate this part into my measure. Im pretty sure it is possible, and i would like to avoid creating the three extra help columns with 1 millions rows each, since the data model is already quite big.
Any help as to how i can do this whitout creating the extra columns will be much appreciated!
Can you try the following please
_count=
CALCULATE (
COUNTROWS ( 'Item' ),
TREATAS (
UNION (
SUMMARIZE (
CALCULATETABLE (
'Item',
CROSSJOIN (
{ "1", "2", "3", "4", "5", "6" },
FILTER ( VALUES ( 'Item'[SKUCode] ), 'Item'[SKUCode] IN { "A", "B", "C", "D", "G" } )
)
),
'Item'[SKULevel],
'Item'[SKUCode]
),
SUMMARIZE ( FILTER ( 'Item', 'Item'[SKUCode] = "C" ), 'Item'[SKULevel], 'Item'[SKUCode] )
),
'Item'[SKULevel],
'Item'[SKUCode]
),
FILTER ( VALUES ( 'SKUInfo'[Stockkeeping] ), 'SKUInfo'[Stockkeeping] = 1 ),
NOT 'Item'[SKUStatus] IN { "P", "U", "X", "Z" }
)
I am passing three filtered tables in this measure to do the count.
First set is the following block -> it counts whatever combined elements the data has for 'Item'[SKULevel]={ "1", "2", "3", "4", "5", "6" } and 'Item'[SKUCode]={ "A", "B", "C", "D", "G" }
TREATAS (
UNION (
SUMMARIZE (
CALCULATETABLE (
'Item',
CROSSJOIN (
{ "1", "2", "3", "4", "5", "6" },
FILTER ( VALUES ( 'Item'[SKUCode] ), 'Item'[SKUCode] IN { "A", "B", "C", "D", "G" } )
)
),
'Item'[SKULevel],
'Item'[SKUCode]
),
SUMMARIZE ( FILTER ( 'Item', 'Item'[SKUCode] = "C" ), 'Item'[SKULevel], 'Item'[SKUCode] )
),
'Item'[SKULevel],
'Item'[SKUCode]
2nd set of table is the following block - which further filters the count of the first table to only 'SKUInfo'[Stockkeeping] = 1
FILTER ( VALUES ( 'SKUInfo'[Stockkeeping] ), 'SKUInfo'[Stockkeeping] = 1 )
3rd set of table is the following block - which further filters the 2nd set to only NOT 'Item'[SKUStatus] IN { "P", "U", "X", "Z" }
NOT 'Item'[SKUStatus] IN { "P", "U", "X", "Z" }
In a nutshell, this returns ROWCOUNT for any items that has
'Item'[SKULevel]={ "1", "2", "3", "4", "5", "6" } and 'Item'[SKUCode]={ "A", "B", "C", "D", "G" } but only 'SKUInfo'[Stockkeeping] = 1 and none with [SKUStatus]="P", "U", "X", "Z"
I have a little puzzle that annoys me in PowerBI/DAX. I'm not looking for workarounds - I am looking for an explanation of what is going on.
I've created some sample data to reconstruct the problem.
Here are my two sample tables written in DAX:
Events =
DATATABLE (
"Course", STRING,
"WeekNo", INTEGER,
"Name", STRING,
"Status", STRING,
{
{ "Python", 1, "Joe", "OnSite" },
{ "Python", 1, "Donald", "Video" },
{ "DAX", 2, "Joe", "OnSite" },
{ "DAX", 2, "Hillary", "Video" },
{ "DAX", 3, "Joe", "OnSite" },
{ "DAX", 3, "Hillary", "OnSite" },
{ "DAX", 3, "Donald", "OnSite" }
}
)
WeekNumbers =
DATATABLE ( "WeekNumber", INTEGER, { { 1 }, { 2 }, { 3 }, { 4 } } )
I have a table with events and another table with all weeknumbers and there is a (m:1) relation between them on the weekNo/weeknumber (I've given them different names to easily distinguish them in this example). I have a slicer in PowerBI on the weeknumber. And I have a table which shows aggregation and counts the participants based on the status with the following measures:
#OnSite = COUNTROWS(FILTER(events,Events[Status]="OnSite"))
#Video = COUNTROWS(FILTER(events,Events[Status]="Video"))
I visualize the two measures in a table together with the Course and the weekNo. With the slicer on weekNumber 3 there are nobody with status video so #video is blank. See screenshot.
Then I decided to create a new measure which should show a 0 instead of blank for the #video:
#VideoWithZero = VAR counter=COUNTROWS(FILTER(events,Events[Status]="Video"))
RETURN IF(ISBLANK(counter),0,counter)
I add the #VideoWithZero to the table and get a lot of extra rows in the table for the other weekNo's:
So my question is - Why do I get the extra rows for week 1 and 2 in the table? I would expect my filter on WeekNumber to filter them out.
The filter is being applied to the context of the query executed, and then the measures are calculated. Now the issue is that one of your measures is always returning a value (0), so regardless of your context it will always show a result, thus making it seem that it is ignoring the filter.
One way I tend to get implement this is by providing some additional context to when I might want to show 0 instead of blank. In your case it would be when one of the counts is not blank:
#OnSite =
VAR video = COUNTROWS(FILTER(events,Events[Status]="Video"))
VAR onsite = COUNTROWS(FILTER(events,Events[Status]="OnSite"))
RETURN IF(ISBLANK(video), onsite, onsite + 0) //+0 will force it not to be blank
#Video =
VAR video = COUNTROWS(FILTER(events,Events[Status]="Video"))
VAR onsite = COUNTROWS(FILTER(events,Events[Status]="OnSite"))
RETURN IF(ISBLANK(onsite), video, video + 0)
So on the OnSite measure it will check if there are Videos and if so, it adds +0 to the result of the OnSite count to force it not to be blank (and vice versa)
One other way could be to count total rows and subtract the ones different to the status you need:
#OnSite =
VAR total= COUNTROWS(Events[Status])
VAR notOnsite = COUNTROWS(FILTER(events,Events[Status]<>"OnSite"))
RETURN total - notOnsite
#Video =
VAR total= COUNTROWS(Events[Status])
VAR notVideo= COUNTROWS(FILTER(events,Events[Status]<>"Video"))
RETURN total - notVideo
I need to create a custom header like the picture below:
I check this link Custom aggregate column in power bi matrix
But I don't undestand how to do the same to my case?
Edit
I try to create calculated table but I didn't get the data for dim5 and dim6, how can I modify it?
Edit
Dim_prduit
My problem is how to dispaly Nombre product , and then like hierarchy dim5 then dim6 in the header?
It's ugly but you can write a header table like this and then define a switching measure based on the appropriate indices:
Header =
ADDCOLUMNS (
UNION (
DATATABLE (
"Top", STRING,
"Index1", INTEGER,
"Middle", STRING,
"Index2", INTEGER,
"Bottom", STRING,
"Index3", INTEGER,
{
{ "Nombre product", 1, "", 0, "", 0 },
{ "Affaires nouvelles", 2, "Total", 8, "", 0 },
{ "Affaires nouvelles", 2, "%Total", 9, "", 0 }
}
),
SELECTCOLUMNS (
SUMMARIZECOLUMNS ( Dim_Prod[dim5], Dim_Prod[dim6] ),
"Top", "Affaires nouvelles",
"Index1", 2,
"Middle", Dim_Prod[dim5],
"Index2", RANK.EQ ( Dim_Prod[dim5], Dim_Prod[dim5], ASC ),
"Bottom", Dim_Prod[dim6],
"Index3", RANK.EQ ( Dim_Prod[dim6], Dim_Prod[dim6] )
)
),
"Index0", 100 * [Index1] + 10 * [Index2] + [Index3]
)
Output:
Sample measure:
SampleMeasure =
VAR Top = SELECTEDVALUE ( Header[Top] )
VAR Middle = SELECTEDVALUE ( Header[Middle] )
VAR BottomIndex = SELECTEDVALUE ( Header[Index3] )
RETURN
SWITCH (
TRUE (),
Top = "Nombre product", [NombreProductMeasure],
Top = "Affaires nouvelles" && BottomIndex <> 0, [DimensionMeasure],
Middle = "Total", [TotalMeasure],
Middle = "%Total", [%TotalMeasure]
)
This is pretty hacky though. Power BI may not be the best tool here.
Power BI is not a pixel-perfect data visualization tool, therefore, it is not possible to create customer headers using Built-in visualizations.
Therefore you have pretty much two options:
Build your own custom visualization, using Javascript, Python or R
Use a pixel-perfect tool like SSRS
I am using a relatively new version of Power BI for Report Server.
I have this simplified data:
ImaginaryData =
DATATABLE (
"Fruit", STRING,
"Colour", STRING,
"Amount", INTEGER,
{
{ "Apple", "Red", 10 },
{ "Apple", "Green", 5 },
{ "Apple", "Blue", 17 },
{ "Pear", "Red", 100 },
{ "Pear", "Green", 65 },
{ "Pear", "Blue", 5 },
{ "Orange", "Red", 12 },
{ "Orange", "Green", 8 },
{ "Orange", "Blue", 38 }
} )
I then create a Matrix of the data:
I want to order this Matrix by amounts in the Blue column i.e. the Fruit Orange should be at the top of the list.
With a Table visual I hover over a column header and can then order by that column but that functionality does not appear for a Matrix.
How do I workaround this issue? [using a Table is not a solution]
You need to add a sortcolumn to your table, that holds the sum of the blue amounts for that particular fruit. Like this.
You cannot do this in DAX (calculated column), because then you can't sort [Fruit] by [Sort], because [Sort] is allready indirectly sorted by [Fruit].
So you need to use the Query-editor. I recreated your table in an excel-workbook to import it. Then I used the following M script
let
SortColour = "Blue",
Source = Excel.Workbook(File.Contents("C:\Users\XXXXX\Documents\ImaginaryData.xlsx"), null, true),
ImaginaryData_Table = Source{[Item="ImaginaryData",Kind="Table"]}[Data],
#"Changed Type" = Table.TransformColumnTypes(ImaginaryData_Table,{{"Fruit", type text}, {"Colour", type text}, {"Amount", Int64.Type}}),
JoinTable = Table.SelectRows(Table.Group(#"Changed Type", {"Fruit", "Colour"}, {{"Count", each List.Sum([Amount]), Int64.Type}}), each ([Colour] = SortColour)),
#"Merged Queries" = Table.NestedJoin(#"Changed Type",{"Fruit"},JoinTable,{"Fruit"},"SortTable",JoinKind.LeftOuter),
#"Expanded SortTable" = Table.ExpandTableColumn(#"Merged Queries", "SortTable", {"Count"}, {"Sort"})
in
#"Expanded SortTable"
After loading this query, you can sort [Fruit] by [Sort] in the Data view (Sort by Column on the Modeling tab). Then recreate the matrix visual and sort the Fruit Column descending by clicking the triangle in the visual.
When you add row { Pear / Blue / 50 } to the table in excel and refresh in PowerBI, the matrix changes to this: