Average Strategy dossier consists of a few different visualizations (grids, pie charts, bar charts, maps etc.). This Python script example can scan all the dossiers in your environment and provide aggregated statistics like what is the most popular visualization type or which dossiers contain maps.
The Python script below was created and testedn in Jupyter Notebook with Strategy 2021 u.4 and mstrio library 11.3.3.102. Main steps in this script:
- establish connection to MSTR environment
- select Projects to be analyzed
- get general list of dossiers (list 1)
- get list of visualizations applied in each dossier (list 2)
- merge two lists
- export to Excel
- push the dataset to Platform Analytics project for further analysis
Example visualizations of the results:

Attached to this article are:
- Jupyter Notebook file with the Python code used
- the same code as a regular .py file
Please note - I've added color formatting in the code below (http://hilite.me/). Code copied from here might not work due to indentation issues. In that case, use attached file with sample code. Also this CRM is adding ';' after URLs.
#!/usr/bin/env python
# coding: utf-8
# In[ ]:
# This script will gather basic information about dossiers + types of visualizations used to build those dossiers
# Author: Robert Prochowicz
# Date: 2022-04-11
# Tested with Strategy 2021 u.4 and mstrio 11.3.3.102
# Update parameters in PARAMETERS section
# Make sure your user has access to your Main Project and Platform Analytics Project (write access to Shared Reports)
# Main steps:
## - establish connection to MSTR environment
## - select Projects to be analyzed
## - get general list of dossiers (list 1)
## - get list of visualizations applied in each dossier (list 2)
## - merge two lists
## - export to Excel
## - push the dataset to Platform Analytics project for further analysis
from mstrio.connection import Connection
from mstrio.project_objects.dossier import list_dossiers, list_dossiers_across_projects
from mstrio.project_objects.datasets.super_cube import SuperCube
from mstrio.server import Project, Environment
from datetime import datetime
import pandas as pd
import csv, getpass
# Functions
def quickSearch(connection, root_folder, type_object, certifiedStatus, get_ancestors, limit_search):
res = connection.session.get(url=connection.base_url + "/api/searches/results?" + "root=" + root_folder +
"&type=" + str(type_object) + "&getAncestors=" + get_ancestors + "&limit="
+ str(limit_search) + "&certifiedStatus=" + certifiedStatus)
return res
def search_details(res):
res_json = res.json()['result']
for row in res_json:
path=''
if 'ancestors' in row: # necessary if you set get_ancestors parameter to false
for i in range(len(row['ancestors'])):
path= path+' > '+(row['ancestors'][i]['name'])
else:
path="___NO PATH"
row['path'] = path[3:]
return res_json
def get_viz_list(connection, dossier_id, project_ID):
r = connection.session.get(url=connection.base_url + "/api/v2/dossiers/" + dossier_id + "/definition",
headers={'X-MSTR-ProjectID': project_ID})
viz_def= [] #["","","","","","","","","",""]
if r:
r_json=r.json()
doss_name, doss_id = r_json["name"], r_json["id"]
#print(doss_name, " - ", doss_id)
for chapter in r_json["chapters"]:
chapter_name, chapter_key = chapter["name"], chapter["key"]
#print("\nCHAPTER: ",chapter_name," - ",chapter_key,"\n")
#print(chapter["pages"])
for page in chapter["pages"]:
page_name, page_key = page["name"], page["key"]
#print("PAGE: ",page_name, " - ", page_key, "\n")
for viz in page["visualizations"]:
viz_name, viz_key = viz["name"], viz["key"]
if viz.get("visualizationType"):
viz_type = viz["visualizationType"]
else:
viz_type = "other"
#print("VIZ: ", viz_name, " >>> " ,viz_key, " >>> " ,viz_type)
viz_def.extend([[doss_name,doss_id,chapter_name,chapter_key,page_name,page_key,viz_name,viz_key,viz_type,project_ID]])
else:
print(f"error / dossier: {dossier_id} / project: {project_ID}")
return viz_def
# ## PARAMETERS
# In[ ]:
mstr_base_url = "https://env-240147.customer.cloud.Strategy.com/MicroStrategyLibrary/api"
PA_project_id = "065E7F1E11E8FE1004240080EFE55E79" # Platform Analytics
mstr_username = "mstr"
mstr_password = getpass.getpass(prompt='Password ')
mstr_login_mode = 1 # Login mode (1 - Standard, 16 - LDAP)
root_folder = '' # empty means search will start at the top Project level
type_object = 55 #55 is document/dossier ; 3 is report/cube
certifiedStatus = 'ALL' #CERTIFIED_ONLY , ALL
get_ancestors = 'true' # important if we want to include the path to dossiers
limit_search = -1
# # Connection, Initial dossier list, Projects list
# In[ ]:
mstr_connection = Connection(mstr_base_url, mstr_username, mstr_password, login_mode=mstr_login_mode, verbose=False)
# Get all dossiers info + Path
search_result = quickSearch(mstr_connection, root_folder, type_object, certifiedStatus, get_ancestors, limit_search)
df_doss_list = pd.DataFrame(search_details(search_result))
# remove unwanted columns
df_doss_list.drop(['ancestors','owner',"abbreviation","certifiedInfo","iconPath","extType","acg"], inplace=True, axis=1)
# remove documents and templates - leave only dossiers
df_doss_list=df_doss_list[df_doss_list.viewMedia.isin([1879072805])]
# Get the list of all projects
env = Environment(connection=mstr_connection)
project_list=[(a.name, a.id) for a in env.list_projects()]
for p in project_list:
print(p)
# ### [Optional] Define custom project list to scan
# In[ ]:
# Limit the list of Projects
project_list=[('Strategy Tutorial', 'B7CA92F04B9FAE8D941C3E9B7E0CD754'),
('Financial Report (Strategy Tutorial)', '575C1BF94B465776C76B378E168E07AC')]
# Get just Project IDs
project_list_ids=[a[1] for a in project_list]
# from the list of all dossiers (from all projects) keep only those from project_list_ids
print(f"\n- Initial number of dossiers: {len(df_doss_list.index)}")
df_doss_list=df_doss_list[df_doss_list.projectId.isin(project_list_ids)]
print(f"\n- Number of dossiers after stripping project list {len(df_doss_list.index)}")
# #### [Optional] Export to Excel list of dossier
# In[ ]:
# Export to Excel list of dossier details
df = pd.DataFrame(df_doss_list)
df.to_csv('dossiers_list.csv', index = None,quoting=csv.QUOTE_ALL, encoding='utf-8', sep=",")
# ## Get visualizations for each dossier
# #### Get visualizations
# In[ ]:
doss_list=df_doss_list[["id","projectId"]].values.tolist()
print(f"Length of dossiers list: {len(doss_list)}")
count_dos=0 # this counter will give you hints how long the whole process will take
viz_list=[]
dt1=datetime.now()
for d in doss_list[:]:
viz_def=get_viz_list(mstr_connection, d[0], d[1])
viz_list.extend(viz_def)
count_dos+=1
if (count_dos % 50) == 0 or count_dos == (len(doss_list)):
eta = (len(doss_list[:])/count_dos)*(datetime.now()-dt1)
print(count_dos, "dossiers processed / ETA: ", eta)
df_doss_def = pd.DataFrame(viz_list)
df_doss_def.columns =['Dossier Name', 'id', 'Chapter Name', 'Chapter Key',"Page Name","Page Key", "Visualization ",
"Visualization Key","VisualizationType", "projectId"]
# #### [Optional] Apply Filter : import only dossiers that contain geospatial visualization (map)
# In[ ]:
# OPTIONAL
# Filter only dossiers with Geospatial Viz
df_doss_def=df_doss_def[df_doss_def.VisualizationType.isin(["geospatial_service"])]
# #### Merge dataframes
# In[ ]:
# Merge two dataframes
df_merged = pd.merge(df_doss_list, df_doss_def, on=["id","projectId"])
# #### [Optional] Export to Excel the final results
# In[ ]:
# Export to Excel complete dataset
df = pd.DataFrame(df_merged)
df.to_csv('dossiers_viz.csv', index = None,quoting=csv.QUOTE_ALL, encoding='utf-8', sep=",")
# #### Push data to Platform Analytics for further analysis with user telemetry
# In[ ]:
# Login to Platform Analytics
mstr_connection = Connection(mstr_base_url, mstr_username, mstr_password, project_id=PA_project_id,
login_mode=mstr_login_mode, verbose=False)
cube_name="dossier_details_project_Tutorial"
mstr_dataset = SuperCube(mstr_connection, name=cube_name)
mstr_dataset.add_table(
name="df_merged",
data_frame=df_merged,
update_policy="replace",
to_metric=None,
to_attribute=['name', 'id', 'type', 'description', 'subtype', 'dateCreated',
'dateModified', 'version', 'hidden', 'viewMedia', 'projectId', 'path',
'Dossier Name', 'Chapter Name', 'Chapter Key', 'Page Name', 'Page Key',
'Visualization ', 'Visualization Key', 'VisualizationType']
)
mstr_dataset.create(folder_id="D3C7D461F69C4610AA6BAA5EF51F4125")
# In[ ]: