Is there a method to pass the formatting selection made in the PowerBI menu to a Deneb visual? - powerbi

See title, trying to pass a formatting selection (for example, percentage) to a Deneb visual instead of defining it in the vega / vega-lite JSON, and wanted to know if such a thing was possible.
Right now, we are just manually changing the formatting in the JSON

No, but Kerry Kolosko has a clever solution for this in her KPI charts that are in the sample file for the Deneb visual. In addition to passing in number fields, she also does formatting in DAX and passes in text to use with text marks.
DAX
Format Variance =
var a = calculate(DIVIDE(MAX('KPIsDATA'[Actual]),'KPITarget'[KPITarget Value])-1,'KPIsDATA'[Date]=MAX('KPIsDATA'[Date]))
var b = FORMAT(ABS(a),"#%")
Var c = IF(a>0,"▲ " , "▼ ")
Var d = IF(a>0," above target" , " below target")
Return
c & b & d
You could do an "Auto" format like this in DAX:
Format Actual =
VAR _number = SUM(KPIsDATA[Actual])
VAR _digits = 1
RETURN IF( ABS(_number) >= 1000000000, FORMAT(_number, "0,,," & IF(_digits > 0, ".", "") & REPT("0",_digits) & "B"),
IF( ABS(_number) >= 1000000, FORMAT(_number, "0,," & IF(_digits > 0, ".", "") & REPT("0",_digits) & "M"),
IF( ABS(_number) >= 1000, FORMAT(_number, "0," & IF(_digits > 0, ".", "") & REPT("0",_digits) & "K"),
FORMAT(_number, "0" & IF(_digits > 0, ".", "") & REPT("0",_digits) )
)
)
)

Related

Updating the values of variables in DAX

I need to change the value of variables in a switch in dax:
switch( true(),
condition1,
var test1 = 2
var test2 = 3
,condition 2,
var test1 = 4
var test2 = 5
,
var test1 = 7
var test2 = 6
)
I need to do this because I have to change massive number of variables depending on the condition, and I don't want to have a switch for every single variable.
I already tried this approach with switch and it works without variables.
It's like dax does not allow you to change the value of a variable after the first time it was assigned.
edit
hello, here is the example of what I want to achieve:
Value Daily Form =
SWITCH( true(),
// if both are selected
(ISFILTERED(tblAAA[AAA_name]) && ISFILTERED(tblBBB[BBB_name])),
var Target = sum(F_Daily_AAA_BBB[target])
var TotalPayments = sum(F_Daily_AAA_BBB[vlr_total_payment])
// if AAA is selected
, (ISFILTERED(tblAAA[AAA_name]) && not(ISFILTERED(tblBBB[BBB_name]))),
var Target = sum(F_Daily_AAA[target])
var TotalPayments = sum(F_Daily_AAA[vlr_total_payment])
// if BBB is selected
, (not(ISFILTERED(tblAAA[AAA_name])) && ISFILTERED(tblBBB[BBB_name])),
var Target = sum(F_Daily_BBB[target])
var TotalPayments = sum(F_Daily_BBB[vlr_total_payment])
// none is selected
,
var Target = sum(F_Daily_OR[target])
var TotalPayments = sum(F_Daily_OR[vlr_total_payment])
)
var result =
SWITCH(FIRSTNONBLANK(tblKPIs[Group_Name], tblKPIs[Group_Name]),
"Target (€)", IF(Target > 0, FORMAT(Target, "€ #,##"), if(SELECTEDVALUE('Calendar'[isWorkingDay]) = 1, "€ 0", BLANK())),
"Total Payments (€)", IF(TotalPayments > 0, FORMAT(TotalPayments, "€ #,##"), IF(SELECTEDVALUE('Calendar'[isWorkingDay]) = 1, "€ 0", BLANK())),
)
return result
in the beginning the code that I have to modify is:
Value Daily Form =
var Target = sum(F_Daily_OR[target])
var TotalPayments = sum(F_Daily_OR[vlr_total_payment])
var result =
SWITCH(FIRSTNONBLANK(tblKPIs[Group_Name], tblKPIs[Group_Name]),
"Target (€)", IF(Target > 0, FORMAT(Target, "€ #,##"), if(SELECTEDVALUE('Calendar'[isWorkingDay]) = 1, "€ 0", BLANK())),
"Total Payments (€)", IF(TotalPayments > 0, FORMAT(TotalPayments, "€ #,##"), IF(SELECTEDVALUE('Calendar'[isWorkingDay]) = 1, "€ 0", BLANK())),
)
return result
The only difference is the instead of 2 variables there are like 75,
and I don't want to make a switch for each of them because this will spaghettify the code.
Also I have to modify like 50 of this Metrics full of variables, so I need a quick copy paste solution like that switch, which worked in other cases in which the code didn't have variables.
Thank you for taking the time to help me.
It is indeed, because variables in DAX are actually constants. Variables are immutable. You can store the value in variable but you cannot change it later.
Here is a definition of the DAX variable from the documentation:
Stores the result of an expression as a named variable, which can then be passed as an argument to other measure expressions. Once resultant values have been calculated for a variable expression, those values do not change, even if the variable is referenced in another expression.
Find more in the documentation.
What exactly do you want to achieve by this?
Creating separate measure for each condition and then another measure with switch condition won't work for you?

