{
  "nbformat": 4,
  "nbformat_minor": 5,
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "name": "python",
      "version": "3.13.0"
    },
    "blog_metadata": {
      "topic": "Power BI April 2026 feature summary: Copilot, reporting, and analyst productivity updates",
      "slug": "power-bi-april-2026-feature-summary-copilot-reporting-and-an",
      "generated_by": "LinkedIn Post Generator + Azure OpenAI",
      "generated_at": "2026-05-15T16:40:21.319Z"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# Power BI April 2026 feature summary: Copilot, reporting, and analyst productivity updates\n",
        "\n",
        "This notebook turns the April 2026 Power BI feature summary into hands-on validation steps focused on Copilot readiness, reporting productivity, and semantic model governance. The main theme is practical readiness: teams with clean, governed semantic models are best positioned to benefit from AI-assisted authoring and controlled rollout."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "%pip install pandas requests"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "import os\n",
        "import json\n",
        "import requests\n",
        "import pandas as pd\n",
        "from typing import List, Dict, Any"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Example 1: Inventory workspaces and semantic models for Copilot-readiness review\n",
        "\n",
        "This example queries the Power BI REST API to list workspaces and datasets so you can identify candidate semantic models for a pilot. It supports the blog's recommendation to start with trusted workspaces and high-quality models before broader rollout."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### Required environment variables\n",
        "\n",
        "- `POWERBI_AAD_TOKEN`: Azure AD bearer token with permission to call the Power BI REST API."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "import os\n",
        "import requests\n",
        "import pandas as pd\n",
        "\n",
        "TOKEN = os.getenv(\"POWERBI_AAD_TOKEN\", \"\")\n",
        "\n",
        "if not TOKEN:\n",
        "    print(\"Set POWERBI_AAD_TOKEN to run against the live Power BI REST API.\")\n",
        "    sample_rows = [\n",
        "        {\n",
        "            \"workspace\": \"Sales Analytics\",\n",
        "            \"workspaceId\": \"ws-001\",\n",
        "            \"dataset\": \"Revenue Model\",\n",
        "            \"datasetId\": \"ds-001\",\n",
        "            \"configuredBy\": \"bi@contoso.com\",\n",
        "            \"isRefreshable\": True,\n",
        "        },\n",
        "        {\n",
        "            \"workspace\": \"Operations\",\n",
        "            \"workspaceId\": \"ws-002\",\n",
        "            \"dataset\": \"Plant KPI\",\n",
        "            \"datasetId\": \"ds-002\",\n",
        "            \"configuredBy\": \"ops-bi@contoso.com\",\n",
        "            \"isRefreshable\": True,\n",
        "        },\n",
        "    ]\n",
        "    inventory_df = pd.DataFrame(sample_rows)\n",
        "else:\n",
        "    headers = {\"Authorization\": f\"Bearer {TOKEN}\"}\n",
        "    groups_resp = requests.get(\"https://api.powerbi.com/v1.0/myorg/groups\", headers=headers, timeout=30)\n",
        "    groups_resp.raise_for_status()\n",
        "    groups = groups_resp.json().get(\"value\", [])\n",
        "\n",
        "    rows = []\n",
        "    for g in groups:\n",
        "        ds_resp = requests.get(\n",
        "            f\"https://api.powerbi.com/v1.0/myorg/groups/{g['id']}/datasets\",\n",
        "            headers=headers,\n",
        "            timeout=30,\n",
        "        )\n",
        "        ds_resp.raise_for_status()\n",
        "        datasets = ds_resp.json().get(\"value\", [])\n",
        "        for d in datasets:\n",
        "            rows.append(\n",
        "                {\n",
        "                    \"workspace\": g.get(\"name\"),\n",
        "                    \"workspaceId\": g.get(\"id\"),\n",
        "                    \"dataset\": d.get(\"name\"),\n",
        "                    \"datasetId\": d.get(\"id\"),\n",
        "                    \"configuredBy\": d.get(\"configuredBy\"),\n",
        "                    \"isRefreshable\": d.get(\"isRefreshable\"),\n",
        "                }\n",
        "            )\n",
        "    inventory_df = pd.DataFrame(rows)\n",
        "\n",
        "print(inventory_df.head(10).to_string(index=False))"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Example 2: Flag semantic models missing basic governance metadata for analyst productivity\n",
        "\n",
        "This example creates a simple governance checklist and flags whether a semantic model appears ready for Copilot-assisted workflows. It reflects the blog's point that semantic model quality, ownership, endorsement, and sensitivity labeling all influence trustworthy AI-assisted results."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "import pandas as pd\n",
        "\n",
        "df = pd.DataFrame([\n",
        "    {\"workspace\": \"Sales\", \"dataset\": \"Revenue Model\", \"owner\": \"bi@contoso.com\", \"endorsement\": \"Certified\", \"sensitivity\": \"Confidential\"},\n",
        "    {\"workspace\": \"Ops\", \"dataset\": \"Plant KPI\", \"owner\": \"\", \"endorsement\": \"None\", \"sensitivity\": \"\"},\n",
        "    {\"workspace\": \"Finance\", \"dataset\": \"Margin Model\", \"owner\": \"finance-bi@contoso.com\", \"endorsement\": \"Promoted\", \"sensitivity\": \"Internal\"},\n",
        "])\n",
        "\n",
        "df[\"copilot_ready\"] = (\n",
        "    df[\"owner\"].ne(\"\") &\n",
        "    df[\"endorsement\"].isin([\"Promoted\", \"Certified\"]) &\n",
        "    df[\"sensitivity\"].ne(\"\")\n",
        ")\n",
        "\n",
        "print(df[[\"workspace\", \"dataset\", \"owner\", \"endorsement\", \"sensitivity\", \"copilot_ready\"]].to_string(index=False))"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Example 3: Export workspace inventory to CSV for rollout planning and governance review\n",
        "\n",
        "The original post included a PowerShell example for exporting inventory. Here it is translated to Python so you can generate a CSV for rollout planning, governance review, and sharing with BI owners."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### Required environment variables\n",
        "\n",
        "- `POWERBI_AAD_TOKEN`: Azure AD bearer token with permission to call the Power BI REST API."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "import os\n",
        "import requests\n",
        "import pandas as pd\n",
        "\n",
        "TOKEN = os.getenv(\"POWERBI_AAD_TOKEN\", \"\")\n",
        "output_path = \"powerbi-inventory.csv\"\n",
        "\n",
        "if not TOKEN:\n",
        "    rows = [\n",
        "        {\"Workspace\": \"Sales Analytics\", \"WorkspaceId\": \"ws-001\", \"Dataset\": \"Revenue Model\", \"DatasetId\": \"ds-001\", \"Refreshable\": True},\n",
        "        {\"Workspace\": \"Operations\", \"WorkspaceId\": \"ws-002\", \"Dataset\": \"Plant KPI\", \"DatasetId\": \"ds-002\", \"Refreshable\": True},\n",
        "        {\"Workspace\": \"Finance\", \"WorkspaceId\": \"ws-003\", \"Dataset\": \"Margin Model\", \"DatasetId\": \"ds-003\", \"Refreshable\": False},\n",
        "    ]\n",
        "    export_df = pd.DataFrame(rows)\n",
        "else:\n",
        "    headers = {\"Authorization\": f\"Bearer {TOKEN}\"}\n",
        "    groups = requests.get(\"https://api.powerbi.com/v1.0/myorg/groups\", headers=headers, timeout=30).json().get(\"value\", [])\n",
        "    rows = []\n",
        "    for g in groups:\n",
        "        datasets = requests.get(\n",
        "            f\"https://api.powerbi.com/v1.0/myorg/groups/{g['id']}/datasets\",\n",
        "            headers=headers,\n",
        "            timeout=30,\n",
        "        ).json().get(\"value\", [])\n",
        "        for d in datasets:\n",
        "            rows.append(\n",
        "                {\n",
        "                    \"Workspace\": g.get(\"name\"),\n",
        "                    \"WorkspaceId\": g.get(\"id\"),\n",
        "                    \"Dataset\": d.get(\"name\"),\n",
        "                    \"DatasetId\": d.get(\"id\"),\n",
        "                    \"Refreshable\": d.get(\"isRefreshable\"),\n",
        "                }\n",
        "            )\n",
        "    export_df = pd.DataFrame(rows)\n",
        "\n",
        "export_df.to_csv(output_path, index=False)\n",
        "print(f\"Saved {len(export_df)} rows to {output_path}\")\n",
        "print(export_df.head(5).to_string(index=False))"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Example 4: Audit a simple Copilot/preview readiness checklist across BI assets\n",
        "\n",
        "This example mirrors the PowerShell audit logic in Python. It helps validate the blog's recommendation to gate rollout through governance checks and expand only after trusted assets and workspaces show good results."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "import pandas as pd\n",
        "\n",
        "assets = pd.DataFrame([\n",
        "    {\"Workspace\": \"Sales\", \"Dataset\": \"Revenue Model\", \"Endorsement\": \"Certified\", \"Sensitivity\": \"Confidential\", \"Owner\": \"bi@contoso.com\"},\n",
        "    {\"Workspace\": \"Ops\", \"Dataset\": \"Plant KPI\", \"Endorsement\": \"None\", \"Sensitivity\": \"\", \"Owner\": \"\"},\n",
        "    {\"Workspace\": \"Finance\", \"Dataset\": \"Margin Model\", \"Endorsement\": \"Promoted\", \"Sensitivity\": \"Internal\", \"Owner\": \"finance-bi@contoso.com\"},\n",
        "])\n",
        "\n",
        "assets[\"CopilotReady\"] = (\n",
        "    assets[\"Endorsement\"].isin([\"Promoted\", \"Certified\"]) &\n",
        "    assets[\"Sensitivity\"].fillna(\"\").str.strip().ne(\"\") &\n",
        "    assets[\"Owner\"].fillna(\"\").str.strip().ne(\"\")\n",
        ")\n",
        "\n",
        "print(assets[[\"Workspace\", \"Dataset\", \"Endorsement\", \"Sensitivity\", \"Owner\", \"CopilotReady\"]].to_string(index=False))"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Example 5: Visualize the April 2026 update themes as a workflow graph\n",
        "\n",
        "The blog included a Mermaid diagram summarizing how Copilot, reporting, and analyst productivity connect to governance and rollout. Since Mermaid is not native to standard Python notebooks, this cell recreates the flow as a simple directed graph table for validation."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "import pandas as pd\n",
        "\n",
        "edges = [\n",
        "    (\"April 2026 Power BI updates\", \"Copilot\"),\n",
        "    (\"April 2026 Power BI updates\", \"Reporting\"),\n",
        "    (\"April 2026 Power BI updates\", \"Analyst productivity\"),\n",
        "    (\"Copilot\", \"Assess semantic model readiness\"),\n",
        "    (\"Copilot\", \"Review governance metadata\"),\n",
        "    (\"Copilot\", \"Controlled rollout by workspace\"),\n",
        "    (\"Reporting\", \"Validate report dependencies\"),\n",
        "    (\"Reporting\", \"Track certified/promoted assets\"),\n",
        "    (\"Analyst productivity\", \"Export inventories via API\"),\n",
        "    (\"Analyst productivity\", \"Automate admin audits\"),\n",
        "    (\"Analyst productivity\", \"Share CSVs with BI owners\"),\n",
        "]\n",
        "\n",
        "graph_df = pd.DataFrame(edges, columns=[\"source\", \"target\"])\n",
        "print(graph_df.to_string(index=False))"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Summary\n",
        "\n",
        "Key takeaways from the April 2026 update:\n",
        "- Copilot value depends heavily on semantic model quality, naming, measures, and business context.\n",
        "- Reporting productivity improves fastest when the semantic layer is already trustworthy.\n",
        "- Governance should guide rollout, starting with trusted workspaces and high-quality semantic models.\n",
        "- MCP-related patterns are promising, but still early enough to evaluate carefully.\n",
        "\n",
        "## Next Steps\n",
        "\n",
        "1. Run the inventory export against a trusted subset of Power BI workspaces.\n",
        "2. Add governance metadata checks such as endorsement, ownership, and sensitivity labels.\n",
        "3. Identify a small analyst cohort and measure whether Copilot-assisted authoring reduces time to first draft.\n",
        "4. Expand only after validating productivity gains without weakening governance or control."
      ]
    }
  ]
}