Forum Discussion
Power BI Report creation through Script
- 1 year ago
Hi everyone,
A quick update so I am able to create reports in a programatic fashion it looks like:def create_model_bim(tables, output_folder): # Load a fresh copy of the model template model_bim = copy.deepcopy(model_template) # Replace {{query_order}} annotation for annotation in model_bim["model"].get("annotations", []): if annotation.get("value") == "{{query_order}}": annotation["value"] = str([tbl["name"] for tbl in tables]) # Build table_column_map to validate relationships later table_column_map = {} with open("Static/data_type_mapping.json") as f: type_mapping = json.load(f) model_bim["model"]["tables"] = [] for table in tables: column_names = [col["name"] for col in table["columns"]] table_dict = { "name": table["name"], "columns": [ { "name": col["name"], "dataType": type_mapping.get(col["type"].lower(), "string"), "sourceColumn": col["name"] } for col in table["columns"] ], "partitions": [ { "name": f"{table['name']}_Partition", "mode": "import", "source": { "type": "m", "expression": ( f"let Source = Sql.Database(\"server_name\", \"database_name\") " f"in Source{{[Schema=\"dbo\", Item=\"{table['name']}\"]}}[Data]" ) } } ] } model_bim["model"]["tables"].append(table_dict) # table_column_map[table["name"]] = [col["name"] for col in table["columns"]] table_column_map[table["name"]] = column_names # ✅ Load relationships sheet and parse valid entries # metadata_path = os.path.join(os.path.dirname(output_folder), "Files", "MetaData.xlsx") metadata_path = os.path.abspath(os.path.join(output_folder, "..", "..", "Files", "MetaData.xlsx")) # relationships = extract_relationships_from_metadata(metadata_path) relationships = extract_relationships_from_metadata(metadata_path, table_column_map) if relationships: model_bim["model"]["relationships"] = relationships measures = extract_measures_from_metadata(metadata_path) if measures: measures_table = { "name": "__Measures", "columns": [ { "name": "Dummy", "dataType": "string" } ], "measures": measures, "partitions": [ { "name": "__Measures_Partition", "mode": "import", "source": { "type": "m", "expression": "let Source = #table({\"Dummy\"}, {}) in Source" } } ] } model_bim["model"]["tables"].append(measures_table) # Write model.bim to file bim_path = os.path.join(output_folder, "model.bim") with open(bim_path, "w", encoding="utf-8") as file: json.dump(model_bim, file, indent=4) print(f"✅ model.bim created at: {bim_path}") #-- Report.json file creation: def create_valid_report_json(report_folder_path, chart_types_df, chart_axes_df): base_config = copy.deepcopy(report_static_config["config"]) def create_visual_config(visual_type, visual_index, axes): visual_id = str(uuid.uuid4()) layout = { "id": 0, "position": { "x": 100.0 + (visual_index % 2) * 450.0, "y": 100.0 + (visual_index // 2) * 350.0, "z": 0, "width": 400.0, "height": 300.0, "tabOrder": 0 } } projections = {} selects = [] from_tables = set() for axis_type, axis_list in axes.items(): projections[axis_type] = [] for axis in axis_list: table = axis['table_name'] column = axis['column'] full_ref = f"{table}.{column}" from_tables.add(table) if axis.get('aggregation'): agg_func = 0 # sum projections[axis_type].append({"queryRef": f"Sum({full_ref})"}) selects.append({ "Aggregation": { "Expression": { "Column": { "Expression": {"SourceRef": {"Source": table}}, "Property": column } }, "Function": agg_func }, "Name": f"Sum({full_ref})", "NativeReferenceName": f"Sum of {column}" }) else: projections[axis_type].append({"queryRef": full_ref, "active": True}) selects.append({ "Column": { "Expression": {"SourceRef": {"Source": table}}, "Property": column }, "Name": full_ref, "NativeReferenceName": column }) visual_config = { "name": visual_id, "layouts": [layout], "singleVisual": { "visualType": visual_type, "projections": projections, "prototypeQuery": { "Version": 2, "From": [{"Name": t, "Entity": t, "Type": 0} for t in from_tables], "Select": selects }, "drillFilterOtherVisuals": True, "hasDefaultSort": True, "objects": {}, "vcObjects": { "title": [ { "properties": { "text": { "expr": { "Literal": { "Value": f"'{visual_type.title()} Visual {visual_index + 1}'" } } } } } ] } } } return visual_config visual_containers = [] for idx, row in chart_types_df.iterrows(): visual_type = row.get('plot_type') worksheet = row.get('worksheet') if not visual_type or not worksheet: continue # Skip incomplete rows relevant_axes = chart_axes_df[ (chart_axes_df['worksheet'] == worksheet) & (chart_axes_df['type'].isin(['rows', 'cols'])) & # (chart_axes_df['order_id'] == 0) & (chart_axes_df['table_name'].notna()) ] axes_dict = {} for axis_type in ['rows', 'cols']: group = relevant_axes[relevant_axes['type'] == axis_type] if not group.empty: axes_dict['Category' if axis_type == 'rows' else 'Y'] = group.apply( lambda axis_row: { 'table_name': axis_row['table_name'], 'column': axis_row['column'], 'aggregation': str(axis_row.get('aggregation', '')).strip().lower() == 'sum' }, axis=1 ).tolist() if axes_dict: config = create_visual_config(visual_type, idx, axes_dict) container = { "config": json.dumps(config), "filters": "[]", "height": 300.0, "width": 400.0, "x": 100.0 + (idx % 2) * 450.0, "y": 100.0 + (idx // 2) * 350.0, "z": 0.0 } visual_containers.append(container) report_json = { "config": json.dumps(base_config), "layoutOptimization": 0, "resourcePackages": [], "sections": [ { "config": "{}", "displayName": "Auto Page", "displayOption": 1, "filters": "[]", "height": 720.0, "name": str(uuid.uuid4()), "visualContainers": visual_containers, "width": 1280.0 } ] } output_path = os.path.join(report_folder_path, "report.json") with open(output_path, "w", encoding="utf-8") as f: json.dump(report_json, f, indent=4) print(f"✅ report.json with {len(visual_containers)} visuals written at: {output_path}")
Hi Sidhant ,
Thank you for reaching out to the Microsoft Community Forum.
Can you please refer the Microsoft official documents.
Run Python scripts in Power BI Desktop - Power BI | Microsoft Learn
Create Power BI visuals using Python in Power BI Desktop - Power BI | Microsoft Learn
Use an external Python IDE with Power BI - Power BI | Microsoft Learn
If my response has resolved your query, please mark it as the Accepted Solution to assist others. Additionally, a 'Kudos' would be appreciated if you found my response helpful.
Thank you
Hi v-dineshya ,
The thing is I am trying to use scripts to create the visuals using the pbip file format so the documentation links that you gave I assume that are to be used inside Power BI Desktop (In Get Data-> Python script), but that not my requirement mine is different:
So I was able to fix some issues:
So now I am able to open the pbip file but even after adding the connection reference for data on visuals I am not able to see the add columns option which we ususally get
So if you have any idea let me know.
Regards,
Sidhant.
- v-dineshya1 year agoCommunity Support
Hi Sidhant ,
Thank you for reaching out to the Microsoft Community Forum.
Please follow these steps:
1. Add Custom Visuals to Your Project
If your visuals are custom visuals, you need to: Download the custom .pbiviz files for the visuals you're using (barchart, linechart, etc.). Place them in the correct location and register them in your pbip project.If you're unsure which custom visuals are needed, open the report.json and look under visualContainers -> config -> singleVisual -> visualType to identify them.
2. Reference Them in capabilities.json or the Report Definition: You’ll also need to ensure these visuals are referenced in the project metadata. That often means: Adding them to the visualPlugins array. Making sure their capabilities (like dataRoles) are defined properly so Power BI knows what fields can go in which bucket
3. Field Wells Appear Only if Visual is Valid: Once a visual is loaded successfully, Power BI Desktop will enable the field wells (X-axis, Y-axis, legend, etc.). You won’t get the “add data fields here” option unless: The visual is recognized.
It has defined data roles in its capabilities. The dataset is connected and valid
If my response has resolved your query, please mark it as the Accepted Solution to assist others. Additionally, a 'Kudos' would be appreciated if you found my response helpful.
Thank you- v-dineshya1 year agoCommunity Support
Hi Sidhant ,
If my response has resolved your query, please mark it as the Accepted Solution to assist others. Additionally, a 'Kudos' would be appreciated if you found my response helpful.
Thank you- v-dineshya1 year agoCommunity Support
Hi Sidhant ,
If my response has resolved your query, please mark it as the Accepted Solution to assist others. Additionally, a 'Kudos' would be appreciated if you found my response helpful.
Thank you