Home Power BI
Category:

Power BI

When it comes to writing, I have the least trust in my writing skills. I always wanted my blog to sound more like a personal journey than some docs, whenever I look back mostly it doesn’t. I hope at least this post will sound like a journey. I am not an expert with visualizations; this post is all about my thought processing when I designed this template. Presentation slides or Power BI templates are like babies, you like yours. So, I would really like to hear your feedback on my approach. Feel free to use the comments section or send an email to Prathy@outlook.com

For me, one of the hidden pleasures of working with Power BI is working with colours and choosing the layouts. Of course, primary usage is the ability to design something to promote data-driven decisions in an organisation. I am not encouraging anyone to splash lots of colours on to your report. Designing reports in Power BI remind me of my Digital scrapbooking days. An empty page looks like a blank canvas except, the gesso smell. While I work with business obviously I follow branding and give importance to the user input; when it comes to my templates like my previous blog post “How to find all Power Users” and “POWER BI TEMPLATE TO DOCUMENT THE POWER BI SERVICE“, it gets difficult I keep on change things. This Template is still an unfinished project. I don’t think it will ever get finished. However, I learned a lot while creating this one. Hopefully, I will use my learnings in the future blog posts.

Let’s look at the first Page:

I usually create background images, decide the layout and then use that image as back ground in Power BI. I used image background for this template too. The background colour and left pane are part of image background. I could use frame and all other things as an image as well. That will look and work better. Although for this template, I kind of went with the flow and it was too late to change to the image. Frames: The sole reason behind the Frames was just because I like Frames. Anyone who worked with Power BI can easily guess why I went for the frame which has a lil gap on the top. It’s because of that little bar you get on top of every visual in Power BI  https://ideas.powerbi.com/forums/265200-power-bi-ideas/suggestions/12247677-optionally-remove-focus-mode-box

I tried following a pattern with the look and feel of below image

Most of the times, I used left pane for slicers or any valuable information I wanted to show. I kind of followed inverted pyramid concept, but excluding the left pane, I suppose. Colours: I have various data categories and I wanted to differentiate all those categories with different colours. I looked for popular colour combos and went for the colours I used in the below image. You can find popular colour combos here – https://www.colorcombos.com/popular-color-combinations/2

Pushpin affect, that’s just to show off my digital scrapbooking tact. I used treemap visual and layered that with a pushpin image.

The left pane, there is a lot of information here. Bottom table is something unnecessary, I needed something to fill up that space so I added by creating a calculated table. It’s a bit misleading or needs a better naming. It has Failed, Failures
Today and I also have a dynamic title with failure information. I was duplicating the same content which was not a wise choice.

Next comes the drill through affect: I added a drill through icon to show users that it has Drill Through functionality. Not sure that’s doing any justice. When I googled for drill through, that was the first image came up in my search feed also it was a perfect image to add a background colour. As I wanted to follow my pattern, so I went for colours which were good to show black foreground. When the user uses navigates to drill through page, that page will have the drill through icon background colour theme. Each frame which has some characters are separate table visuals. I formatted them to show like labels.

First, I changed Column Headers Font colour and Background colour to the background I used in the left pane, next increased Row padding to 11 so it aligns nicely with my drill icon. Then bottom to top, I formatted them to send Back, so when the user right clicks to choose drill through it will not interfere. Only when a user clicks on the table, they will be able to see the column header interfering with previous one otherwise it looks nice. Then I used a ribbon chart to show the number of refreshes and number of failures by Date to get an overview. Another pattern I followed is on each page, I added Last refresh data time, obviously to show when was the last time report refreshed.

rest of the pages are pretty much similar apart from few extra affects.

Page Workspaces:

Noticeably assorted colour pattern. Then, I used Bookmarks functionality.

I added an effect like clicking check boxes. Basically, I had several visuals on this page, I created three bookmarks by selecting the visuals I wanted to show. Then on each relevant bookmark, I went for ticked checkbox image than an unticked one. So when users access it using Power Bi service, it will look like a proper checkbox. You can find more information about bookmarks here – https://docs.microsoft.com/en-us/power-bi/desktop-bookmarks

Page Datasets:

Two noticeable approaches here are, using images and numbers to highlight some measures. I used https://www.iconfinder.com/ to get all my icons and I think, they do stand out quite well. Then, I used slicers as a lil button with full frame and I edited interactions to work only with the chart. I also separated them with other visuals using lines so it kind of explains they belong to chart only.

Page Gateways:

I have a lot of placeholders here. I do want to add more information from Gateway Data source query. One noticeable thing I did here is, in the Gateway contact information, I was showing a green circle to show it is live.

I am using an image reference here. I created a measure with following DAX

Status = IF(Gateways[Gateway Status]="Live","https://upload.wikimedia.org/wikipedia/commons/0/0e/Ski_trail_rating_symbol-green_circle.svg",Blank())

Then, I updated table properties to use image height as 24, 24 is the minimum in the current version.

All rest of the pages are similar, nothing too exciting. Hope it gives some ideas to someone out there. Let me know what you think about it.

Prathy

2 comments
2 FacebookTwitterPinterestEmail

If you are the goto person for Power BI in your organisation, then I am sure at least once you may have been asked about Power BI users question, I get asked many times. Of course, I can go to Power BI Service, check each workspace and Power BI Apps and see who has access to what; not a productive way when I am working with many workspaces. Or as I blogged before, I can use Power BI API to get all users data, probably a better way when I am working with many workspaces. If I share content using Power BI Apps and given access using security group, It gets difficult to understand who has access to what, who is a member of what groups.

If you have enough rights, you can view users information and members of which groups in Office 365 portal, again not a very productive way.  However, by using Power BI and Graph API, we can create a report to show all users information. I will be able to see all users who have Power BI license. I can slice this data by Location, Team and many more. It’s not only Power BI; I can view all other licenses. For example, Power Apps and Microsoft Flow. Now I can easily see who has access and monitor users and license, If you want to know about Graph API and how to use it with Power BI, check out my earlier blog post – Access Microsoft Graph API using Power BI.

The Template:

By using Microsoft Graph API, I created a template, where you can see all users, their groups and their license details. You can download the template here – https://1drv.ms/u/s!Avm7gbgZtlMlqB12UF4WXFGzzgXk .

Using template:

When you open the Pbit file, you will see a pop up window with two parameters.

Enter these values Graph API URL = https://graph.microsoft.com/  and Graph API  Version =  beta. After a while, based on size, the template should get populated with data.  If you want to understand the logic behind the template, carry on reading …

10 comments
2 FacebookTwitterPinterestEmail

Recently I came across Microsoft Graph API through Power BI Custom data connectors documentation. Amazed by the amount of information provided by this API. I didn’t find an appropriate use case right away, but later I found a very interesting one “a Power BI template to find all Power BI users and their Groups”. In this post, I am going to cover a bit about Graph API and how to extract data into Power BI, more like an antecedent for my next blog post.

Microsoft Graph API is a RESTful Web API; we can use this to get access to data from the Microsoft Cloud services like Active Directory, Sharepoint, Onedrive and much more. You can find all documentation here – https://developer.microsoft.com/en-us/graph/docs/concepts/overview. What one of the main benefits of this API compares to many other Microsoft API’s is it has a single endpoint https://graph.microsoft.com.  I could use this as a data source in my Power BI Desktop, publish the Model to Power BI service and schedule the data source. Currently, we can not schedule Power BI custom data connectors, but once this feature gets implemented, I think it is better to access Graph API using custom data connector as documented here –  https://github.com/Microsoft/DataConnectors/tree/master/samples/MyGraph

For now, if you want you can extract data from this API using OData Connector. The best place I found useful to start with Microsoft Graph API is the Graph Explorer – https://developer.microsoft.com/en-us/graph/graph-explorer

Microsoft Graph now supports two versions. I found beta useful as it has more data than version v1.0. You can switch between versions easily in Graph explorer and see what data available in each version. A user needs the right level of permission to get access to the correct data, and these permissions are at very granular level. I don’t think; I understood permissions very well if you want you can find permissions information here – https://developer.microsoft.com/en-us/graph/docs/concepts/permissions_reference

You can use the Graph Explorer, to see what data is available to view, modify permissions or just to get an overview of the API.

Access Microsoft Graph API using Power BI

Microsoft Graph has a unified OData endpoint, so I can just use this as OData Feed data source connection, and with few simple clicks, I could import data int Power BI Desktop.

I just copied the API URL from Graph Explorer, pasted in the OData feed data source. I used organizational account authentication. That’s all; I can see all users 🙂

You can download a simple template here – https://1drv.ms/u/s!Avm7gbgZtlMlqCk02OFlwX2ANOfs 

Summary:

This is a fascinating data source, and it gets more interesting with Power BI. As I mentioned earlier, I started playing with this API to get an overview of all Power BI users available. One can get a lot of insights from this data source, hope you find it useful.

Prathy 🙂

 

9 comments
1 FacebookTwitterPinterestEmail

SharePoint is a killer; front end looks nice and beautiful. Once you start exploring behind the screens, that is when it shows the true colours. Whenever you view a list in the SharePoint mostly, you are looking at a SharePoint list View, so it does not show many underlined columns, not even columns with their real names. When you use SharePoint list as a source for a Power BI model, apparently it extracts all the information from the backend, which means you see far more columns than you expected and most of the times column names look obscure.

For example, look at following columns, how anyone can interpret s6hu meant to be column Jan-17

Original Name  Display Name
Title AI Number
cybf Aug-17
Notes1 Notes
s6hu Jan-17
a6ua Feb-17
dnxw Mar-17
uv0g Apr-17
yqkw May-17
ContentType Content Type

If you have faced this problem, want a quick fix, then just download this template. It should rename columns with display names wherever possible, or you may want to read rest of the post, you will know how I created the Template.

SharePoint List Power BI Template

Step 1:

First I created two parameters one for SharePoint URL and one for SharePoint list ID.

[ Description = "Sharepoint List URL" ] SPListURL = null meta [IsParameterQuery=true, Type="Any", IsParameterQueryRequired=true];
[ Description = "Sharepoint List ID" ] ListID = null meta [IsParameterQuery=true, Type="Any", IsParameterQueryRequired=true];

If you are not sure about getting List ID follow this URL or download this template – Get Sharepoint List ID’s. I used following M Code in the Get Sharepoint List ID’s template.

#"SharepointList IDs" = let
    Source = SharePoint.Tables(SPListURL, [ApiVersion = 15])
in
    Source;

Bingo, you get all lists from the given SharePoint site.

Step 2:

Once I know the URL and ID, I created another query with following M Code

 SPList = let
//SPListURL is the URL of sharepoint list
Source = SharePoint.Tables(SPListURL, [ApiVersion = 15]),
/* ListID is the ID of Sharepoint list */
SPList = Source{[Id=ListID]}[Items],
#"Keep only FieldValuesAsText column" = Table.SelectColumns(SPList,{"FieldValuesAsText"}),
RecordColumnNames= Record.FieldNames(#"Keep only FieldValuesAsText column"{0}[FieldValuesAsText]),
ExpandColumn= Table.ExpandRecordColumn(#"Keep only FieldValuesAsText column", "FieldValuesAsText",RecordColumnNames)
in
ExpandColumn;

I navigated to the list I want to import data from, chose FieldValuesAsText column only. FieldValuesAsText has text representation of all list data. Then I used function Record.FieldNames to get all values from Record. This makes it easy for future proofing. If any user changes columns in the future, Model will be clever enough to know the new column names. Then Expanded FieldValuesAsText column with the RecordColumnNames list.

Step 3:

I referenced the previous query and this time extracted all available column names using function Table.ColumnNames. Later I am going to use this query to join the query from Step 4.

 ListColumnNames = let
    Source = SPList,
    ColumnsNames= Table.ColumnNames(Source ),
    #"Converted to Table" = Table.FromList(ColumnsNames, Splitter.SplitByNothing(), null, null, ExtraValues.Error)
in
    #"Converted to Table";

Step 4:

I created another query with the same source as step 1 but in this query, I navigated to field ContentType and then Fields. Apparently, this is where SharePoint hiding all its secrets 🙂

 Title = let
    //SPListURL is the URL of sharepoint list
    Source = SharePoint.Tables(SPListURL, [ApiVersion = 15]),
    /*    ListID is the ID of Sharepoint list       */
    SPList = Source{[Id=ListID]}[Items],
    #"Removed Other Columns" = Table.SelectColumns(SPList,{"ContentType"}),
    ContentType1 = #"Removed Other Columns"{0}[ContentType],
    Fields = ContentType1[Fields],
    #"Removed Other Columns1" = Table.SelectColumns(Fields,{"EntityPropertyName", "InternalName", "StaticName", "Title"})
in
    #"Removed Other Columns1";

Step 5:

I think this step is where the important stuff is.

First, I did a left outer join with ListColumnNames (Step3) and Title (Step 4) on EntityPropertyName and Column1. Then expanded and removed unnecessary columns. I ended up with Origin Name and Title (Display Name name in the SharePoint list). Then I created a custom column with a List of original column names.

In step 6, I want to rename all columns based on the display columns, but if we have duplicate columns or if there is already a column with the same name, Table.RenameColumns function will fail.

So I created a custom column with a list of original column names to see if the column already exists. Then I used List.Contains to check if the column already exists and I filtered out all columns which already exists.

In the end, I left again with Original Name and Title but excluded duplicates and columns already exist in the SharePoint List, then I transformed rows to list using Table.TransformRows function.

RenamedColumns = let
    Source = Table.NestedJoin(ListColumnNames,{"Column1"},Title,{"EntityPropertyName"},"Title",JoinKind.LeftOuter),
    #"Expanded Title" = Table.ExpandTableColumn(Source, "Title", {"EntityPropertyName", "Title"}, {"EntityPropertyName", "Title.1"}),
    #"Renamed Columns" = Table.RenameColumns(#"Expanded Title",{{"Column1", "Original Name"}, {"Title.1", "Title"}}),
    #"Filtered Rows" = Table.SelectRows(#"Renamed Columns", each ([EntityPropertyName] <> null)),
    #"Removed Other Columns" = Table.SelectColumns(#"Filtered Rows",{"Original Name", "Title"}),
    AddListColumns= Table.AddColumn(#"Removed Other Columns", "Custom", each Table.ColumnNames(SPList)),
    CheckNameAlreadyExists = Table.AddColumn(AddListColumns,"TF",each List.Contains([Custom],[Title])),
    #"Filter already existing column names" = Table.SelectRows(CheckNameAlreadyExists, each [TF] = false),
    #"Removed Duplicates" = Table.Distinct(#"Filter already existing column names", {"Title"}),
    #"Removed Other Columns1" = Table.SelectColumns(#"Removed Duplicates",{"Original Name", "Title"}),
    MakeAList= Table.TransformRows(#"Removed Other Columns1", Record.FieldValues)
in 

    MakeAList;

Step 6:

The final step for the template!

Again I referenced my query from Step1, SPList. Then used function Table.RenameColumns to rename columns as display names.  That’s all! Your lovely SharePoint list is ready for the transformations and analysis.

 #"Sharepoint List" = let
    Source = SPList,
    RenameColumns= Table.RenameColumns(Source,RenamedColumns,MissingField.UseNull)
in
    RenameColumns;

Summary :

Lately, one slogan I have heard among people is “We are in digital transformation”. The first place they start or probably the easiest place to start is moving all important Excel workbooks to SharePoint Online then analyse them using Power BI. But it was not that simple to make it work, at least not for me. I could write stories about it. I hope I will find some time to write about my adventures of successfully scheduling a Power BI Model with SharePoint list data source…

Sometimes you face irritating problems, If a user changes a column, it breaks the model, because of renaming columns to friendly names as it looks like in the Sharepoint List. I can’t imagine the frustration of a user when a model brakes with a name change error. Luckily I did not work with really wide lists. But with the very first model I designed with SP list, I realised this issue. My best friend google betrayed me, and I left with no choice other than exploring all the metadata I extracted from Sharepoint List.

This Template helped me to speed up the process. Now I don’t need to create Models for users; if they want they can design their own models, the way they want. It’s a win win 🙂

It’s not only me; there are other are others had similar issues

https://community.powerbi.com/t5/Desktop/Column-Name-Changes-when-Sharepoint-list-is-imported-in-PBI/td-p/183814

https://community.powerbi.com/t5/Issues/Sharepoint-list-connector-pulling-in-incorrect-column-names/idi-p/138924

I hope this helps someone out there. This is just a workaround; it worked great for me, hope it works for you too 😊

Sharepoint Power BI Template  – https://1drv.ms/u/s!Avm7gbgZtlMlqCHE55X7yJaDuBx0

Until next time,

Prathy 🙂

 

6 comments
2 FacebookTwitterPinterestEmail

(Ideally, I would like to do this as a Power BI custom data connector. I have tried, for some reason, my Visual Studio has been crashing when I click on connect to PBI Service using OAuth2. Once I succeed, it would become another blog post)

Why Calling Power BI service using Power BI Desktop?

We all know Power BI is a great tool and easily adaptable. Using Power BI Desktop and service, we can create models then we can publish or save them to Power BI Service. In service, we have workspaces, dashboards, reports, datasets, workbooks and apps; Power BI users create and/or access all these features based on their access levels. Which means all your users will be creating and/or accessing content from Power BI service. Which is great, but how can I answer questions like below:

  • Number of workspaces
  • Who has access to that particular workspace and their level of access
  • Number of Dashboards
  • Number of Reports
  • Dataset Last Refresh time
  • Average refresh time of X data set? ( You can plan, do you need premium or not based on this value)
  • How many Gateways ( For me, it’s not working at the moment)

And much more

Of course, I can get this information by going to Power BI service but how about getting answers to all those questions in one report.With extensive Power BI documentation, we know we could use Power BI API to Embedded Power BI reports or do data refresh. So I thought to call same Power BI API using Power BI Desktop to get the information I need for documenting my Power BI.

Calling Power BI service using Power BI Desktop

Before we dwell into this, let’s understand my approach for API Access. So when using Power BI API, the user will be able to see whatever they have access to. When a user creates a workspace in Power BI mean they are creating an office 365 group, which means they are creating loads of things in Office 365. I will talk more about this in another blog post. For now, just assume I have an SA User. The only user who can create workspaces, which means this user has access to every single workspace in my Power BI tenant. Instead of using an OAuth authentication, I am using the hard coded username and password for my API calls. As I mentioned earlier, I will talk more about Power BI workspaces and my so-called SA User in another blog post (Power BI publishing Strategy)

To call Power BI API, first I need to register an application for Power BI. You can create an application using this URL – https://dev.powerbi.com/apps. You can find more information about how to create and edit an App here – https://powerbi.microsoft.com/en-us/documentation/powerbi-developer-register-app/.

Don’t forget to save your Client ID and Client Secret safe; I still don’t know how to find client secret using Azure Portal (Maybe I have not looked well enough!)

Then in Power BI Desktop, I created two parameters one for Client ID and one for Client Secret. Next, I created a query called getToken with following M

GetToken:

let
    //App Details
    client_id = ClientID,
    client_secret=ClientSecret,

    //Authentication
    
    //URI's
    redirect_uri = "http://localhost:13526/redirect",
    token_uri = "https://login.windows.net/common/oauth2/token", 
    authorize_uri = "https://login.windows.net/common/oauth2/authorize",
    resource="https://analysis.windows.net/powerbi/api",
    
    //User Details  
    username="xxxxxxxxxxxxxxx.com",
    password="xxxxxxxxx",
    

   tokenResponse = Json.Document(Web.Contents(token_uri,          
                                [
                                    Content=
                                    Text.ToBinary(Uri.BuildQueryString(
                                    [
                                        client_id = client_id
                                        ,client_secret=client_secret
                                        ,username=username
                                        ,password=password
                                        ,resource=resource
                                        ,grant_type = "password"
                                        ,redirect_uri = redirect_uri
                                    ]))
                                    ,Headers=
                                        [Accept="application/json"]
                                        , ManualStatusHandling={400}
                                ])),
                                access_token = tokenResponse[access_token],
    token = tokenResponse[access_token]
in
    token

By using above query, I get an access token to call Power BI API using the given user access details. Then it’s a matter of calling various Power BI API GET operations. There is a plenty of documentation available, but Power BI Apiary was most useful one for me. By going to http://docs.powerbi.apiary.io/#introduction/what-can-i-do-with-the-power-bi-api? You can quickly see different operations you could do with Power BI API. I want to start with workspaces.

List all Groups / List all Workspaces:

Once up on time Workspaces were called Groups, may be that’s why in API they are still called Groups. The GET call for Groups is https://api.powerbi.com/v1.0/myorg/groups. I created a query called Workspaces with following M Code to get workspaces data.

let
    getgroups_uri ="https://api.powerbi.com/v1.0/myorg/groups",
    GetGroups = Json.Document(Web.Contents(getgroups_uri, 
                [
                Headers=
                    [
                    Authorization="Bearer "& refToken
                    ], 
                ManualStatusHandling={400}
                ]
                )),
    value = GetGroups[value],
    #"Converted to Table" = Table.FromList(value, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
    #"Expanded Column1" = Table.ExpandRecordColumn(#"Converted to Table", "Column1", {"id", "isReadOnly", "name"}, {"id", "isReadOnly", "name"}),
    #"Renamed Columns" = Table.RenameColumns(#"Expanded Column1",{{"id", "Workspace ID"}, {"name", "Workspace name"}})
in
    #"Renamed Columns"

List all Datasets:

Next all datasets under each workspace. Datasets GET request need GroupID query parameter. Hence I created a function called fnGetdatasets with following M Code

(groupid as text)=>

let
getdatasets_uri =" https://api.powerbi.com/v1.0/myorg/groups/"&groupid&"/datasets",

 GetGroups = Json.Document(Web.Contents(getdatasets_uri ,

 [

 Headers=

 [

 Authorization="Bearer "&getToken

 ],

 ManualStatusHandling={400}

 ]

 )),

 value = GetGroups[value],

 #"Converted to Table" = Table.FromList(value, Splitter.SplitByNothing(), null, null, ExtraValues.Error)

in

 #"Converted to Table"

Then created a new query with following M code to get all datasets under each workspace.

let

 Source = Workspaces,

 #"Invoked Custom Function" = Table.AddColumn(Source, "fnDatasets", each fnDatasets([id])),

 #"Expanded fnDatasets" = Table.ExpandTableColumn(#"Invoked Custom Function", "fnDatasets", {"Column1"}, {"Column1"}),

 #"Expanded Column1" = Table.ExpandRecordColumn(#"Expanded fnDatasets", "Column1", {"id", "name", "addRowsAPIEnabled", "configuredBy", "isRefreshable", "isEffectiveIdentityRequired", "isEffectiveIdentityRolesRequired", "isOnPremGatewayRequired"}, {"id.1", "name.1", "addRowsAPIEnabled", "configuredBy", "isRefreshable", "isEffectiveIdentityRequired", "isEffectiveIdentityRolesRequired", "isOnPremGatewayRequired"})

in

 #"Expanded Column1"

All Reports:

Again Reports API needs Workspace ID to get reports. There are two ways you can get Reports data. However, I went for the one who needs GroupID. I created function and then called that function for each GroupID

fnReports Function:
(groupid as text)=>
let
getdatasets_uri ="https://api.powerbi.com/v1.0/myorg/groups/"&groupid&"/reports",
GetGroups = Json.Document(Web.Contents(getdatasets_uri , 
[
Headers=
[
Authorization="Bearer "&refToken
], 
ManualStatusHandling={400}
]
)),
value = GetGroups[value],
#"Converted to Table" = Table.FromList(value, Splitter.SplitByNothing(), null, null, ExtraValues.Error)
in
#"Converted to Table"

Reports Query:

let
getgroups_uri ="https://api.powerbi.com/v1.0/myorg/groups",
GetGroups = Json.Document(Web.Contents(getgroups_uri, 
[
Headers=
[
Authorization="Bearer "& refToken
], 
ManualStatusHandling={400}
]
)),
value = GetGroups[value],
#"Converted to Table" = Table.FromList(value, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
#"Expanded Column1" = Table.ExpandRecordColumn(#"Converted to Table", "Column1", {"id", "isReadOnly", "name"}, {"id", "isReadOnly", "name"}),
#"Renamed Columns" = Table.RenameColumns(#"Expanded Column1",{{"id", "Workspace ID"}, {"name", "Workspace name"}}),
#"Invoked Custom Function" = Table.AddColumn(#"Renamed Columns", "fnReports", each fnReports([Workspace ID])),
#"Expanded fnReports" = Table.ExpandTableColumn(#"Invoked Custom Function", "fnReports", {"Column1"}, {"Column1"}),
#"Expanded Column2" = Table.ExpandRecordColumn(#"Expanded fnReports", "Column1", {"id", "modelId", "name", "webUrl", "embedUrl", "isOwnedByMe", "isOriginalPbixReport", "datasetId"}, {"Report.id", "Report.modelId", "Report.name", "Report.webUrl", "Report.embedUrl", "Report.isOwnedByMe", "Report.isOriginalPbixReport", "Report.datasetId"})
in
#"Expanded Column2"

Like this, I can also get List of users under each workspace, Dataset refresh history. In the documentation I can see, I can get all gateways and much more information about Gateways – https://msdn.microsoft.com/en-us/library/mt809129.aspx. I think this feature is not available yet, as it is not shown in the apiary and I get an error when I call this service.(Something for future!)

A sample report below:

Summary:

I have to admit, it was not easy. The main difficulty for me was too much information out there. I struggled to understand which API to use, what redirect URL and headers etc. I don’t know much about API’s. All these headers and scopes are very new to me; I still don’t understand why or how they work. So part of the problem was me and part was various documentation about Power BI Embedded. However, at the end of the day, I learned something new. By calling API, I can answer many questions with one refresh in Power BI Desktop.

This post is already too long; I will create a nicer looking template with all queries and post it soon. It’s pretty difficult to get much time to blog during school summer holidays. I hope I create a template soon and also hope this gives some ideas and help someone out there.

Some References for Power BI API :

https://msdn.microsoft.com/en-us/library/mt147898.aspx

http://docs.powerbi.apiary.io/#introduction/what-can-i-do-with-the-power-bi-api?

https://powerbi.microsoft.com/en-us/documentation/powerbi-developer-get-azuread-access-token/

Till next time,

Prathy 🙂

13 comments
2 FacebookTwitterPinterestEmail

So far I have seen many Power BI usage metrics demo’s or read blog posts about usage metrics, but not actually looked in detail. Recently I started exploring App Workspaces to create some standards for how to design, publish and collaborate with Power BI reports. In that process, I thought to look at Report Usage metrics by presuming I will be able to get Power BI Reports metadata. I don’t think it benefited for what I was looking for, but I saw Report GUID!  I remember seeing this before when I was working filters in Power BI Report URL.

By looking at the URL I thought, I could use the URL for Click Through and Drill Through.  So I started exploring to see if there is any possibility of Drill Through functionality. In a nutshell, Yes! You can just point to a report URL from Power BI Report and it will open that report when you click on it, like Click Through. If you also give filters like mentioned here – https://powerbi.microsoft.com/en-us/documentation/powerbi-service-url-filters/, it can work as Drill Through too. That gives you an idea, however, If you want to see what other things I explored or did with this then carry on reading…

Drill Through Reporting in Power BI:

 

By looking at my Report URL, I can see It formed with few Id’s, which looks like GroupID, ReportID and ReportSection. Getting GroupID and ReportID is doable but what is this ReportSection? Report Section, it does have a pattern, the very first tab is Report Section, the second one is Repost Section 1 and goes on. Oh Yeah, I also understood that I better call each tab as Report Sections than tabs. (Group ID are Office 365 Group Id’s, and Report ID’s are available through Power BI Usage Metrics)

Even if you understand Report section was based on the position, it could be a bit tedious process to figure out the position of Report Section. It is not actually the position; it’s based on which section created when. At this point, I could easily guess, this info hidden somewhere in Power BI files.

Report Section:

One of my good friend Malden, who is also very talented, once showed me how easily he was getting content from Excel by renaming as zip, he also mentioned it works with many Microsoft applications. So I thought to rename Power BI file to Zip file. For my convince after unzipping, there was a welcoming folder called Report.

Inside Report folder, there were two files

By opening these files in Notepad, I noticed Layout was a Json file type, and  LinguisticSchema was XML. Also, these two files have some information about Reports.

One useful tool I knew which could pull data from these file types is Power BI. Naturally, I renamed files with respective file types and started importing into Power BI.

For both of them, I got an error. I thought something wrong with the file format. Then I checked both files with XML Format Checker and Jason Format checker. Both of them were fine. However, when I copied content from those files and saved as new copy using Notepad, they were ok to import into Power BI desktop. (No idea why. I didn’t want to dig deeper, I must have done something wrong).

 

So, once I imported data into Power BI, I found a new terminology called POD. Each Report section was called like PODx. It might be some programming terminology, which I don’t know. Whatever, after bit of clean up this is how data in my queries look like

I can join these two queries to get which Report belongs to what section.

At this stage, I can easily create URL using GroupID, ReportID and RepostSection. To make it bit more interesting (at least for me ), we can use query parameters to get ReportID and GroupID.

Using query parameters to create Drill Through URL:

I created two parameters one for GroupID and one for ReportID. Then I created two queries by returning those parameter values so that I can use them for my Drill Through URL and edit parameters from the designer.

Then I created a calculated column under Layout Query (Query with Report Section information)

ReportURL = "https://app.powerbi.com/groups/"&MAX(GroupID[GroupID])&"/reports/"&MAX(ReportID[ReportID])&"/"&'Layout'[ReportSection]

Another calculated column as follows to form a full URL with filters

RegionURL =

Var RegURL = CALCULATE(MAX(Layout[ReportURL]),Layout[Report Name]="Region")

return

SUBSTITUTE(RegURL&"?filter=Schools/Region eq '"& CALCULATE(MAX(Schools[Region]))&"'"," ","%20")



Now I have a drill through URL for each Region.

And, I can create a report like below to drill through on each Region

And it works 🙂

But what if you want to drill through to an app?

Drill through to a published App:

APP Workspaces URL – https://app.powerbi.com/groups/me/apps/8a9deb71-100d-4c43-9585-5d7738d92caa/reports/18728640-81c2-4d24-8dbf-436a51d5416a/ReportSection

In the above URL, we have AppID and ReportID; ReportID is same as App Workspaces. Just instead of GroupID, we need to use AppID and small changes in the URL. I didn’t manage to find a way to query AppID other than copying from URL.

So to the PowerBI Model, we can add another Query Parameter saying APPID, and change Drill Through URL based on the sharing.I don’t want to make this post any longer If you really want, I am sure you can write that DAX expression.

Summary:

Now the basic question, does anyone want to do it? May be No! One benefit I can see is, when Microsoft bring Drill through functionality into Power BI, it could be limited to work with in a model or with in a Workspace. But this way we can point to any URL in any workspace. Another benefit for me, it is nice to know how Power BI Service URL was structured and few other things like Report folder in Power BI file and knowing Report Section terminology 🙂

In summary, if you have a burning Drill through the problem, then this could be handy. Few quick points, works only in Power Bi Service. Filters does not work with Public publish. There is no Back button like we expect with any drill through functionality. You can point to any report in any workspace. When you click on the URL, it opens a new window/tab for each URL. It was slow for me but it could be just my internet connection. If you have more than one report, then you can use Usage Statistics and get ReportID for all reports. I am sure there must a way to get Office 365 group ID’s using Power Shell.

To be frank, very soon Microsoft is going to release Drill through functionality, so there is no point of going through all this pain other than if you love looking into Power BI files 🙂

 

Prathy 🙂

5 comments
1 FacebookTwitterPinterestEmail

Recently one of my business users came to me asking “how can I get a Clickable Card in Power BI”? He wants a card where he can show the measured value, but when he clicks on that, he wanted to cross filter other visuals. To be fair, A valid ask, but not something I have done before. After deep thought, I came up with a work around, so thought to write a quick blog post for future reference.

Let’s understand the need, assume we are looking at Products data, and this is how report looks like

In the above report, if we have 50000 rows instead of 5, it would be difficult to find those two products which are causing significant loss. Of course, we can click on the chart on the right and interact, but that’s not the point here. So how can we make that card clickable? Well, for now, we don’t have an inbuilt clickable visual. So the question is how can we get something which looks like the card but interactive.  (I am sure there are several ways of doing this, but I have gone for Treemap visual.)

Let’s see how I created a Clickable Card:

First I created a calculated table

LossTable =
CALCULATETABLE (
ADDCOLUMNS (
SUMMARIZE ( Products, Products[Product] ),
"Prod", "Prod",
"LossCount", CALCULATE ( COUNT ( Products[Profit/Loss] ), Products[Profit/Loss] = "L" )
),
Products[Profit/Loss] = "L"
)

Then I created a relationship between Products table and a new Loss table, also I have hidden LossTable for users.

Replaced existing card with a treemap, Product column on Group and Sum of Loss count on values. As I had same values for all rows in Prod column, as expected there was only one tile in Treemap.

Now I have a clickable Card look-alike, which can interact with other visuals.

Hope this helps someone out there!

Prathy 🙂

2 comments
0 FacebookTwitterPinterestEmail

I am a huge OneNote fangirl, most of the times I start my working day by opening OneNote. But yesterday I accidentally discovered that I could Embed Power BI content into OneNote. In fact not only OneNote there are several other sources we can embed into OneNote – https://support.office.com/en-us/article/Embed-content-in-OneNote-fd5abf7d-abd4-4902-8e5f-93088c45b11d?ui=en-US&rs=en-US&ad=US&=fromAR1

The Sad part is we can only embed publicly published Power BI reports, which mean anyone on the internet can view these reports. (You can learn more about Power BI publish here  – https://powerbi.microsoft.com/en-us/documentation/powerbi-service-publish-to-web/ )

How Power BI looks in One Note?

Once you have your Power BI embedded URL ready, just copy and paste it into One Note. Initially, OneNote shows a bright white refresh button with dimmed yellow Microsoft Power BI background and a hyperlink text with Power BI.When you click on the refresh button, that’s when you can see Power BI content just like you see on any other website or blog with all the interactivity and full-screen options.

This could be handy for documentation, but I don’t think I want to publish my reports to the public for documentation purpose. If we have token functionality like Embedding with Non-Power BI users then probably we can use One Note as Power Note.

However, Yesterday, I was very excited to come across this and decided to write a quick blog post for fellow OneNote lovers.

Prathy 🙂

 

3 comments
0 FacebookTwitterPinterestEmail

In my recent talk for PASS BA Marathon, I showed few formatting tricks in Power BI with my super slow laptop. I promised to write a blog post but due to some other priorities, I didn’t manage to publish this blog post in time, well better late than never!

You can watch recorded Session here:

or just some highlights here:

Adding Gif images to Power BI:

People who knew me in person, I am sure they know I like pictures. However, so many pictures on a dashboard are undoubtedly not a good idea. Stephen Few mentioned, “Art has its place but not on the Dashboard”. Here, I am not at all recommending to put loads of GIF’s on the dashboard, but if you want to go crazy with your dashboard or want to get people attention, it’s not a bad idea. Well as Stephen Few mentioned in another article, It’s nice to highlight what needs attention.

Adding GIF images is quite easy. First I created a measure with value 0. I named this measure as BGGif, so I know I have to hide it from users, and it will be easy to identify in the model. It is not mandatory to create a measure, you can use an existing one, but creating a separate one makes it easy. Then I placed Line Chart( you can use other charts, but Line Chart makes it a bit easy). Then I went to format options of Line Chart, under Plot Area, for Add Image option I chose the GIF image. Based on the data colours, there is a chance of spotting a Lil dot; if you don’t want it, just move BGGif value to tool tips. I like the idea of putting Gif images; you can create some cool ones like below 🙂  I read or heard using Plot Area of charts for gif images, I don’t remember where exactly it was. Whoever it was, thank you 🙂

Dynamic Background:

There are several ways we can do this based on our use case. In my demo, I just wanted to show a background in green if the price <=100 if not Red.

First I created a measure with a bit of DAX. Again, I am going to prefix it with BG and make sure I hide it for business users.

PriceBG = if([Sum Of Price]<=100,"http://cdn30.us1.fansshare.com/image/wallpapergreen/pix-for-gt-plain-mint-green-wallpaper-mint-green-plain-background-wallpaper-wallpaper-mint-green-999507947.jpg" , "http://www.publicdomainpictures.net/pictures/200000/velka/plain-red-background.jpg")

In the measure, it is just a URL with Red and Green backgrounds. I changed the data category of measure to Image URL. Then I used Image custom visual to display PriceBG measure. One problem with this approach is if URL brakes, visuals will not work.

Using Unicode:

I first saw this technique when Will Thomson showed at UK Power BI Summit also recently Chris Webb blogged about using Unichar() function.  In my demo, I just copied Emoji’s from the Web and placed them in my measure, but if you want you can use UNICHAR() function as Chris explained.

To show #Beds – I created a measure like below:

#BedsEmoji = if((AirBnB[bedrooms])>=5,"?️ +",

IF(AirBnB[bedrooms]=1,"?️",

IF(AirBnB[bedrooms]=2,"?️ ?️",

IF(AirBnB[bedrooms]=3,"?️ ? ?️️",

IF(AirBnB[bedrooms]=4,"?️ ?️ ?️ ?️","0")))))

And for an overall review, I used Sentiment Analysis, based on sentiment analysis value; I created another measure:

ReviewEmoji = if(SUM([Score])<=.50,"?","?")

These emoji looks great on Power BI Service than PowerBI Desktop. I love the functionality of using strings in DAX measures, it enables us to use Unicode and advantages are unlimited. As I blogged in one of my previous blog posts, you can use these to highlight a specific data point in a chart. Or as Chris blogged, we can use Unicode in many ways.

Hope this blog post gives you some ideas, and again I am sorry for not publishing blog post earlier. You can download the PBI file here – https://1drv.ms/f/s!Avm7gbgZtlMlpx4qFeK1Qu15NcpE and view reports here – https://app.powerbi.com/view?r=eyJrIjoiNzUxYzRmNjUtNDA4Mi00MWI0LWJiNWQtMDRiZWQwZmFjYjE0IiwidCI6IjM4YmU3MjU5LTMyMGQtNDZkYy04YzNiLWNkZDA5OTM1NGExMyIsImMiOjh9

Keep Smiling,

Prathy ?

 

0 comment
1 FacebookTwitterPinterestEmail