# dashboard { #powerbpy.dashboard }

`dashboard`

A python class used to model a power BI dashboard project

## Classes

| Name | Description |
| --- | --- |
| [Dashboard](#powerbpy.dashboard.Dashboard) | A python class used to model a power BI dashboard project |

### Dashboard { #powerbpy.dashboard.Dashboard }

```python
dashboard.Dashboard(file_path)
```

A python class used to model a power BI dashboard project

#### Parameters {.doc-section .doc-section-parameters}

| Name      | Type   | Description                                                                                                                                                          | Default    |
|-----------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------|
| file_path |        | The path to the directory where you want to store the new dashboard. The directory should not exist yet. The basename of the directory will also be the report name. | _required_ |

#### Returns {.doc-section .doc-section-returns}

| Name   | Type   | Description   |
|--------|--------|---------------|
|        | None   |               |

#### Notes {.doc-section .doc-section-notes}

- To create a new dashboard instance, use either Dashboard.create(dashboard_path) to create a new dashboard or Dashboard.create(dashboard_path) to load an existing dashboard.
- The dashboard uses a .pbip/.pbir format with TMDL enabled.
- To publish this type of dashboard you will need to either use git enabled workspaces OR convert to a .pbit template and then to a .pbix file before publishing
- These annoyances are worth it because the .pbir + TMDL format is the only one that allows real version control and programatic manipulation of the report using these functions.
- (.pbip uses mimified json by default and throws an error when it's given unpacked json).

- Time intelligence and relationship autodection are turned off by default

#### Methods

| Name | Description |
| --- | --- |
| [add_blob_csv](#powerbpy.dashboard.Dashboard.add_blob_csv) | Add a csv file store in a ADLS blob container to a dashboard |
| [add_local_csv](#powerbpy.dashboard.Dashboard.add_local_csv) | Add a locally stored CSV file to a dashboard |
| [add_tmdl](#powerbpy.dashboard.Dashboard.add_tmdl) | Add a locally stored TMDL file to the dashboard |
| [create](#powerbpy.dashboard.Dashboard.create) | Create a new dashboard.      |
| [get_measures_list](#powerbpy.dashboard.Dashboard.get_measures_list) | Returns a list of DAX measures in the report |
| [list_pages](#powerbpy.dashboard.Dashboard.list_pages) | List all pages associated with a dashboard |
| [load](#powerbpy.dashboard.Dashboard.load) | Load an existing dashboard from a file path |
| [load_page](#powerbpy.dashboard.Dashboard.load_page) | Load an existing page |
| [new_page](#powerbpy.dashboard.Dashboard.new_page) | Create a new blank dashboard page |

##### add_blob_csv { #powerbpy.dashboard.Dashboard.add_blob_csv }

```python
dashboard.Dashboard.add_blob_csv(
    data_path,
    account_url,
    blob_name,
    tenant_id=None,
    use_saved_storage_key=False,
    sas_url=None,
    storage_account_key=None,
    warnings=True,
)
```

Add a csv file store in a ADLS blob container to a dashboard

###### Parameters {.doc-section .doc-section-parameters}

| Name                  | Type   | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          | Default    |
|-----------------------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------|
| account_url           |        | The url to your Azure storage account. It should be in the format of https://<YOUR STORAGE ACCOUNT NAME>.blob.core.windows.net/. You can find it in Azure Storage Explorer by clicking on the storage account and then looking at the blob endpoint field                                                                                                                                                                                                                                                            | _required_ |
| blob_name             |        | The name of the blob container. In Azure Storage Explorer, click on the storage account, then inside "Blob Containers" will be all your blob containers. Use the node dislay name field.                                                                                                                                                                                                                                                                                                                             | _required_ |
| data_path             |        | The relative path to the file you want to load from the blob. It should be relative to blob_name                                                                                                                                                                                                                                                                                                                                                                                                                     | _required_ |
| tenant_id             |        | The tenant id of the tenant where your storage account is stored. This field is only used with browser authentication. (The default).                                                                                                                                                                                                                                                                                                                                                                                | `None`     |
| use_saved_storage_key |        | This optional argument tells python to look in your system's default credential manager for an Azure Storage Account token and prompt the user to add one if it's not there. USE WITH CAUTION, THE STORAGE ACCOUNT TOKENS ALLOW FOR A MASSIVE AMOUNT OF ACCESS. CONSIDER USING SAS URLS OR INTERACTIVE BROWSER AUTHENTICATION INSTEAD.                                                                                                                                                                               | `False`    |
| sas_url               |        | A limited time single access url scoped to just the file you want to grant read access to. To generate one from Azure Storage Explorer, right click on the file you want and then choose "Get Shared Access Signature"                                                                                                                                                                                                                                                                                               | `None`     |
| storage_account_key   |        | It is not recommended to use this when running this function on a local computer. Hardcoding credentials into code is SUPER BAD practice. Please set use_saved_storage_key to true instead. It will store the key securely in your operating system's credential manger. You should only pass a storage account key to the function if you are running this code in a cloud environment such as databricks and using that cloud platform's secure secret manager. (Something like Github Secrets or Azure Key Vault) | `None`     |

###### Returns {.doc-section .doc-section-returns}

| Name   | Type   | Description   |
|--------|--------|---------------|
|        | None   |               |

###### Notes {.doc-section .doc-section-notes}

DO NOT HARD CODE CREDENTIALS. Use the use_saved_storage_key option instead.

This function creates custom M code and is therefore more picky than pandas or Power BI desktop.
The csv file should probably not have row numbers. (Any column without a column name will be renamed to "probably_an_index_column")
NA values must display as "NA" or "null" not as N/A.
If the data is malformed in Power BI, try cleaning it first in python and then rerunning this function.

This function creates a new TMDL file defining the dataset in TMDL format and also in M code.
The DiagramLayout and Model.tmdl files are updated to include refrences to the new dataset.
Other dumb things: If you get an error when trying to open the .pbip file try changing the combatibility version to 1567 in the semanticmodel > definition > database.tmdl file.

Dashboards created with the Dashboard.create() function start with the compatibility version set to 1567, so you should only have this problem with manually created dashboards.
I may eventually add an automatic fix for this.

##### add_local_csv { #powerbpy.dashboard.Dashboard.add_local_csv }

```python
dashboard.Dashboard.add_local_csv(data_path)
```

Add a locally stored CSV file to a dashboard

###### Parameters {.doc-section .doc-section-parameters}

| Name      | Type   | Description                                                                                                                                                                                  | Default    |
|-----------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------|
| data_path |        | The path where the csv file is stored. Can be a relative path. The M code requires a full path, but this python function will help you resolve any valid relative paths to an absolute path. | _required_ |

###### Returns {.doc-section .doc-section-returns}

| Name    | Type   | Description                                |
|---------|--------|--------------------------------------------|
| dataset | class  | An instantce of the LocalCsv dataset class |

###### Notes {.doc-section .doc-section-notes}

This function creates custom M code and is therefore more picky than pandas or Power BI desktop.
The csv file should probably not have row numbers. (Any column without a column name will be renamed to "probably_an_index_column")
NA values must display as "NA" or "null" not as N/A.
If the data is malformed in Power BI, try cleaning it first in python and then rerunning this function.

This function creates a new TMDL file defining the dataset in TMDL format and also in M code.
The DiagramLayout and Model.tmdl files are updated to include refrences to the new dataset.

##### add_tmdl { #powerbpy.dashboard.Dashboard.add_tmdl }

```python
dashboard.Dashboard.add_tmdl(data_path=None, add_default_datetable=True)
```

Add a locally stored TMDL file to the dashboard

###### Parameters {.doc-section .doc-section-parameters}

| Name                  | Type   | Description                                                                                                                                                      | Default   |
|-----------------------|--------|------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------|
| data_path             |        | The path where the tmdl file is stored.                                                                                                                          | `None`    |
| add_default_datetable |        | Do you want the TMDL file you add to be our team's custom date table? This will allow you to create your own date heirarchies instead of using time intelligence | `True`    |

###### Notes {.doc-section .doc-section-notes}

- TMDL is a data storage format automatically created by power BI consisting of a table and column definitions and the M code used to generate the dataset.
- In practice this means that you can copy datasets between dashboards. You can use this function to automatically copy the TMDL files at scale
- Potential pitfalls: M needs full paths to load data. If the new dashboard doesn't have access to the same data as the old dashboard, the data copying may fail.

##### create { #powerbpy.dashboard.Dashboard.create }

```python
dashboard.Dashboard.create(file_path)
```

Create a new dashboard.     
my_dashboard = Dashboard.create(dashboard_path)

###### Parameters {.doc-section .doc-section-parameters}

| Name      | Type   | Description   | Default    |
|-----------|--------|---------------|------------|
| file_path |        |               | _required_ |
| The       |        |               | _required_ |

###### Returns {.doc-section .doc-section-returns}

| Name   | Type                               | Description   |
|--------|------------------------------------|---------------|
|        | An instance of the dashboard class |               |

###### Notes {.doc-section .doc-section-notes}

- To create a new dashboard instance, use this function `Dashboard.create(dashboard_path)`
- To load an existing dashboard use `Dashboard.load(dashboard_path)`

##### get_measures_list { #powerbpy.dashboard.Dashboard.get_measures_list }

```python
dashboard.Dashboard.get_measures_list(
    export_type='markdown',
    output_file_path='',
    starts_with='formatString:',
)
```

Returns a list of DAX measures in the report

###### Parameters {.doc-section .doc-section-parameters}

| Name             | Type   | Description                                                                                                                                                                                                                  | Default           |
|------------------|--------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------|
| export_type      |        | Export type for the function result: export to a .xlsx file (parameter value 'xlsx'), to a .csv file (parameter value 'csv'), or output in markdown format without saving (parameter value 'markdown'')                      | `'markdown'`      |
| output_file_path |        | The path for export (if the export_type value is specified as '.xlsx' or '.csv'). Example: "D:/PBI project/blank_template/", export result will be stored as "D:/PBI project/blank_template/blank_template - measures.xlsx"" | `''`              |
| starts_with      |        | Technical parameter for measure selection. Default options is 'formatString:', for older reports without formatString in the measure definition try using 'lineageTag:' instead                                              | `'formatString:'` |

###### Returns {.doc-section .doc-section-returns}

| Name   | Type                                                                                                                                                                                                                                      | Description   |
|--------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|
|        | Returns a list of DAX measures used in the report in the specified format (see param export_type): the measure name, its definition, the table it belongs to, and the description (if available); prints \"Measures not found\" otherwise |               |

##### list_pages { #powerbpy.dashboard.Dashboard.list_pages }

```python
dashboard.Dashboard.list_pages()
```

List all pages associated with a dashboard

###### Parameters {.doc-section .doc-section-parameters}

| Name   | Type   | Description   | Default    |
|--------|--------|---------------|------------|
| None   |        |               | _required_ |

###### Returns {.doc-section .doc-section-returns}

| Name   | Type   | Description                                              |
|--------|--------|----------------------------------------------------------|
| pages  | list   | This returns a list of all the page_ids in the dashboard |

###### Notes {.doc-section .doc-section-notes}

Use this function to get a list of all the page_ids associated with a dashboard. The list of page_ids is determined from reading the "test_dashboard/test_dashboard.Report/definition/pages/pages.json" file.
This assumes that page_ids listed in the page.json match the folder names.

##### load { #powerbpy.dashboard.Dashboard.load }

```python
dashboard.Dashboard.load(file_path)
```

Load an existing dashboard from a file path

###### Parameters {.doc-section .doc-section-parameters}

| Name      | Type   | Description   | Default    |
|-----------|--------|---------------|------------|
| file_path |        |               | _required_ |
| The       |        |               | _required_ |

###### Returns {.doc-section .doc-section-returns}

| Name   | Type   | Description   |
|--------|--------|---------------|
|        | None   |               |

###### Notes {.doc-section .doc-section-notes}

- To load an existing dashboard, use this function `Dashboard.load(dashboard_path)`
- To create a new dashboard instance use `Dashboard.create(dashboard_path)`

##### load_page { #powerbpy.dashboard.Dashboard.load_page }

```python
dashboard.Dashboard.load_page(page_id)
```

Load an existing page

###### Parameters {.doc-section .doc-section-parameters}

| Name    | Type   | Description                                 | Default    |
|---------|--------|---------------------------------------------|------------|
| page_id |        | The page_id of the page you'd like to load. | _required_ |

###### Returns {.doc-section .doc-section-returns}

| Name   | Type   | Description                                                                           |
|--------|--------|---------------------------------------------------------------------------------------|
| _Page  | class  | This returns an instance of the Page class corresponding to the page you just loaded. |

###### Notes {.doc-section .doc-section-notes}

You should use this function to load an existing page from a power BI report as an instance of the Page class. This lets you call Page methods such as those that add visuals.
To list all page ids you can use `Dashboard.list_pages()`. You can also check the .pbip folder structure to find the page ids

##### new_page { #powerbpy.dashboard.Dashboard.new_page }

```python
dashboard.Dashboard.new_page(
    page_name,
    title=None,
    subtitle=None,
    display_option='FitToPage',
)
```

Create a new blank dashboard page

###### Parameters {.doc-section .doc-section-parameters}

| Name           | Type   | Description                                                                                                                                                                          | Default       |
|----------------|--------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|
| page_name      |        | The display name for the page you just created. This is different from the page_id which is only used internally.                                                                    | _required_    |
| title          |        | Title to put at the top of the page. This under the hood calls the add_text_box() function. If you would like more control over the title's appearance use that function instead.    | `None`        |
| subtitle       |        | Subtitle to put at the top of the page. This under the hood calls the add_text_box() function. If you would like more control over the title's appearance use that function instead. | `None`        |
| display_option |        | Default way to display the page for end users (View -> Page View options in Power BI). Possible options: FitToPage, FitToWidth, ActualSize                                           | `'FitToPage'` |

###### Returns {.doc-section .doc-section-returns}

| Name        | Type   | Description                                                                                                                                                                                                                                                                                                             |
|-------------|--------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| new_page_id | str    | The unique id for the page you just created. If you used this function it will be in the format page1, page2, page3, page4, etc. If you manually create a page it will be a randomly generated UUID. To find a page's page id, consult the report > definition> pages > page.json file and look in the page order list. |

###### Notes {.doc-section .doc-section-notes}

In order to reference the page to add visuals to it later, you'll need to remember what order you created the pages in. The first page that is created when you first call `create_new_dashboard()` is called "page1", the next page you create is called "page2", the page after that is called "page3" etc. (I'm going to convert the functions to classes and methods soon at which point this paragraph will become irrelevant).

In our example, I'll create a new page called "Bee Colonies" and then we'll add a title called "The bees are in trouble!" and a subtitle below it called "We're losing bee colonies". The title and subtitle arguments make a best guess about the best font and position for the text boxes that make up the title and subtitle. These arguments are optional, so if you don't want a title or subtitle, just leave the argument blank. If you want the title to have a different font, style, position, etc from the default use the `add_text_box()` function.
Here's the code to create a new (mostly blank) page:

```python
    my_dashboard.new_page(page_name = "Bee Colonies",
               title= "The bees are in trouble!",
               subtitle = "We're losing bee colonies")
```

Here's what the new page looks like in Power BI Desktop
![New Page Example](https://github.com/Russell-Shean/powerbpy/raw/main/docs/assets/images/new_page_example.png?raw=true "Example Page")