Connect to Power BI published reports with Python without API

Connect and export your published Power BI reports datasets with Python using Analyse in Excel connection. No API required.

Power BI is a great tool to import and transform data from various sources. Exporting data is however more difficult.
This Python function returns a Pandas DataFrame from Power BI service, given a dataset id and a table name (or Dax query), allowing you for exemple to save Power BI data in a file or in a SQL database.
This method uses Windows identity, also used in Analyse in Excel, and should be used as a quick and convenient way to extract Power BI data. Power BI rest API execute queries should be preferred if you have Azure and Power BI relevant rights.

Requirements

  • Test if Analyse in Excel is working for a report you have access to
  • Analysis Services client library MSOLAP should be version 15 (recent version 16 is not working as today)
  • Install pywin32 via pip install pywin32 or conda install pywin32
  • Go to app.powerbi.com/datahub/datasets, select a dataset: end of url is your dataset id
  • Update the code your dataset id and table name (list of tables available via Show tables button on Power BI dataset page) or use DAX code to generate a custom table with measures

The code

"""Connect to published Power BI datasets and export data with Python
Author:
    https://LittleBigFrog.xyz - 13.01.2022
"""

import adodbapi #Install via pip install pywin32 or conda install pywin32
import pandas as pd

def GetData(DatasetId,TableQuery):
    ConnectionString = f"""Provider=MSOLAP.8;
    Integrated Security=ClaimsToken;
    Persist Security Info=True;
    Initial Catalog=sobe_wowvirtualserver-{DatasetId};
    Data Source=pbiazure://api.powerbi.com;
    MDX Compatibility=1;
    Safety Options=2;
    MDX Missing Member Mode=Error;
    Identity Provider=https://login.microsoftonline.com/common, https://analysis.windows.net/powerbi/api, 929d0ec0-7a41-4b1e-bc7c-b754a28bddcc;
    Update Isolation Level=2"""
    Query = TableQuery if TableQuery.lower().startswith("select") else  f"evaluate {TableQuery}" 
    conn = adodbapi.connect(ConnectionString)
    DataFrame=pd.read_sql(Query, conn)
    return DataFrame

# Find your DatasetId
# go to https://app.powerbi.com/datahub/datasets
# click on your dataset: end of url is your DatasetId
# click on "Show tables" to see available tables
DatasetId = "ee30a2fc-aezb-4eb8-81d2-d1ec21eec060"
QueryTablesList="Select TABLE_NAME from $SYSTEM.DBSCHEMA_TABLES where TABLE_SCHEMA='MODEL' and TABLE_TYPE='SYSTEM TABLE' "
TableName = "DatasetTableName" #not case sensitive


# List of Dataset tables
AvailableTables=GetData(DatasetId,QueryTablesList)['TABLE_NAME'].tolist()
# Get pandas dataframe for specific table
Data=GetData(DatasetId,TableName)
# Get data from a DAX query
Dax='SUMMARIZE (Sales,Sales[Color],"Sales", SUM ( Sales[Amount] ))'
DataDax=GetData(DatasetId,Dax)
# Export to Excel (requires openpyxl)
Data.to_excel("PowerBIexport.xlsx", index = False)
# Export to csv 
Data.to_csv('out.csv')


# Export table to SQL server
from sqlalchemy import create_engine
#Build your connection: https://docs.sqlalchemy.org/en/14/dialects/mssql.html#module-sqlalchemy.dialects.mssql.pyodbc
connection_uri = create_engine(
    "mssql+pyodbc://scott:tiger@myhost:49242/databasename"
    "?driver=ODBC+Driver+17+for+SQL+Server"
    "&authentication=ActiveDirectoryIntegrated"
)
engine = create_engine(connection_uri, fast_executemany=True)
Data.to_sql("SQL_Table_Name", engine, if_exists="replace", index=False)
Available on GitHub

Notes

  • The function uses the connection generated for Power BI Analyse in Excel
  • The Windows identity of the caller is used to connect to Analysis Services (Integrated Security=ClaimsToken)
  • Beauty of the solution is avoiding authentification required for premium XLMA and Power BI REST api (you/IT need to register an Azure AD application and I'm still looking for a clear documentation)
  • I'm investigating the issue with latest MSOLAP client library. Meanwhile, previous version 15.1.108.23 is available here: x64  and  x86 (thank you Rahul Tenany for the links)
  • It was tested on different machines and configurations: more testing and feedback is welcome