iT邦幫忙

第 12 屆 iT 邦幫忙鐵人賽

DAY 14
0
Microsoft Azure

Azure 的奇幻之旅系列 第 14

Azure 系列文(14) - Power BI Embedded 豐富你的網站 (下)

上一篇提到了怎麼將Power BI快速的Embedded到你的網站,但是前一天的兩種方法 - 發行至Web、安全內嵌,都有一些自己的問題,所以如果你的問題沒辦法解決,那Power BI Embedded For Develop可能會是你最佳的選擇! 本篇會把如何把Report、Dashboard嵌入到網頁內!

準備

  • Azure 帳號
  • Power BI 帳號

建立Power BI Embedded

首先呢,如果我們想要使用Embedded的服務,必須先註冊Embedded,基本上就是填一些資訊,到最後一步的時候下載範例
https://ithelp.ithome.com.tw/upload/images/20200922/201279949YsNRjYkkj.png

設定專案

也可以使用Git的方式將專案下載下來

git clone https://github.com/microsoft/PowerBI-Developer-Samples.git

進入Python目錄

cd PowerBI-Developer-Samples-master/Python/Embed for your customers/

安裝依賴

pip install requirements.txt

接著在Config.py填你的資料,如果忘記上面的資料可以到Azure Portal的Azure Active Diretory的應用程式註冊找一下
config.py

class BaseConfig(object):
    # Can be set to 'MasterUser' or 'ServicePrincipal'
    AUTHENTICATION_MODE = 'MasterUser'

    # Workspace Id in which the report is present
    WORKSPACE_ID = ''  <- Power BI的WorkSpace ID
    
    # Report Id for which Embed token needs to be generated
    REPORT_ID = ''      <- Power BI的Report ID
    
    # Id of the Azure tenant in which AAD app and Power BI report is hosted. Required only for ServicePrincipal authentication mode.
    TENANT_ID = ''      <- Azure Active Diretory的租用戶識別碼
    
    # Client Id (Application Id) of the AAD app
    CLIENT_ID = ''      <- Azure Active Diretory的用戶端識別碼
    
    # Client Secret (App Secret) of the AAD app. Required only for ServicePrincipal authentication mode.
    CLIENT_SECRET = ''   <- Azure Active Diretory的憑證與秘密
    
    # Scope of AAD app. Use the below configuration to use all the permissions provided in the AAD app through Azure portal.
    SCOPE = ['https://analysis.windows.net/powerbi/api/.default']
    
    # URL used for initiating authorization request
    AUTHORITY = 'https://login.microsoftonline.com/organizations'
    
    # Master user email address. Required only for MasterUser authentication mode.
    POWER_BI_USER = ''
    
    # Master user email password. Required only for MasterUser authentication mode.
    POWER_BI_PASS = ''

接下來只要python app.py就可以看到網頁了!!
https://ithelp.ithome.com.tw/upload/images/20200923/20127994KyF2zyh40u.png

Power BI Embedded For Dashboard

從程式碼裡面的** powerbiembedding/static/index.js
index.js

$(function () {
    var models = window['powerbi-client'].models;
    var reportLoadConfig = {
        type: "report",  <- 將這個地方改成dashboard
        tokenType: models.TokenType.Embed,
        /*
        // Enable this setting to remove gray shoulders from embedded report
        settings: {
            background: models.BackgroundType.Transparent
        }
        */
    };
    var reportContainer = $("#report-container").get(0);
    
    // Initialize iframe for embedding report
    powerbi.bootstrap(reportContainer, reportLoadConfig);
    $.ajax({
        type: "GET",
        url: "/getembedinfo",
        dataType: "json",
        success: function (data) {
            embedData = $.parseJSON(JSON.stringify(data));
            reportLoadConfig["accessToken"] = embedData["accessToken"];
            reportLoadConfig["embedUrl"] = embedData["embedUrl"];
            
            // Use the token expiry to regenerate Embed token for seamless end user experience
            // Refer https://aka.ms/RefreshEmbedToken
            tokenExpiry = embedData["tokenExpiry"];
            
            // Embed Power BI report when Access token and Embed URL are available
            var report = powerbi.embed(reportContainer, reportLoadConfig);
            
            // Triggers when a report schema is successfully loaded
            report.on("loaded", function () {
                console.log("Report load successful")
            });

            // Triggers when a report is successfully embedded in UI
            report.on("rendered", function () {
                console.log("Report render successful")
            });

            // Clear any other error handler event
            report.off("error");
            
            // Below patch of code is for handling errors that occur during embedding
            report.on("error", function (event) {
                var errorMsg = event.detail;
            
                // Use errorMsg variable to log error in any destination of choice
                console.error(errorMsg);
                return;
            });
        },
        error: function (err) {
            
            // Show error container
            var errorContainer = $(".error-container");
            $(".embed-container").hide();
            errorContainer.show();
            
            // Format error message
            var errMessageHtml = "<strong> Error Details: </strong> <br/>" + $.parseJSON(err.responseText)['errorMsg'];
            errMessageHtml = errMessageHtml.split("\n").join("<br/>")
            // Show error message on UI
            errorContainer.html(errMessageHtml);
        }
    });
});