generate a one-column table that contains hundreds of different categories using M or DAX

I need to split my products into a total of 120 predefined price clusters/buckets. These clusters can overlap and look somewhat like that:
As I dont want to write down all of these strings manually: Is there a convenient way to do this in M or DAX directly using a bit of code?
Thanks in advance!
Dave
With m-Query you can create a function. Open the query editor. Richt click and create empty query. Create function (ignore warning) and call it : RowGenerator.
Open advanced editor and past the following code:
let
Bron = (base as number, start as number, end as number) => let
Bron = Table.FromList(List.Generate(() => start, each _ <= end, each _ + 1), Splitter.SplitByNothing(), null, null, ExtraValues.Error),
#"Aangepaste kolom toegevoegd" = Table.AddColumn(Bron, "Aangepast", each Number.ToText(base) & " - " & Number.ToText([Column1]))
in
#"Aangepaste kolom toegevoegd"
in
Bron
This function creates a table where base is your first number and start, end the range.
Add another empty query, open the advanged editor and paste:
let
Bron = List.Generate(() => 0, each _ < 5, each _ + 1),
#"Geconverteerd naar tabel" = Table.FromList(Bron, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
#"Aangeroepen aangepaste functie" = Table.AddColumn(#"Geconverteerd naar tabel", "test", each RowGenerator(_[Column1], _[Column1] + 1, 5)),
#"test uitgevouwen" = Table.ExpandTableColumn(#"Aangeroepen aangepaste functie", "test", {"Column1", "Aangepast"}, {"Column1.1", "Price Cluster"}),
#"Kolommen verwijderd" = Table.RemoveColumns(#"test uitgevouwen",{"Column1", "Column1.1"})
in
#"Kolommen verwijderd"
This creates first a list of 5 rows, then it calls the previous made function for each row and the last step is to expend the rows and remove the not needed columns.
Enjoy:
You can create this bucket by DAX (New Table):
Table = SELECTCOLUMNS(
GENERATE(SELECTCOLUMNS(GENERATESERIES(0,10,1),"FirstPart",[Value]), SELECTCOLUMNS(GENERATESERIES(0,10,1),"SecondPart",[Value]))
,"Bucket", [FirstPart] & " - " & [SecondPart]
)
Table = SELECTCOLUMNS(
GENERATE(SELECTCOLUMNS(GENERATESERIES(0,9,1),"FirstPart",[Value]), TOPN([FirstPart], SELECTCOLUMNS(GENERATESERIES(1,9,1),"SecondPart",[Value]), [SecondPart],ASC))
,"Bucket", [FirstPart] & " - " & [SecondPart]
)

Pinescript - "Compare" Indicator with Percentage Change Function takes only last bar data

need help pls.
In Tradingview I use "Compare" to see the BTCUSDT vs. ETHUSDT on Binance and it's basically OK. But lines on the chart are too "up & down" and I want to see the SMA or EMA for those tickers.
I'm trying to do it step by step but I can't pass through the issue that my code takes only last calculated value in consideration and "percentage change line" starts from 0 with each new data. So it makes no sence. Meaning, my last data doesn't add upon prior value, but always starts from zero.
So, data (value) that comes out is good (same as when I put same tickers on Tradingview "Compare") but Tradingview "Compare" calculates / adds data on historical data, while my code starts from 0.
Here is the Pine script code:
//#version=4
study(title="Compare", shorttitle="Compare", overlay=false, max_bars_back=0)
perc_change = (((close[0] - open[0]) / open [0]) * 100)
sym1 = "BINANCE:BTCUSDT", res1 = "30", source1 = perc_change
plot(security(sym1, res1, source1), color=color.orange, linewidth=2)
sym2 = "BINANCE:ETHUSDT", res2 = "30", source2 = perc_change
plot(security(sym2, res2, source2), color=color.blue, linewidth=2)
Sounds like the delta between the two ROCs is what you are looking for. With this you can show only the 2 ROCs, but also columns representing the delta between the two. you can also change the ROC's period:
//#version=4
study(title="Compare", shorttitle="Compare")
rocPeriod = input(1, minval = 1)
showLines = input(true)
showDelta = input(true)
perc_change = roc(close, rocPeriod)
sym1 = "BINANCE:BTCUSDT"
sym2 = "BINANCE:ETHUSDT"
res = "30"
s1 = security(sym1, res, perc_change)
s2 = security(sym2, res, perc_change)
delta = s1 - s2
plot(showLines ? s1 : na, "s1", color.orange)
plot(showLines ? s2 : na, "s2", color.blue)
hline(0)
plot(showDelta ? delta : na, "delta", delta > 0 ? color.lime : color.red, 1, plot.style_columns)

Split row in multiple other rows in Power Bi based on a division of a number

