Dax and Power BI, default and slicer - date

I am trying to set up a report for users which by default shows today´s data.
But I would also like people with whom the report is share to be able to pick data, from the seventies to year 2043.
I currently managed to set up a report filter in DAX :
Date_Today_Default =
var currentrowdate = FORMAT('Date'[DATE], "dd/mm/yyyy")
var DateToday = FORMAT(TODAY(),"dd/mm/yyyy")
return
IF(DateToday = currentrowdate, "YES", "NO")
But I would like to give users the possibility to see default values when the report opens and slice the report as well. In this case, the users cannot change the date if "YES" is selected in my filter.
Is this doable in Power BI ?

You can leverage the ISFILTERED function to give you behavior like this.
Start by creating a new table that you will use for the values in your slicer
SlicerDate = SELECTCOLUMNS('Date', "Date",[Date])
And then go into your model view and create a relationship between your SlicerDate table and your Date table on the Date field.
Now make the following small changes to your dax.
Date_Today_Default =
var currentrowdate = FORMAT(Max('Date'[Date]), "dd/mm/yyyy")
var DateToday = FORMAT(TODAY(),"dd/mm/yyyy")
return
IF (isFiltered(SlicerDate[Date]), "YES", IF (DateToday = currentrowdate, "YES", "NO"))
Create a slicer visual and bring the date field from the SlicerDatetable into its values.
When you choose a date in the slicer, you will cause 'Date_Today_Default' to automatically show 'yes' for all records, letting all of them through the filter you have on your visual. But then they will be filtered down by the date you just selected in the slicer! So that gives your users control over the date selected.
When no date is chosen in the slicer, the 'Date_Today_Default' logic will fall into the IF DateToday = CurrentRow statement and only mark one row 'YES.' The filter you have on your visual will omit all the other records.
Hope it helps

Related

Get most recent month name with Power BI measure?

I have 2 columns, Status and Date. The "Status" column contains three values ('Past Due', 'Soon Due', 'Calibrated').
I would like to display the most recent month name calculated for each of these status categories separately. Specifically, I would like to create a table visual where we have 3 different columns with the names "Past Due", "Soon Due", and "Calibrated". These columns display the most recent month name for dates corresponding to each status category, as outlined in the screenshots below.
Sample Input:
Desired Output:
FORMAT([DateField], "MMM") is the key DAX function here.
I've outlined the 3 measures below that should give you the result you want. Replace "Table1" with your table name.
Past Due
Past Due = CALCULATE(FORMAT(MAX(Table1[Date]), "MMM"), Table1[Status] = "Past Due")
Soon Due
Soon Due = CALCULATE(FORMAT(MAX(Table1[Date]), "MMM"), Table1[Status] = "Soon Due")
Calibrated
Calibrated = CALCULATE(FORMAT(MAX(Table1[Date]), "MMM"), Table1[Status] = "Calibrated")
Measures in Table

Conditional WHERE clause in KDB?