接著把config.py裡面的Report ID改成Dashboard ID,Dashboard ID在網址列就可以看到了
https://ithelp.ithome.com.tw/upload/images/20200923/2012799496EJjRoWxE.png

將pbiembedservice.py的程式碼修改成以下

from flask import current_app as app
import requests
import json

def getembedparam(accesstoken):
    '''Returns Embed token and Embed URL'''

    try:
        headers = {'Content-Type': 'application/json', 'Authorization': 'Bearer ' + accesstoken}

        reporturl = 'https://api.powerbi.com/v1.0/myorg/groups/' + app.config['WORKSPACE_ID'] + '/dashboards/' + app.config['REPORT_ID']
        
        apiresponse = None

        try:
            apiresponse = requests.get(reporturl, headers=headers)
            if app.debug:
                print('Embed URL Request ID: ', apiresponse.headers.get('RequestId'))
        except Exception as ex:
            raise Exception('Error while retrieving report Embed URL\n')

        if not apiresponse:
            raise Exception('Error while retrieving report Embed URL\n' + apiresponse.reason + '\nRequestId: ' + apiresponse.headers.get('RequestId'))

        try:
            apiresponse = json.loads(apiresponse.text)        
            embedurl = apiresponse['embedUrl']
            datasetId = apiresponse['id']
        except Exception as ex:
            raise Exception('Error while extracting Embed URL from API response\n' + apiresponse.text)
            
        # Get embed token
        embedtokenurl = 'https://api.powerbi.com/v1.0/myorg/groups/'+ app.config['WORKSPACE_ID'] + '/dashboards/' + app.config['REPORT_ID'] + '/GenerateToken'
        body = {
            'accessLevel': 'View',
            'datasetId': app.config['DATASET_ID']
        }


        apiresponse = None
        
        try:
            
            # Generate Embed token for multiple workspaces, datasets, and reports. Refer https://aka.ms/MultiResourceEmbedToken
            apiresponse = requests.post(embedtokenurl, data=json.dumps(body), headers=headers)
            if app.debug:
                print('Embed token Request ID: ', apiresponse.headers.get('RequestId'))
        except:
            raise Exception('Error while invoking Embed token REST API endpoint\n')
        
        if not apiresponse:
            raise Exception('Error while retrieving report Embed URL\n' + apiresponse.reason + '\nRequestId: ' + apiresponse.headers.get('RequestId'))

        try:
            apiresponse = json.loads(apiresponse.text)
            
            embedtoken = apiresponse['token']
            embedtokenid = apiresponse['tokenId']
            tokenexpiry = apiresponse['expiration']
            if app.debug:
                print('Embed token Expires on: ', tokenexpiry)
                print('Embed Token ID: ', embedtokenid)
        except Exception as ex:
            raise Exception('Error while extracting Embed token from API response\n' + apiresponse.reason)

        response = {'accessToken': embedtoken, 'embedUrl': embedurl, 'tokenExpiry': tokenexpiry}
        
        return json.dumps(response)
    except Exception as ex:
        return json.dumps({'errorMsg': str(ex)}), 500

我們還需要去取得Dashboard的dataset,用範例裡面的試看看,記下DatasetId
https://ithelp.ithome.com.tw/upload/images/20200923/20127994RH1No6XfsD.png

再到Config.py新增DatasetId即可

DATASET_ID = 'xxxxxx'

接著就可以在網頁上看到你的Dashboard已經嵌入成功囉~!
https://ithelp.ithome.com.tw/upload/images/20200923/20127994Dk7VnkqsEN.png

Dashboard的Dataset為什麼要透過Tile拿?

因為Dashboard是由磚(Tile)組成的,所以每個磚都會有獨立的Dataset,所以這也是拿DataseId麻煩的地方,如果要嵌入Dashboard就必須透過get Tile去Query所有的DatasetId,才可以產生Dashborad的Embedded Token,藉此才可以嵌入到網頁上!


上一篇
Azure 系列文(13) - Power BI Embedded 豐富你的網站 (上)
下一篇
Azure 系列文(15) - Key Vault 保護你的安全資訊
系列文
Azure 的奇幻之旅30

尚未有邦友留言

立即登入留言