Connect Microsoft Power BI to QPR ProcessAnalyzer: Difference between revisions

From QPR ProcessAnalyzer Wiki
Jump to navigation Jump to search
 
(34 intermediate revisions by the same user not shown)
Line 1: Line 1:
This guide explains how to connect '''Microsoft Power BI''' to '''QPR ProcessAnalyzer''' using the Power Query Web.Contents function. It walks you through creating the data source, building the semantic model, setting privacy levels, defining column data types, and producing your first report.
This guide explains how to connect '''Microsoft Power BI''' to QPR ProcessAnalyzer using the Power Query [https://learn.microsoft.com/en-us/powerquery-m/web-contents Web.Contents] function. It walks you through creating the data source, building the semantic model, defining column data types, and producing the first report.


The connection works by authenticating against the QPR ProcessAnalyzer REST API to obtain an access token, then running an expression query against a selected model to retrieve data as a table.
The connection works by authenticating against the QPR ProcessAnalyzer REST API with username and password to obtain an access token, then running an expression query against a selected model to retrieve data as a table.


== Overview ==
== Overview ==
The connection is built in the Power Query editor. The query performs three steps:
# Get an access token: sends the username and password to the token endpoint and reads the returned access token.
# Run an expression query: sends a QPR ProcessAnalyzer query to the api/expression/query endpoint using the access token.
# Parse and shape: converts the returned data into a Power BI table.


The connection is built entirely in the Power Query editor using a single M query. The query performs three steps:
== Create Data Source and Semantic Model ==
# Get an access token: sends the username and password to the token endpoint using the OAuth password grant type and reads the returned access_token.
Follow these steps to create the data source and the semantic model. These instructions have been written for the Power BI Service (cloud), but they can also be applied for the Power BI Desktop.
# Run an expression query: sends a JSON request body (dimensions, values, ordering, etc.) to the api/expression/query endpoint, using the access token as a Bearer token.
# On the '''Home''' ribbon, click '''Get data''' → '''Blank query'''. The Power Query editor opens with a new empty query.
# Parse and shape: converts the returned JSON into a Power BI table.
# Delete any existing content and paste the Power Query script below. Configure server URL, username, password, model ID, the actual query, and column data types to the script. Click '''Next'''.
# Click '''Configure Connection''' and '''Edit connection'''.
# Check that '''Authentication kind''' is '''Anonymous''', and '''Privacy level''' is NOT '''None''' (https://learn.microsoft.com/en-us/power-query/privacy-levels). Click '''Connect'''.
# Define a describing name for the query (in the '''Query Settings''' panel).
# Click '''Create a report'''.
# Define a name for the semantic model, and click '''Create'''. Data source and semantic model have been created, and the [[#Create_Report|report editor]] opens.)


== Step 1: Create Data Source ==
=== Power Query Example ===
# Open '''Power BI Desktop'''.
<syntaxhighlight lang="typescript" line>
# On the '''Home''' ribbon, click '''Get data''' → '''Blank query'''.
#* Alternatively, choose '''Get data''' → '''More...''' → '''Other''' → '''Blank Query''' → '''Connect'''.
# The '''Power Query Editor''' opens with a new empty query named Query1.
# In the toolbar, click '''Advanced Editor'''.
# Delete any existing content and paste the M script below.
 
=== Power Query Script ===
 
<syntaxhighlight lang="powerquery">
let
let
     // ================= Configuration =================
     // ================= Configuration =================
     BaseUrl = "https://server.onqpr.com/qprpa/",
     Url = "https://customer.onqpr.com/qprpa/",
    ModelId  = 123,
     UserName = "qpr",
     UserName = "qpr",
     Password = "demo",
     Password = "demo",
    ModelId  = 1,
     RequestBody = [
     RequestBody = [
         Dimensions = {
         Dimensions = {
             [
             [
                 Name       = "Company Code",
                 Name = "Case start time",
                 Expression = "Column(""Company Code"")"
                 Expression = "AggregateFrom(Events, ""Min"", TimeStamp)",
                DatetimeTruncation = "month"
             ]
             ]
         },
         },
         Values = {
         Values = {
             [
             [
                 Name               = "Count",
                 Name = "Count",
                 AggregationFunction = "count"
                 AggregationFunction = "count"
             ]
             ]
Line 42: Line 43:
         Ordering = {
         Ordering = {
             [
             [
                 Name     = "Count",
                 Name = "Case start time",
                 Direction = "Descending"
                 Direction = "Ascending"
             ]
             ]
         },
         },
         Root             = "Cases",
         Root = "Cases",
         ModelId         = ModelId,
         ModelId = ModelId,
         ContextType     = "model",
         ContextType = "model",
         ProcessingMethod = "dataframe"
         ProcessingMethod = "dataframe"
     ],
     ],
Line 55: Line 56:
     TokenBody = Uri.BuildQueryString([
     TokenBody = Uri.BuildQueryString([
         grant_type = "password",
         grant_type = "password",
         username   = UserName,
         username = UserName,
         password   = Password
         password = Password
     ]),
     ]),
     TokenResponse = Web.Contents(
     TokenResponse = Web.Contents(
         BaseUrl,
         Url,
         [
         [
             RelativePath = "token",
             RelativePath = "token",
             Headers = [
             Headers = [
                 #"Content-Type" = "application/x-www-form-urlencoded",
                 #"Content-Type" = "application/x-www-form-urlencoded",
                 #"Accept"       = "application/json"
                 #"Accept" = "application/json"
             ],
             ],
             Content = Text.ToBinary(TokenBody)
             Content = Text.ToBinary(TokenBody)
Line 74: Line 75:
     // ================= Step 2: Run query =================
     // ================= Step 2: Run query =================
     QueryResponse = Web.Contents(
     QueryResponse = Web.Contents(
         BaseUrl,
         Url,
         [
         [
             RelativePath = "api/expression/query",
             RelativePath = "api/expression/query",
             Headers = [
             Headers = [
                 #"Content-Type" = "application/json",
                 #"Content-Type" = "application/json",
                 #"Accept"       = "application/json",
                 #"Accept" = "application/json",
                 #"Authorization" = "Bearer " & AccessToken
                 #"Authorization" = "Bearer " & AccessToken
             ],
             ],
Line 88: Line 89:
     AsTable = Table.FromRecords(Parsed),
     AsTable = Table.FromRecords(Parsed),


     // ================= Step 3: Set column types =================
     // ================= Step 3: Set column data types =================
     TypedTable = Table.TransformColumnTypes(
     TypedTable = Table.TransformColumnTypes(
         AsTable,
         AsTable,
         {
         {
             {"Company Code", type text},
             {"Case start time", type datetime},
             {"Count",       Int64.Type}
             {"Count", Int64.Type}
         }
         }
     )
     )
Line 100: Line 101:
</syntaxhighlight>
</syntaxhighlight>


# Update the '''Configuration''' section to match your environment:
=== Column Data Types ===
#* BaseUrl – your QPR ProcessAnalyzer base URL (keep the trailing slash).
The data type for each column in the queried dataset needs to be defined. The following example shows how to convert QPR ProcessAnalyzer's data types in the Power Query script.
#* ModelId – the numeric ID of your model.
<syntaxhighlight lang="typescript" line>
#* UserName and Password – your QPR ProcessAnalyzer credentials.
# Adjust the '''RequestBody''' to select the dimensions, values, and ordering you need.
# Click '''Done''' to close the Advanced Editor.
# Rename the query (right-click the query in the '''Queries''' pane → '''Rename''').
 
=== Data types ===
The following example shows how to convert different data types in the PowerBI query.
<syntaxhighlight>
TypedTable = Table.TransformColumnTypes(
TypedTable = Table.TransformColumnTypes(
AsTable,
AsTable,
Line 117: Line 110:
{"IntegerColumn", Int64.Type},
{"IntegerColumn", Int64.Type},
{"DecimalColumn", type number},
{"DecimalColumn", type number},
{"DateColumn", type date},
{"DateColumn", type datetime},
{"BooleanColumn", type logical}
{"BooleanColumn", type logical}
}
}
Line 123: Line 116:
</syntaxhighlight>
</syntaxhighlight>


== Step 2: Configure Privacy Settings ==
== Create Report ==
Because the query passes data (credentials and a token) from one Web.Contents call into another, Power BI's '''Privacy Level''' checks can block the query or trigger a "Formula.Firewall" error. You must configure privacy settings correctly.
When the data source and the semantic model are in place, you can continue with creating the first report:
 
# From the '''Visualizations''' pane, select a visual, for example a bar chart.
# In the Power Query Editor, go to '''File''' → '''Options and settings''' → '''Options'''.
# Under '''Current File''', select '''Privacy'''.
# Choose '''Combine data according to your Privacy Level settings for each source''', and set the source privacy level to '''Public''' or '''Organizational''' as appropriate for your organization.
# Click '''OK'''.
 
=== Setting credentials for the data source ===
When the query runs for the first time, Power BI may prompt for credentials for the base URL:
# If prompted, select '''Anonymous''' as the authentication method (authentication is handled inside the query via the token).
# Set the privacy level for the URL to '''Organizational''' (or '''Public''').
# Click '''Connect'''.
 
== Step 3: Create First Report ==
# Switch to the '''Report view''' (left sidebar).
# From the '''Visualizations''' pane, select a visual, for example a '''Clustered bar chart'''.
# From the '''Data''' pane, drag fields onto the visual:
# From the '''Data''' pane, drag fields onto the visual:
#* Drag Company Code to the '''Y-axis''' (or Axis).
#* Drag Company Code to the '''Y-axis''' (or Axis).
#* Drag Count to the '''X-axis''' (or Values).
#* Drag Count to the '''X-axis''' (or Values).
# Adjust formatting (title, colors, data labels) in the '''Format''' pane.
# Adjust formatting (title, colors, data labels) in the '''Format''' pane.
# Add slicers or filters as needed (for example, a slicer on Company Code).
# Save the report: '''File''' → '''Save As'''.
# Save the report: '''File''' → '''Save As''' and choose a location for the .pbix file.
 
== Limitations ==
When implementing this integration, be aware of the following limitations.
 
=== Refreshing Data ===
Data shown in Power BI is a snapshot taken at the time of the last data load. It is not a live connection to QPR ProcessAnalyzer. The data is updated when a refresh is performed, either:
* Manual refresh: In Power BI Service, open the semantic model, and press the '''Refresh''' button. In Power BI Desktop, click '''Refresh''' on the Home ribbon.
* Scheduled refresh: Power BI Service allows to schedule an automatic refresh. To configure it, open the semantic model and press the arrow down below in the '''Refresh''' button and press '''Schedule refresh'''.
 
=== Shared QPR ProcessAnalyzer Credentials ===
The connection authenticates using a single set of QPR ProcessAnalyzer credentials embedded in the query, rather than each report user's individual account. This has important consequences:
* All Power BI users effectively see data through the same QPR ProcessAnalyzer account, regardless of who they are.
* User-specific permissions and per-user access restrictions defined in QPR ProcessAnalyzer are not applied to individual Power BI users.
* Any access control must be handled on the Power BI side (for example, workspace permissions or row-level security), not through the QPR ProcessAnalyzer.
 
=== Filtering Behavior ===
The configured query can contain QPR ProcessAnalyzer filters to cases and events, but creating filters interactively while viewing the report (drilldown) is not possible. Still, filtering performed on the Power BI side (slicers, visual filters, page/report filters) takes effect.


== Refreshing Data ==
This means the full result set defined by the query is always retrieved before Power BI filtering is applied, which can affect the volume of data transferred and report performance. To limit data at the source, you must change the query itself rather than rely on interactive filtering.
* '''Manual refresh:''' In Power BI Desktop, click '''Refresh''' on the Home ribbon.
* '''Scheduled refresh (Power BI Service):''' After publishing, configure a scheduled refresh. Because the query calls a web API, you may need an appropriate gateway configuration and correctly configured credentials/privacy levels in the service.

Latest revision as of 10:01, 24 August 2026

This guide explains how to connect Microsoft Power BI to QPR ProcessAnalyzer using the Power Query Web.Contents function. It walks you through creating the data source, building the semantic model, defining column data types, and producing the first report.

The connection works by authenticating against the QPR ProcessAnalyzer REST API with username and password to obtain an access token, then running an expression query against a selected model to retrieve data as a table.

Overview

The connection is built in the Power Query editor. The query performs three steps:

  1. Get an access token: sends the username and password to the token endpoint and reads the returned access token.
  2. Run an expression query: sends a QPR ProcessAnalyzer query to the api/expression/query endpoint using the access token.
  3. Parse and shape: converts the returned data into a Power BI table.

Create Data Source and Semantic Model

Follow these steps to create the data source and the semantic model. These instructions have been written for the Power BI Service (cloud), but they can also be applied for the Power BI Desktop.

  1. On the Home ribbon, click Get dataBlank query. The Power Query editor opens with a new empty query.
  2. Delete any existing content and paste the Power Query script below. Configure server URL, username, password, model ID, the actual query, and column data types to the script. Click Next.
  3. Click Configure Connection and Edit connection.
  4. Check that Authentication kind is Anonymous, and Privacy level is NOT None (https://learn.microsoft.com/en-us/power-query/privacy-levels). Click Connect.
  5. Define a describing name for the query (in the Query Settings panel).
  6. Click Create a report.
  7. Define a name for the semantic model, and click Create. Data source and semantic model have been created, and the report editor opens.)

Power Query Example

let
    // ================= Configuration =================
    Url  = "https://customer.onqpr.com/qprpa/",
    UserName = "qpr",
    Password = "demo",
    ModelId  = 1,
    RequestBody = [
        Dimensions = {
            [
                Name = "Case start time",
                Expression = "AggregateFrom(Events, ""Min"", TimeStamp)",
                DatetimeTruncation = "month"
            ]
        },
        Values = {
            [
                Name = "Count",
                AggregationFunction = "count"
            ]
        },
        Ordering = {
            [
                Name = "Case start time",
                Direction = "Ascending"
            ]
        },
        Root = "Cases",
        ModelId = ModelId,
        ContextType = "model",
        ProcessingMethod = "dataframe"
    ],

    // ================= Step 1: Get access token =================
    TokenBody = Uri.BuildQueryString([
        grant_type = "password",
        username = UserName,
        password = Password
    ]),
    TokenResponse = Web.Contents(
        Url,
        [
            RelativePath = "token",
            Headers = [
                #"Content-Type" = "application/x-www-form-urlencoded",
                #"Accept" = "application/json"
            ],
            Content = Text.ToBinary(TokenBody)
        ]
    ),
    TokenParsed = Json.Document(TokenResponse),
    AccessToken = TokenParsed[access_token],

    // ================= Step 2: Run query =================
    QueryResponse = Web.Contents(
        Url,
        [
            RelativePath = "api/expression/query",
            Headers = [
                #"Content-Type" = "application/json",
                #"Accept" = "application/json",
                #"Authorization" = "Bearer " & AccessToken
            ],
            Content = Json.FromValue(RequestBody)
        ]
    ),
    Parsed = Json.Document(QueryResponse),
    AsTable = Table.FromRecords(Parsed),

    // ================= Step 3: Set column data types =================
    TypedTable = Table.TransformColumnTypes(
        AsTable,
        {
            {"Case start time", type datetime},
            {"Count", Int64.Type}
        }
    )
in
    TypedTable

Column Data Types

The data type for each column in the queried dataset needs to be defined. The following example shows how to convert QPR ProcessAnalyzer's data types in the Power Query script.

TypedTable = Table.TransformColumnTypes(
	AsTable,
	{
		{"TextColumn", type text},
		{"IntegerColumn", Int64.Type},
		{"DecimalColumn", type number},
		{"DateColumn", type datetime},
		{"BooleanColumn", type logical}
	}
),

Create Report

When the data source and the semantic model are in place, you can continue with creating the first report:

  1. From the Visualizations pane, select a visual, for example a bar chart.
  2. From the Data pane, drag fields onto the visual:
    • Drag Company Code to the Y-axis (or Axis).
    • Drag Count to the X-axis (or Values).
  3. Adjust formatting (title, colors, data labels) in the Format pane.
  4. Save the report: FileSave As.

Limitations

When implementing this integration, be aware of the following limitations.

Refreshing Data

Data shown in Power BI is a snapshot taken at the time of the last data load. It is not a live connection to QPR ProcessAnalyzer. The data is updated when a refresh is performed, either:

  • Manual refresh: In Power BI Service, open the semantic model, and press the Refresh button. In Power BI Desktop, click Refresh on the Home ribbon.
  • Scheduled refresh: Power BI Service allows to schedule an automatic refresh. To configure it, open the semantic model and press the arrow down below in the Refresh button and press Schedule refresh.

Shared QPR ProcessAnalyzer Credentials

The connection authenticates using a single set of QPR ProcessAnalyzer credentials embedded in the query, rather than each report user's individual account. This has important consequences:

  • All Power BI users effectively see data through the same QPR ProcessAnalyzer account, regardless of who they are.
  • User-specific permissions and per-user access restrictions defined in QPR ProcessAnalyzer are not applied to individual Power BI users.
  • Any access control must be handled on the Power BI side (for example, workspace permissions or row-level security), not through the QPR ProcessAnalyzer.

Filtering Behavior

The configured query can contain QPR ProcessAnalyzer filters to cases and events, but creating filters interactively while viewing the report (drilldown) is not possible. Still, filtering performed on the Power BI side (slicers, visual filters, page/report filters) takes effect.

This means the full result set defined by the query is always retrieved before Power BI filtering is applied, which can affect the volume of data transferred and report performance. To limit data at the source, you must change the query itself rather than rely on interactive filtering.