Full Query:
{[tier;company;ccy; startdate; enddate] select Deal_Time, Deal_Date from DEALONLINE_REMOVED where ?[company = `All; 1b; COMPANY = company], ?[tier = `All;; TIER = tier], Deal_Date within(startdate;enddate), Status = `Completed, ?[ccy = `All;1b;CCY_Pair = ccy]}
Particular Query:
where ?[company = `All; 1b; COMPANY = company], ?[tier = `All; 1b; TIER = tier],
What this query is trying to do is to get the viewstate of a dropdown.
If there dropdown selection is "All", that where clause i.e. company or tier is invalidated, and all companies or tiers are shown.
I am unsure if the query above is correct as I am getting weird charts when displaying them on KDB dashboard.
What I would recommend is to restructure your function to make use of the where clause using functional qSQL.
In your case, you need to be able to filter based on certain input, if its "All" then don't filter else filter on that input. Something like this could work.
/Define sample table
DEALONLINE_REMOVED:([]Deal_time:10#.z.p;Deal_Date:10?.z.d;Company:10?`MSFT`AAPL`GOOGL;TIER:10?`1`2`3)
/New function which joins to where clause
{[company;tier]
wc:();
if[not company=`All;wc:wc,enlist (=;`Company;enlist company)];
if[not tier=`All;wc:wc,enlist (=;`TIER;enlist tier)];
?[DEALONLINE_REMOVED;wc;0b;()]
}[`MSFT;`2]
If you replace the input with `All you will see that everything is returned.
The full functional select for your query would be as follows:
whcl:{[tier;company;ccy;startdate;enddate]
wc:(enlist (within;`Deal_Date;(enlist;startdate;enddate))),(enlist (=;`Status;enlist `Completed)),
$[tier=`All;();enlist (=;`TIER;enlist tier)],
$[company=`All;()enlist (=;`COMPANY;enlist company)],
$[ccy=`All;();enlist (=;`CCY_Pair;enlist ccy)];
?[`DEALONLINE_REMOVED;wc;0b;`Deal_Time`Deal_Date!`Deal_Time`Deal_Date]
}
The first part specifies your date range and status = `Completed in the where clause
wc:(enlist (within;`Deal_Date;(enlist;startdate;enddate))),(enlist (=;`Status;enlist `Completed)),
Next each of these conditionals checks for `All for the TIER, COMPANY and CCY_Pair column filtering. It then joins these on to the where clause when a specific TIER, COMPANY or CCY_Pair are specified. (otherwise an empty list is joined on):
$[tier=`All;();enlist (=;`TIER;enlist tier)],
$[company=`All;();enlist (=;`COMPANY;enlist company)],
$[ccy=`All;();enlist (=;`CCY_Pair;enlist ccy)];
Finally, the select statement is called in its functional form as follows, with wc as the where clause:
?[`DEALONLINE_REMOVED;wc;0b;`Deal_Time`Deal_Date!`Deal_Time`Deal_Date]

Tableau Column Difference - as a dimension

I am looking for difference of two columns in Tableau. I have the formula with me.
IF ATTR([Valuation Profile]) = "Base" THEN
LOOKUP(ZN(SUM([Value])), 1) > - ZN(LOOKUP(SUM([Value]),0)) END
But I get it as a separate column in the columns sections. How do I get that in the rows section? Basically how to get the difference as a dimension?
Please see attached images of what I want and what I have. Apparently, I cannot upload my excel sheet and tableau worksheet here. So I have upload just the screenshots.
What I have - vs - What I want
Tableau Workbook
First off, there is no way that you can generate additional rows for your data in Tableau!
In your case however you could use a workaround and do the following:
Create a calculated field for BASE and one for CSA. The formula should
be IF [Valuation Profile] = 'BASE' THEN [Value] END and IF
[Valuation Profile] = 'CSA' THEN [Value] END respectively
Afterwards you can drag Measure Names onto your rows shelf and
replace the SUM([Value]) with your two newly created calculated fields
that should give you all three measures in different rows in your table
Reference: https://community.tableau.com/message/627171#627171
Use LOD expression to calculate the individual values first.
Create calculated fields 'BASE', 'CSA' and 'CSA-BASE' as below.
BASE:
{FIXED [Book Name]: SUM( if [Valuation Profile] = 'BASE' then Value else 0 end ) }
CSA:
{FIXED [Book Name]: SUM( if [Valuation Profile] = 'CSA' then Value else 0 end ) }
CSA-BASE
[CSA]-[BASE]
Solution

Yii Framework - Collecting Date Of Birth Using 3 Dropdown, Then Converting To Date Obj

In my database, I have a date of birth (dob) field that is of type date.
When I create model from my table, it creates one attribute as dob for
me.
So when I generate my form from my model, it has one field that can collect
the user's date of birth. What I want to have is to have 3 dropdown elements
each for day month and year. then when I submit my form, they all get bundle
up together as dd-mm-yyyy and get populated to my model attribute "dob"
At this point I can't figure out how to do it using Yii form since the model
gets passed to the view, how can I find a way to accomplish this. So to recap,
-I want to have only one field in my User table for dob as date type
-I want to have 3 dropdowns in my Yii generated form that at submit time they
form my dob and populate it in the $model->user_dob
That is really strange... I did a similar thing earlier today. I find that people don't use the date picker correctly so I prefer to use drop downs.
Declare virtual fields in your model for month, day, and year, add validation rules, then create a drop down for each.
Example of creating the drop down lists:
echo CHtml::activeDropDownList($model, 'month', $monthsArray);
echo CHtml::activeDropDownList($model, 'day', $daysArray);
echo CHtml::activeDropDownList($model, 'year', $yearsArray);
You need to fill the arrays with the months, days, and years you want to give as options. This seems to be outside the scope of your question but I'll include example functions for doing that at the end, just in case.
Then in your form controller, when you do:
$model->attributes = $_POST['User'];
those values should be added to $model->month, $model->day, and $model->year.
Then all you have to do is format it in the Date format like this:
$model->dob = $model->year . '-' . $model->month . '-' . $model->day;
and save the model.
--- extra: example of month, day, year arrays ---
These aren't really the best way of doing it, but for my purposes they have worked fine.
public function getMonthsArray()
{
for($monthNum = 1; $monthNum <= 12; $monthNum++){
$months[$monthNum] = date('F', mktime(0, 0, 0, $monthNum, 1));
}
return array(0 => 'Month:') + $months;
}
public function getDaysArray()
{
for($dayNum = 1; $dayNum <= 31; $dayNum++){
$days[$dayNum] = $dayNum;
}
return array(0 => 'Day:') + $days;
}
public function getYearsArray()
{
$thisYear = date('Y', time());
for($yearNum = $thisYear; $yearNum >= 1920; $yearNum--){
$years[$yearNum] = $yearNum;
}
return array(0 => 'Year:') + $years;
}

Dynamic grouping in crystal reports

So I have these 3 table/views in my database.
Table
id
template
View1 // the ids in this view have a corresponding id in table if template = 1
id
type1
View2 // the ids in this view have a corresponding id in table if template = 2
id
type2
So in my report, I want to select all the ids... and then group by template, and then group by type. I can do this for one View at a time by setting up the group to be either View1.type1 or View2.type2. But, I want it to group by View1.type1 if template is 1 and then I want it to group by View2.type2 if the template is 2.
So I made a forumla called type, and changed the group to that formula.. So I am first grouping by template, and then by type (my formula). If I set the formula for type as below:
formula = {View1.type1}
Then it works as expected and I see the correct grouping. It also works if I only do it for View2.type2.
However, when I do this:
if {Table.template} = 1
formula = {View1.type1}
else
formula = {View2.type2}
This returns no data for my grouping. Even if I do this:
if 1 = 1
formula = {View1.type1}
else
formula = {View2.type2}
This also returns no data. How is dynamic grouping supposed to work? I am missing something? I guess at the worst case I can make another view in my database or even use subreports... but I was hoping to have it work like this... I greatly appreciate the help guys!...
UPDATE:
So I can do formulas such as this one:
if {View1.type1} = "" then
formula = "[Undefined]"
else
formula = {View1.type1}
end if
It looks like I only have issues when I try to use a formula with the 2 views...