In Power BI Desktop i have a table from an excel file and i want to split a row based on a division between the value of a specific column and a default number.
In more details lets assume tha we have a table like this :
if the default value we want to devide column Amount is 50,then the desirable result would be something like that :
Do you have any idea how can i implement that in Power query editor or with dax?
Thanks
Tested this in Power Query for Excel, but hopefully should work for you in Power BI too. If you create a function like:
divisionToList = (numberToDivide as number, numberToDivideBy as number) as list =>
let
divisionResult = numberToDivide / numberToDivideBy,
isResultValid = (divisionResult >= 0) and (Number.Mod(divisionResult, 1) = 0),
errorIfInvalid = Error.Record("Cannot create a list with " & Text.From(divisionResult) & " items", Number.ToText(numberToDivide) & " / " & Number.ToText(numberToDivideBy) & " = " & Text.From(divisionResult), null),
listOrError = if isResultValid then List.Repeat({divisionResult}, divisionResult) else error errorIfInvalid
in listOrError,
It should divide two numbers and return a list of length d in which each element is d (d is the result of the division). This list can then, in the context of a table, be expanded into new rows.
There is some basic error handling in the function for cases where the division yields a problematic number (since you can't have a list with, for example, 5.1 elements or -1 elements). You can change/remove this handling if necessary.
I think this code below takes me from your first image to your second image -- and hopefully will give you some idea on how to go about achieving this.
let
mockData = Table.FromColumns({{200, 400}, {"A", "B"}}, type table [Amount = number, Description = text]),
defaultValue = 50, // Not sure what logic is required for arriving at this figure, so have simply assigned it.
divisionToList = (numberToDivide as number, numberToDivideBy as number) as list =>
let
divisionResult = numberToDivide / numberToDivideBy,
isResultValid = (divisionResult >= 0) and (Number.Mod(divisionResult, 1) = 0),
errorIfInvalid = Error.Record("Cannot create a list with " & Text.From(divisionResult) & " items", Number.ToText(numberToDivide) & " / " & Number.ToText(numberToDivideBy) & " = " & Text.From(divisionResult), null),
listOrError = if isResultValid then List.Repeat({divisionResult}, divisionResult) else error errorIfInvalid
in listOrError,
invokeFunction = Table.TransformColumns(mockData, {{"Amount", each divisionToList(_, defaultValue), type list}}),
expanded = Table.ExpandListColumn(invokeFunction, "Amount")
in
expanded

Multiple IF Statements in DAX

I currently have Column Data formulated below in Power BI which I need for it to display in one column but replacing the "1" with a Text value being:
Orginal column formula:
Age (18-27) = IF(AND([Age]>17, [Age]<28),"1",BLANK())
Age (28-35) = IF(AND([Age]>27, [Age]<36),"1",BLANK())
Age (36-43) = IF(AND([Age]>35, [Age]<44),"1",BLANK())
Age (44-50) = IF(AND([Age]>43, [Age]<51),"1",BLANK())
Age (50+) = IF([Age]>50,"1 ", BLANK())
Output:
Age (18-27) = IF(AND([Age]>17, [Age]<28),"Age (18-27)",BLANK())
Age (28-35) = IF(AND([Age]>27, [Age]<36),"Age (28-35)",BLANK())
Age (36-43) = IF(AND([Age]>35, [Age]<44),"Age (36-43)",BLANK())
Age (44-50) = IF(AND([Age]>43, [Age]<51),"Age (44-50)",BLANK())
Age (50+) = IF([Age]>50,"Age (50+) ", BLANK())
I would like to have the formula display the data in one column where it is consolidating the Output formula (seen above) so I see the results in one column.
Just nest your IFs:
Age Group = IF(AND([Age]>17, [Age]<28),"18-27",
IF(AND([Age]>27, [Age]<36),"28-35",
IF(AND([Age]>35, [Age]<44),"36-43",
IF(AND([Age]>43, [Age]<51),"44-50",
IF([Age]>50,"50+", BLANK())
))))
You can use SWITCH() like this which is much cleaner than nested IFs:
Age Group = SWITCH(TRUE(),
AND([Age]>17, [Age]<28), "18-27",
AND([Age]>27, [Age]<36), "28-35",
AND([Age]>35, [Age]<44), "36-43",
AND([Age]>43, [Age]<51), "44-50",
[Age]>50, "50+", BLANK()
)
Source: https://community.powerbi.com/t5/Desktop/IF-or-SWITCH/m-p/167098#M72970
Another variation of the SWITCH TRUE pattern:
Age Group =
SWITCH (
TRUE (),
[Age] < 18, BLANK (),
[Age] <= 27, "18-27",
[Age] <= 35, "28-35",
[Age] <= 43, "36-43",
[Age] <= 50, "44-50",
[Age] > 50, "50+"
)
if you want to categorize the column value in the numerical range you can use below dax query.
bubble = IF(AND([no_of_days_pending]>=100, [no_of_days_pending]<200),150,
IF(AND([no_of_days_pending]>=200, [no_of_days_pending]<300),250,
IF(AND([no_of_days_pending]>=300, [no_of_days_pending]<400),350,
IF(AND([no_of_days_pending]>=400, [no_of_days_pending]<500),450,
IF([no_of_days_pending]>=500,600, BLANK())
))))