Tutorial: Crie um fluxo de trabalho de atualização de estado

Neste tutorial de ponta a ponta, cria um fluxo de tarefas translítico que acompanha o estado do projeto, escreve atualizações numa base de dados e publica notificações de um relatório Power BI no Microsoft Teams. A solução mantém um histórico completo de todas as atualizações de estado, para que possa acompanhar como o estado do projeto mudou ao longo do tempo. Este tutorial demonstra como combinar a escrita de dados com chamadas de API externas para criar um fluxo de trabalho completo de comunicação.

Neste tutorial, aprenderás como:

  • Crie uma base de dados SQL no Fabric com tabelas de monitorização de projetos e de estado que mantenham o histórico completo.
  • Configura uma biblioteca de variáveis para armazenar a configuração separadamente.
  • Configure funções de dados de utilizador que atualizem o estado, solicitem atualizações e publiquem notificações no Teams.
  • Opcionalmente, configura atalhos para a Casa do Lago com vistas materializadas para o lago para vistas diretas para o Lago.
  • Integre as funções dos dados do utilizador num relatório Power BI utilizando botões de funções de dados.

Se você não tiver uma capacidade de Fabric existente, inicie uma avaliação de Fabric.

Pré-requisitos

  • Power BI Desktop. Se não tiver o Power BI Desktop instalado no seu dispositivo, siga as instruções em Obter o Power BI Desktop.
  • Um canal do Microsoft Teams onde tens permissão para adicionar webhooks recebidos.

Descrição geral

Este tutorial cria uma solução de acompanhamento de projetos onde os utilizadores podem atualizar o estado do projeto diretamente a partir de um relatório do Power BI. Quando um utilizador atualiza um estado, o sistema:

  1. Escreve o novo estado na base de dados SQL, mantendo um histórico completo de todas as atualizações de estado.
  2. Envia uma notificação do Adaptive Card para o Microsoft Teams.
  3. Atualiza o relatório para mostrar os dados atualizados.

Fluxo de utilizador

O fluxo de trabalho cria um ciclo contínuo de feedback entre os utilizadores do relatório:

  1. Solicitar atualização através do Teams a partir do relatório — Um utilizador seleciona um projeto no relatório e envia um pedido de atualização de estado. A solicitação é publicada no Teams com um link de retorno para o relatório.

  2. Receber notificações no Teams e abrir o relatório — O proprietário do projeto vê a notificação no Teams e seleciona o link para abrir o relatório.

  3. Atualizar estado no relatório — O proprietário do projeto seleciona o projeto, escolhe um novo estado, adiciona notas e seleciona o botão de atualização.

  4. Ver atualização em tempo real e enviar notificação — O relatório atualiza-se imediatamente para mostrar o novo estado, e uma notificação é publicada no Teams a confirmar a alteração.

Arquitetura

A solução liga estes componentes dentro do Microsoft Fabric:

Componente Purpose
Base de Dados SQL Fabric Armazena registos de projetos e atualizações de estado com histórico completo. Contém a tabela Project, a tabela Status updates (que mantém um histórico completo de todas as alterações) e a vista Project status.
Casa do Lago (opcional) Fornece atalhos para as tabelas da base de dados SQL para visualizações Direct Lake. Use quando precisar de vistas materializadas para o lago para análises.
Biblioteca de variáveis Armazena valores de configuração como o URL do webhook do Teams e o URL do relatório. Atualizar valores sem republicar funções.
Funções de dados do usuário Funções em Python que tratam da escrita de retorno para SQL e enviam notificações para o Microsoft Teams por meio de Adaptive Cards.
Modelo Semântico do Power BI Define o modelo de dados, as relações e as medidas. Construído com o relatório no Power BI Desktop, mas existe como um item separado no serviço Power BI.
Power BI Relatório A interface de utilizador onde os utilizadores visualizam projetos, selecionam novos estados e acionam atualizações através de botões de função de dados.
Microsoft Teams Recebe notificações do Cartão Adaptativo com alterações de estado e liga de volta ao relatório.

Os dados fluem em duas direções:

  • Caminho de leitura: O Power BI lê da base de dados SQL (via DirectQuery) ou do Lakehouse (via Direct Lake) para mostrar o estado atual do projeto.
  • Caminho de escrita: Quando um utilizador seleciona um botão de função de dados, o Power BI chama a função de dados do utilizador, que escreve na base de dados SQL e publica no Teams.

Criar um banco de dados SQL

Este cenário utiliza dados de acompanhamento de projetos. Siga os passos em Criar uma base de dados SQL no Fabric para criar uma nova base de dados SQL no seu espaço de trabalho do Fabric.

Criar as tabelas da base de dados

  1. Na tua base de dados SQL, abre uma nova janela de consulta.

  2. Execute o seguinte script SQL para criar a tabela do Projeto:

    CREATE TABLE [Project] (
        [Project id] INT NOT NULL,
        [Project name] NVARCHAR(200) NOT NULL,
        [Product name] NVARCHAR(200),
        [Description] NVARCHAR(4000),
        [Priority] NVARCHAR(20),
        [Start date] DATE,
        [Target end date] DATE,
        [Budget] DECIMAL(18,2),
        [Project manager] NVARCHAR(100),
        [Department] NVARCHAR(100),
        [Created date] DATETIME2,
        [Created by] NVARCHAR(100),
        [Is active] BIT,
        CONSTRAINT PK_Project PRIMARY KEY NONCLUSTERED ([Project id])
    );
    
  3. Crie a tabela de atualizações de estado para acompanhar as alterações de estado ao longo do tempo:

    CREATE TABLE [Status updates] (
        [Update id] INT NOT NULL,
        [Project id] INT NOT NULL,
        [Status] NVARCHAR(50) NOT NULL,
        [Updated date] DATETIME2 NOT NULL,
        [Updated by] NVARCHAR(100) NOT NULL,
        [Notes] NVARCHAR(4000),
        CONSTRAINT PK_StatusUpdates PRIMARY KEY NONCLUSTERED ([Update id])
    );
    
  4. Crie uma vista que devolve o estado mais recente de cada projeto:

    CREATE VIEW [Project status] AS
    SELECT 
        p.[Project id],
        p.[Project name],
        COALESCE(ls.[Latest status], 'Not Started') AS [Latest status],
        ls.[Latest notes]
    FROM [Project] p
    LEFT JOIN (
        SELECT 
            [Project id],
            [Status] AS [Latest status],
            [Notes] AS [Latest notes],
            ROW_NUMBER() OVER (PARTITION BY [Project id] ORDER BY [Update id] DESC) AS RowNum
        FROM [Status updates]
    ) ls ON p.[Project id] = ls.[Project id] AND ls.RowNum = 1;
    
  5. Insira dados de projeto de exemplo:

    INSERT INTO [Project] ([Project id], [Project name], [Product name], [Description], [Priority], [Start date], [Target end date], [Budget], [Project manager], [Department], [Created date], [Created by], [Is active])
    VALUES
    (1, 'Best Practices with Power BI - FabCon Atlanta', 'FabCon Atlanta', 'Session covering Power BI best practices for enterprise deployments', 'High', '2026-01-15', '2026-03-20', 5000.00, 'person1@somecompany.com', 'Developer Relations', '2026-01-15', 'Admin', 1),
    (2, 'Translytical Task Flows - Build', 'Microsoft Build', 'Deep dive into translytical workloads and real-time analytics patterns', 'Critical', '2026-02-01', '2026-05-19', 7500.00, 'person2@somecompany.com', 'Product Engineering', '2026-02-01', 'Admin', 1),
    (3, 'Advanced DAX Patterns - FabCon Barcelona', 'FabCon Barcelona', 'Workshop on complex DAX calculations and optimization techniques', 'High', '2026-03-01', '2026-09-15', 6000.00, 'person1@somecompany.com', 'Developer Relations', '2026-02-20', 'Admin', 1),
    (4, 'Semantic Modeling Deep Dive - Ignite', 'Microsoft Ignite', 'Comprehensive session on semantic model design and best practices', 'High', '2026-01-10', '2026-11-18', 8000.00, 'person2@somecompany.com', 'Product Engineering', '2026-01-10', 'Admin', 1),
    (5, 'Custom Visuals in Power BI - FabCon Atlanta', 'FabCon Atlanta', 'Hands-on lab for building custom visuals with the Power BI SDK', 'Medium', '2025-12-01', '2026-03-20', 4500.00, 'person1@somecompany.com', 'Developer Relations', '2025-12-01', 'Admin', 1),
    (6, 'TMDL for Version Control - Build', 'Microsoft Build', 'Session on using TMDL for semantic model source control and CI/CD', 'Critical', '2025-11-15', '2026-02-15', 5500.00, 'person2@somecompany.com', 'Product Engineering', '2025-11-15', 'Admin', 1),
    (7, 'Real-time Analytics with Power BI - Ignite', 'Microsoft Ignite', 'Showcase of Direct Lake and real-time streaming capabilities', 'High', '2026-02-10', '2026-11-18', 7000.00, 'person1@somecompany.com', 'Developer Relations', '2026-02-10', 'Admin', 1),
    (8, 'Semantic Modeling Workshop - FabCon Barcelona', 'FabCon Barcelona', 'Interactive workshop on building enterprise-grade semantic models', 'High', '2026-04-01', '2026-09-15', 6500.00, 'person2@somecompany.com', 'Product Engineering', '2026-02-25', 'Admin', 1);
    
  6. Inserir atualizações de estado de exemplo:

    INSERT INTO [Status updates] ([Update id], [Project id], [Status], [Updated date], [Updated by], [Notes])
    VALUES
    (1, 1, 'Not Started', '2026-01-15', 'person1@somecompany.com', 'Session abstract submitted and approved'),
    (2, 1, 'In Progress', '2026-01-25', 'person1@somecompany.com', 'Outline completed, starting slide deck'),
    (3, 1, 'In Progress', '2026-02-10', 'person1@somecompany.com', 'Demo environment setup in progress'),
    (4, 1, 'In Progress', '2026-02-25', 'person1@somecompany.com', 'First draft of presentation complete, scheduling dry run'),
    (5, 2, 'Not Started', '2026-02-01', 'person2@somecompany.com', 'Session proposal accepted for Build'),
    (6, 2, 'In Progress', '2026-02-08', 'person2@somecompany.com', 'Research phase - gathering customer scenarios'),
    (7, 2, 'In Progress', '2026-02-15', 'person2@somecompany.com', 'Architecture diagrams drafted'),
    (8, 2, 'In Progress', '2026-02-24', 'person2@somecompany.com', 'Building demo lakehouse environment'),
    (9, 3, 'Not Started', '2026-02-20', 'person1@somecompany.com', 'Call for speakers submission pending review'),
    (10, 4, 'Not Started', '2026-01-10', 'person2@somecompany.com', 'Initial brainstorming session with PM team'),
    (11, 4, 'In Progress', '2026-01-20', 'person2@somecompany.com', 'Content outline approved by leadership'),
    (12, 4, 'In Progress', '2026-02-05', 'person2@somecompany.com', 'Sample semantic models being developed'),
    (13, 5, 'Not Started', '2025-12-01', 'person1@somecompany.com', 'Lab environment requirements documented'),
    (14, 5, 'In Progress', '2025-12-15', 'person1@somecompany.com', 'SDK samples being prepared'),
    (15, 5, 'On Hold', '2026-01-10', 'person1@somecompany.com', 'Paused - waiting on SDK v5 release for new features'),
    (16, 6, 'Not Started', '2025-11-15', 'person2@somecompany.com', 'Session planning initiated'),
    (17, 6, 'In Progress', '2025-12-01', 'person2@somecompany.com', 'GitHub Actions workflow samples created'),
    (18, 6, 'In Progress', '2026-01-15', 'person2@somecompany.com', 'Dry run completed with internal team'),
    (19, 6, 'Completed', '2026-02-15', 'person2@somecompany.com', 'Session delivered at internal summit, ready for Build'),
    (20, 7, 'Not Started', '2026-02-10', 'person1@somecompany.com', 'Topic approved for Ignite breakout session'),
    (21, 7, 'In Progress', '2026-02-18', 'person1@somecompany.com', 'Eventstream demo scenarios identified'),
    (22, 7, 'In Progress', '2026-02-26', 'person1@somecompany.com', 'Direct Lake performance benchmarks in progress'),
    (23, 8, 'Not Started', '2026-02-25', 'person2@somecompany.com', 'Workshop format and duration confirmed');
    

Configurar uma biblioteca de variáveis

Uma biblioteca de variáveis armazena valores de configuração separadamente do seu código de função. Esta separação oferece um benefício chave: permite atualizar valores como URLs de webhooks ou links de relatórios sem a necessidade de editar ou republicar as funções de dados do utilizador.

Por exemplo, se o seu canal do Teams mudar ou precisar de apontar para outro relatório, atualize o valor da biblioteca de variáveis e a alteração entra em vigor imediatamente — não são necessárias alterações no código.

  1. No seu espaço de trabalho Fabric, seleciona + Novo item.

  2. Role para baixo até a seção Desenvolver dados e selecione Biblioteca de variáveis.

  3. Nomeie a biblioteca ProjectVariables de variáveis e selecione Criar.

  4. Selecionar + Nova variável e adicionar as seguintes variáveis:

    Nome da variável Tipo Descrição
    TEAMS_WEBHOOK_URL String URL do seu webhook recebido no Teams
    POWERBI_REPORT_URL String URL do seu relatório Power BI (adicionado após a publicação)
  5. Selecione Guardar depois de adicionar cada variável.

Obtenha uma URL de webhook do Teams

Siga os passos em Criar um Webhook Recebido para criar um webhook para o seu canal no Teams. Depois de criar o webhook, copie o URL e adicione-o à sua biblioteca de variáveis como TEAMS_WEBHOOK_URL.

Importante

Qualquer pessoa com este URL pode publicar mensagens no seu canal do Teams.

Criar as funções de dados do utilizador

Crie um item de funções de dados de utilizador que trate de atualizações de estado e notificações do Teams.

  1. No seu espaço de trabalho Fabric, selecione + Novo item>Funções de Dados de Utilizador.

  2. Substitua o código padrão pelo seguinte código Python:

    import fabric.functions as fn
    import logging
    from datetime import datetime
    
    udf = fn.UserDataFunctions()
    
    
    @udf.connection(argName="sqlDb", alias="ProjectTrackingDb")
    @udf.connection(argName="varLib", alias="ProjectVariables")
    @udf.function()
    def update_project_status(
        sqlDb: fn.FabricSqlConnection,
        varLib: fn.FabricVariablesClient,
        projectId: int,
        newStatus: str,
        updatedBy: str,
        notes: str,
        updatedDate: str
    ) -> str:
        """
        Updates the status of a project by inserting a new record 
        into the Status updates table and sends a Teams notification.
        """
        logging.info(f"Updating status for Project ID: {projectId}")
    
        # Parse and validate the date
        try:
            parsed_date = datetime.fromisoformat(updatedDate)
        except ValueError:
            raise fn.UserThrownError(
                f"Invalid date format. Use ISO format: '2026-02-27T14:30:00'",
                {"providedDate": updatedDate}
            )
    
        # Validate status value
        valid_statuses = ['Not Started', 'In Progress', 'On Hold', 'Completed', 'Cancelled']
        if newStatus not in valid_statuses:
            raise fn.UserThrownError(
                f"Invalid status. Must be one of: {', '.join(valid_statuses)}",
                {"providedStatus": newStatus}
            )
    
        connection = sqlDb.connect()
        cursor = connection.cursor()
    
        try:
            # Get the previous status
            cursor.execute("""
                SELECT TOP 1 [Status] 
                FROM [Status updates] 
                WHERE [Project id] = ? 
                ORDER BY [Update id] DESC
            """, (projectId,))
            prev_row = cursor.fetchone()
            previous_status = prev_row[0] if prev_row else "Not Started"
    
            # Get the next Update ID
            cursor.execute("SELECT ISNULL(MAX([Update id]), 0) + 1 FROM [Status updates]")
            next_update_id = cursor.fetchone()[0]
    
            # Verify the project exists
            cursor.execute("SELECT [Project name] FROM [Project] WHERE [Project id] = ?", (projectId,))
            project_row = cursor.fetchone()
    
            if not project_row:
                raise fn.UserThrownError(f"Project with ID {projectId} not found.")
    
            project_name = project_row[0]
    
            # Insert the new status update
            cursor.execute("""
                INSERT INTO [Status updates] 
                ([Update id], [Project id], [Status], [Updated date], [Updated by], [Notes])
                VALUES (?, ?, ?, ?, ?, ?)
            """, (next_update_id, projectId, newStatus, parsed_date, updatedBy, notes))
    
            connection.commit()
    
            # Send Teams notification
            _send_teams_update(varLib, project_name, previous_status, newStatus, updatedBy, notes)
    
            return f"Status updated for '{project_name}': {previous_status} → {newStatus}"
    
        except Exception as e:
            connection.rollback()
            raise
        finally:
            cursor.close()
            connection.close()
    
    
    def _send_teams_update(varLib, project_name, previous_status, new_status, updated_by, notes):
        """Helper function to send Teams notification."""
        import requests
        import json
    
        variables = varLib.getVariables()
        webhook_url = variables.get("TEAMS_WEBHOOK_URL")
        report_url = variables.get("POWERBI_REPORT_URL")
    
        if not webhook_url:
            return
    
        adaptive_card = {
            "type": "message",
            "attachments": [{
                "contentType": "application/vnd.microsoft.card.adaptive",
                "content": {
                    "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
                    "type": "AdaptiveCard",
                    "version": "1.4",
                    "body": [
                        {
                            "type": "TextBlock",
                            "size": "Large",
                            "weight": "Bolder",
                            "text": "📋 Project Status Update"
                        },
                        {
                            "type": "FactSet",
                            "facts": [
                                {"title": "Project:", "value": project_name},
                                {"title": "Status:", "value": f"{previous_status} → {new_status}"},
                                {"title": "Updated By:", "value": updated_by}
                            ]
                        },
                        {
                            "type": "TextBlock",
                            "text": f"**Notes:** {notes}" if notes else "",
                            "wrap": True
                        }
                    ],
                    "actions": [
                        {"type": "Action.OpenUrl", "title": "View Project", "url": report_url}
                    ] if report_url else []
                }
            }]
        }
    
        requests.post(webhook_url, headers={"Content-Type": "application/json"}, 
                      data=json.dumps(adaptive_card), timeout=30)
    
    
    @udf.connection(argName="sqlDb", alias="ProjectTrackingDb")
    @udf.connection(argName="varLib", alias="ProjectVariables")
    @udf.function()
    def request_status_update(
        sqlDb: fn.FabricSqlConnection,
        varLib: fn.FabricVariablesClient,
        projectId: int,
        requestedBy: str,
        message: str
    ) -> str:
        """
        Sends a Teams notification requesting a status update for a project.
        """
        logging.info(f"Requesting status update for Project ID: {projectId}")
    
        connection = sqlDb.connect()
        cursor = connection.cursor()
    
        try:
            # Get project details
            cursor.execute("""
                SELECT [Project name], [Project manager] 
                FROM [Project] 
                WHERE [Project id] = ?
            """, (projectId,))
            project_row = cursor.fetchone()
    
            if not project_row:
                raise fn.UserThrownError(f"Project with ID {projectId} not found.")
    
            project_name = project_row[0]
            project_manager = project_row[1]
    
            # Get current status
            cursor.execute("""
                SELECT TOP 1 [Status], [Updated date]
                FROM [Status updates] 
                WHERE [Project id] = ? 
                ORDER BY [Update id] DESC
            """, (projectId,))
            status_row = cursor.fetchone()
            current_status = status_row[0] if status_row else "Not Started"
            last_updated = status_row[1].strftime("%Y-%m-%d") if status_row else "Never"
    
            # Send Teams notification
            _send_status_request(varLib, project_name, project_manager, 
                                current_status, last_updated, requestedBy, message)
    
            return f"Status update requested for '{project_name}' from {project_manager}"
    
        finally:
            cursor.close()
            connection.close()
    
    
    def _send_status_request(varLib, project_name, project_manager, current_status, 
                            last_updated, requested_by, message):
        """Helper function to send status update request via Teams."""
        import requests
        import json
    
        variables = varLib.getVariables()
        webhook_url = variables.get("TEAMS_WEBHOOK_URL")
        report_url = variables.get("POWERBI_REPORT_URL")
    
        if not webhook_url:
            return
    
        adaptive_card = {
            "type": "message",
            "attachments": [{
                "contentType": "application/vnd.microsoft.card.adaptive",
                "content": {
                    "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
                    "type": "AdaptiveCard",
                    "version": "1.4",
                    "body": [
                        {
                            "type": "TextBlock",
                            "size": "Large",
                            "weight": "Bolder",
                            "text": "📢 Status Update Requested"
                        },
                        {
                            "type": "FactSet",
                            "facts": [
                                {"title": "Project:", "value": project_name},
                                {"title": "Owner:", "value": project_manager},
                                {"title": "Current Status:", "value": current_status},
                                {"title": "Last Updated:", "value": last_updated},
                                {"title": "Requested By:", "value": requested_by}
                            ]
                        },
                        {
                            "type": "TextBlock",
                            "text": f"**Message:** {message}" if message else "",
                            "wrap": True
                        }
                    ],
                    "actions": [
                        {"type": "Action.OpenUrl", "title": "Update Status", "url": report_url}
                    ] if report_url else []
                }
            }]
        }
    
        requests.post(webhook_url, headers={"Content-Type": "application/json"}, 
                      data=json.dumps(adaptive_card), timeout=30)
    
  3. Configure as ligações:

    • Selecione Definições ou o painel de ligações.
    • Adicionar ligação ProjectTrackingDb à sua base de dados SQL Fabric.
    • Adicione uma ligação ProjectVariables para a sua Biblioteca de Variáveis.
  4. Selecione Publicar para implementar a função.

Observação

As funções usadas com os botões de dados do Power BI devem devolver uma cadeia (-> str). O Power BI apresenta este valor de retorno ao utilizador após a execução da função, fornecendo feedback sobre o resultado da ação.

Compreender a função update_project_status

A update_project_status função escreve um novo registo de estado na base de dados SQL e envia uma notificação no Teams. Quando um utilizador seleciona o botão de atualização no relatório, ocorre o seguinte fluxo:

Diagrama que mostra o fluxo de dados ao atualizar o estado do projeto: O Power BI chama a função, que escreve para a base de dados SQL e envia uma notificação no Teams.

  1. O Power BI chama a função - O botão da função de dados passa parâmetros (ID do projeto, novo estado, notas, etc.) para a função de dados do utilizador.

  2. Validar entradas - A função valida o formato de data e verifica se o valor de estado é uma das opções permitidas.

  3. Consultar estado atual - A função recupera o estado anterior e o nome do projeto da base de dados.

  4. Inserir novo registo - Uma nova linha é inserida na Status updates tabela com o novo estado, carimbo temporal e notas.

  5. Enviar notificação do Teams - A função _send_teams_update auxiliar publica um Cartão Adaptativo no seu canal do Teams a mostrar a alteração de estado.

  6. Devolver resultado - A função devolve uma mensagem de sucesso que o Power BI apresenta ao utilizador.

Compreenda a função request_status_update

A request_status_update função envia uma notificação no Teams a pedir ao proprietário do projeto que forneça uma atualização de estado. Esta função não escreve na base de dados — apenas envia uma mensagem.

Diagrama que mostra o fluxo de dados ao solicitar uma atualização de estado: O Power BI chama a função, que consulta detalhes do projeto e envia uma notificação no Teams.

  1. O Power BI chama a função - O botão da função de dados passa o ID do projeto, o nome do requerente e a mensagem para a função.

  2. Consultar detalhes do projeto - A função recupera o nome do projeto, o gestor de projeto e o estado atual da base de dados.

  3. Enviar notificação Teams - A função _send_status_request auxiliar publica um Cartão Adaptativo no seu canal Teams com os detalhes do pedido e um botão Atualizar Estado do Projeto que liga de volta ao relatório.

  4. Resultado de retorno - A função devolve uma mensagem de confirmação que o Power BI apresenta ao utilizador.

(Opcional) Preparar atalhos do Lakehouse para vistas diretas do Lago

O Fabric SQL Database armazena todos os dados como tabelas Delta no OneLake, por isso podes criar um modelo semântico Direct Lake diretamente nas tabelas da base de dados SQL. No entanto, o Direct Lake não consegue ler vistas de uma base de dados SQL — apenas tabelas. Para usar uma vista com o Direct Lake, crie atalhos para as tabelas da base de dados SQL num Lakehouse e depois defina a vista aí.

Criar atalhos para as tabelas da base de dados SQL

  1. No teu espaço de trabalho Fabric, cria um novo Lakehouse e ativa os esquemas.

  2. No Lakehouse Explorer, clique com o botão direito em qualquer esquema (como o dbo) e selecione o atalho de Nova tabela.

  3. No Catálogo OneLake, navegue até à sua base de dados SQL e selecione a Project tabela.

  4. Repita para criar um atalho para a tabela Status updates.

Os atalhos fornecem acesso de leitura às tabelas Delta subjacentes sem duplicar dados.

Captura de ecrã a mostrar as opções do Lakehouse para adicionar atalhos e vistas materializadas do lago.

Crie uma vista materializada do lago

Crie uma vista materializada do lago na Casa do Lago que calcule o estado mais recente de cada projeto:

  1. Na Casa do Lago, selecione Gerir vistas materializadas do lago (pré-visualização).

  2. Abra um novo caderno com Spark SQL.

  3. Execute a seguinte consulta:

    CREATE MATERIALIZED LAKE VIEW IF NOT EXISTS dbo.project_status AS
    SELECT 
        p.`Project id` AS ProjectId,
        p.`Project name` AS ProjectName,
        COALESCE(ls.LatestStatus, 'Not Started') AS LatestStatus,
        ls.LatestNotes
    FROM dbo.Project p
    LEFT JOIN (
        SELECT 
            `Project id` AS ProjectId,
            `Status` AS LatestStatus,
            `Notes` AS LatestNotes,
            ROW_NUMBER() OVER (PARTITION BY `Project id` ORDER BY `Update id` DESC) AS RowNum
        FROM dbo.`Status updates`
    ) ls ON p.`Project id` = ls.ProjectId AND ls.RowNum = 1;
    
  4. Agendar a atualização da vista selecionando Programações>Ativo e definindo a frequência.

Captura de ecrã que mostra o calendário materializado da vista do lago e as opções de criação.

Observação

A base de dados SQL mantém-se como destino de escrita para as funções de dados do utilizador. Os atalhos do Lakehouse proporcionam acesso apenas de leitura para análises através da vista materializada para o lago.

Criar o relatório Power BI

Pode ligar-se aos seus dados usando DirectQuery ou Direct Lake:

  • DirectQuery para Base de Dados SQL: Dados em tempo real permitem escrita através das funções de dados dos utilizadores.
  • Tabelas Direct Lake para Base de Dados SQL: A Fabric SQL Database armazena os dados como tabelas Delta no OneLake, para que o Direct Lake possa ler tabelas diretamente.
  • Direct Lake via Lakehouse (para vistas): Direct Lake não consegue ler vistas da base de dados SQL. Para usar as views com o Direct Lake, crie atalhos para as tabelas da base de dados SQL num Lakehouse e depois defina as vistas materializadas do lago aí.

Sugestão

O modo de importação também pode ser usado — não há limitação no modo de armazenamento. Com o Import, o modelo semântico deve ser atualizado antes de os valores atualizados aparecerem no relatório.

Opção A: Conectar-se via DirectQuery

  1. Abra Power BI Desktop.

  2. Selecione o catálogo OneLake.

  3. Encontre a sua base de dados SQL do Fabric.

  4. Selecione Ligar ao endpoint de análise SQL.

  5. Selecione as tabelas/vista Project, Status updates e Project status.

  6. Quando solicitado para o modo de armazenamento, selecione DirectQuery.

Captura de ecrã que mostra o modelo semântico DirectQuery no Power BI.

Opção B: Conectar-se via Direct Lake (para desempenho analítico)

  1. No serviço Power BI, selecione Criar>catálogo OneLake.

  2. Encontra o teu Lakehouse.

  3. Selecione as tabelas de atalhos (Project, Status updates) e a visualização materializada do lago (project_status).

  4. Edite o modelo semântico na experiência de modelação web para adicionar medidas e relações.

Observação

Com o Direct Lake, os nomes das colunas da vista materializada do lago não têm espaços (por exemplo, ProjectId em vez de Project id). Renomeie as colunas no modelo semântico para corresponderem às suas medidas.

Captura de ecrã que mostra o modelo semântico do Direct Lake no Power BI.

Criar a tabela calculada das Opções de Status

Crie uma tabela calculada que forneça os valores de estado para o slicer de botão. Execute este script TMDL na aplicação Power BI Desktop:

createOrReplace

	table 'Status Options'

		column Status
			summarizeBy: none
			isNameInferred
			sourceColumn: [Status]
			sortByColumn: 'Sort Order'

		column Description
			summarizeBy: none
			isNameInferred
			sourceColumn: [Description]

		column 'Sort Order'
			isHidden
			formatString: 0
			summarizeBy: sum
			isNameInferred
			sourceColumn: [Sort Order]

		column 'Status Color'
			summarizeBy: none
			isNameInferred
			sourceColumn: [Status Color]

		partition 'Status Options' = calculated
			mode: import
			source =
				DATATABLE(
				    "Status", STRING,
				    "Description", STRING,
				    "Sort Order", INTEGER,
				    "Status Color", STRING,
				    {
				        { "Not Started", "Project has been created but work has not begun", 1, "#808080" },
				        { "In Progress", "Active work is being performed on the project", 2, "#0078D4" },
				        { "On Hold", "Project is paused pending resources, decisions, or dependencies", 3, "#FFB900" },
				        { "Completed", "All project deliverables have been finished", 4, "#107C10" },
				        { "Cancelled", "Project has been terminated and will not be completed", 5, "#D13438" }
				    }
				)

Criar medidas de apoio

Crie uma tabela calculada para conter as medidas que suportam os botões da função de dados. Execute este script TMDL na aplicação Power BI Desktop:

createOrReplace

	table 'Translytical task flow'

		/// Generates a preview of the Teams notification that will be sent when the user updates the status. Shows a warning if required selections are missing.
		measure 'Preview of status update' = ```
				VAR _ProjectId = SELECTEDVALUE(Project[Project id], 0)
				VAR _ProjectName = SELECTEDVALUE(Project[Project name], "")
				VAR _PreviousStatus = [Latest Status]
				VAR _NewStatus = SELECTEDVALUE('Status Options'[Status], "N/A")
				VAR _UpdatedBy = [Updated by]
				VAR _UpdatedDate = FORMAT(NOW(), "YYYY-MM-DD HH:mm")
				VAR _NL = UNICHAR(10)
				RETURN 
				IF(_ProjectId = 0 || _NewStatus = "N/A",
				    "⚠️ Select a project and new status to preview",
				    "📋 Teams Notification Preview" & _NL &
				    "━━━━━━━━━━━━━━━━━━━━" & _NL &
				    "Project: " & _ProjectName & _NL &
				    "Status: " & _PreviousStatus & " → " & _NewStatus & _NL &
				    "Updated By: " & _UpdatedBy & _NL &
				    "Date: " & _UpdatedDate & _NL &
				    "Notes: See above" & _NL &
				    "━━━━━━━━━━━━━━━━━━━━" & _NL &
				    "📨 This will be sent to Teams"
				)
				```

		/// Returns the email address of the current user. Used to track who made each status update.
		measure 'Updated by' = USERPRINCIPALNAME()

		/// Returns the most recent notes for the selected project. Only evaluates when a project is in scope.
		measure 'Latest notes' =
				IF(ISINSCOPE(Project[Project name]),
				LASTNONBLANKVALUE('Status updates'[Update id], MAX('Status updates'[Notes])),
				BLANK())

		/// Returns the most recent status for the selected project by finding the last non-blank status value.
		measure 'Latest status' =
				IF(HASONEVALUE(Project[Project id]),
				LASTNONBLANKVALUE('Status updates'[Update id], MAX('Status updates'[Status])),
				BLANK())

		/// Returns the Project ID when a single project is selected. Used as a parameter for the update_project_status and request_status_update functions.
		measure 'Selected project id' = SELECTEDVALUE(Project[Project id])
			formatString: 0

		/// Returns today's date in ISO format. Used as the timestamp for status updates.
		measure 'Updated date' = FORMAT(TODAY(), "yyyy-mm-dd")

		/// Provides dynamic text for the update button showing the selected project and new status.
		measure 'Update status button text' = "Update the status of " & SELECTEDVALUE(Project[Project name]) & " to " & SELECTEDVALUE('Status Options'[Status])

		column Value
			isHidden
			formatString: 0
			summarizeBy: sum
			isNameInferred
			sourceColumn: [Value]

		partition 'Translytical task flow' = calculated
			mode: import
			source = {1}

Observação

Este script cria a Translytical task flow tabela com uma coluna oculta. Esconder todas as colunas converte-o numa tabela de medidas, que exibe um ícone especial e aparece sempre no topo do painel de Dados para fácil acesso.

Estas medidas têm múltiplos propósitos:

Medida Purpose
Selected project id Captura o ID do Projeto quando uma única linha do projeto é selecionada. Passado como parâmetro para as funções que lidam com dados do utilizador.
Updated by Retorna o email do utilizador atual via USERPRINCIPALNAME(). Acompanha quem fez cada atualização de status.
Updated date Devolve a data de hoje em formato ISO (yyyy-mm-dd) para o parâmetro de carimbo temporal da função.
Update status button text Fornece rotulagem dinâmica de botões que mostra o projeto selecionado e o novo estado (por exemplo, "Atualizar o estado da Sessão ABC para Em Progresso").
Latest status Mostra o estado mais recente de um projeto usando LASTNONBLANKVALUE para encontrar a última entrada na tabela de atualizações de estado.
Latest notes Mostra as notas mais recentes de um projeto. Só avalia quando um projeto específico está dentro do âmbito.
Preview of status update Gera uma pré-visualização da notificação do Teams antes de enviar, ajudando os utilizadores a confirmar as alterações. Mostra um aviso se faltarem seleções.

Conceber o relatório

O layout do relatório orienta os utilizadores através de um fluxo de trabalho claro: selecionar um projeto, escolher um novo estado, adicionar notas e depois executar a atualização.

Captura de ecrã que mostra o design completo do relatório Power BI com tabela de projetos, slicer de estado, entradas de notas e botões de ação.

Cria a tabela de projetos

  1. Adicione uma Tabela visual para mostrar a informação do projeto.

  2. Adicione estas colunas a partir dos seus dados:

    • Product name
    • Project name
    • Target end date
    • Description
    • Latest status (a partir da tabela/vista de Estado ou Estado do Projeto)
    • Latest notes
  3. Defina o título para 1) Escolha um projeto para atualizar.

  4. Ordena por data de fim alvo ascendente para mostrar primeiro os prazos que se aproximam.

Crie um slicer de botões para seleção de estado

  1. Adiciona um visual cortador de botões.

  2. No campo Valores , adicione Status Options[Status].

  3. No campo Rótulo , adicione FIRST(Status Options[Description]) para mostrar a descrição abaixo de cada estado.

  4. No painel "Formato":

    • Definir o estilo das cartas.
    • Defina a orientação para horizontal.
    • Defina o máximo de azulejos para 5 (um para cada estado).
  5. Configure a formatação condicional para colorir cada carta pelo Status Color campo.

  6. Defina o título para 2) Escolha um novo estado.

Adicionar segmentadores de entrada para notas

  1. Adicione um Input slicer para que os utilizadores possam inserir notas sobre a atualização de estado.

  2. Defina o título para 3) Adicione notas para esta atualização de estado.

  3. Adicione outro filtro de entrada para o campo de mensagem utilizado pelo botão de atualização do estado da solicitação.

  4. Define o título para Ou envia uma mensagem para o canal das equipas.

Sugestão

Dê a cada fatiador de entrada um título descritivo. Quando configuras um botão de função de dados, os segmentadores aparecem no menu suspenso dos parâmetros pelo seu título, tornando mais fácil identificar o correto. Após a configuração, pode esconder o título na tela do relatório se necessário.

Adicionar a tabela de pré-visualização

  1. Adicione uma visualização de Tabela com uma única coluna: a [Preview of status update] métrica.

  2. Defina o título para Atualização de Antevisão.

Isto mostra aos utilizadores como será a notificação do Teams antes de a enviarem.

Adicionar os botões da função de dados

Adicione dois botões: um para atualizar o estado e outro para pedir uma atualização de estado.

Botão de atualização de estado

  1. No separador Inserir, selecione Botão>Função de Dados.

  2. No painel de Formato , configure o texto do botão:

    • Defina o texto padrão para a sua [Update status button text] medida para rotulagem dinâmica.
    • Defina texto desativado para texto estático como "Escolha um projeto, novo estado, e adicione notas primeiro".
  3. Selecione a sua função publicada update_project_status .

  4. Mapear os parâmetros da função:

    Parâmetro Tipo de vinculação Vinculado a
    projectId Medida [Selected project id] Medida
    newStatus Cortador Visual do cortador de botões (auto-apagar ativado)
    updatedBy Medida [Updated by] Medida
    notes Cortador Visual do slicer de entrada (auto-limpeza ativada)
    updatedDate Medida [Updated date] Medida
  5. No painel de Formato em Ação, ative a Atualização do relatório após o resultado bem-sucedido. Esta configuração atualiza automaticamente a página do relatório após a execução bem-sucedida da função.

    Sugestão

    Ative Auto-clear para os parâmetros do slicer para que o botão do slicer e o texto das notas sejam reiniciados após o utilizador ativar a função.

Observação

A opção Atualizar o relatório após o resultado bem-sucedido só atualiza a página do relatório quando a função é executada com sucesso. Para os modos de armazenamento DirectQuery e Direct Lake, a página atualizada mostra dados atualizados imediatamente. Para o modo Importação, o modelo semântico deve ser atualizado separadamente antes de os valores atualizados aparecerem no relatório.

Captura de ecrã que mostra o botão de atualização de estado do projeto no relatório do Power BI.

Botão de solicitar atualização de estado

  1. Adiciona outra função de Botão>Data.

  2. No painel de Formato , configure o texto do botão:

    • Defina o texto padrão para texto estático, como "Enviar mensagem do Teams para o canal".
    • Defina o texto desativado para "Escolha um projeto e escreva uma mensagem primeiro".
  3. Selecione a sua função publicada request_status_update .

  4. Mapear os parâmetros da função:

    Parâmetro Tipo de vinculação Vinculado a
    projectId Medida [Selected project id] Medida
    requestedBy Medida [Updated by] Medida
    message Cortador Visual do slicer de entrada (auto-limpeza ativada)
  5. Ative opcionalmente Atualizar o relatório após o resultado bem-sucedido no painel Formato sob Ação.

Captura de ecrã que mostra o botão de enviar mensagem do Teams no relatório Power BI.

Configurar texto dinâmico de botões

Use texto dinâmico nos seus botões da função de dados para mostrar aos utilizadores exatamente que ação ocorrerá quando selecionarem o botão. Em vez de um rótulo genérico como "Atualizar", o botão pode mostrar texto específico do contexto, como "Atualizar o estado da Sessão ABC para Em Progresso."

Para configurar o texto dinâmico dos botões:

  1. Crie uma medida que gere a etiqueta do botão. Por exemplo, esta medida combina o nome do projeto selecionado e o novo estado:

    Update status button text = 
        "Update the status of " & SELECTEDVALUE(Project[Project name]) & " to " & SELECTEDVALUE('Status Options'[Status])
    
  2. No painel Formatar do botão da função de dados, expanda Botão>Texto.

  3. Defina a sua medida dinâmica com o texto padrão ([Update status button text]).

  4. Defina texto desativado como texto estático que indique aos utilizadores quais as seleções necessárias (por exemplo, "Escolha um projeto, novo estado e adicione notas primeiro").

O botão mostra o texto desativado até que todos os parâmetros necessários tenham valores. Depois de o utilizador fazer as suas escolhas, o botão mostra o texto dinâmico que descreve a ação específica.

Captura de ecrã que mostra o painel de formato de botão com configuração dinâmica de texto, usando uma medida para texto padrão e texto estático para o estado desativado.

(Opcional) Adicione um botão de navegação detalhada e página

Pode adicionar uma página de análise detalhada para mostrar o histórico completo das atualizações de estado de um projeto selecionado.

  1. No separador Inserir , selecione Botão>em Branco.

  2. No painel de Formatação sob Botão, defina o texto:

    • Texto padrão: "Ver todas as atualizações de estado"
    • Texto desativado: "Escolha um projeto para ver todas as atualizações de estado"
  3. Em Ação, ative a ação e defina:

    • Tipo: Drillthrough
    • Destino: Selecione a sua página de histórico de estado (criada nos próximos passos)
  4. Adicione uma nova página e chame-lhe Histórico de atualizações de estado.

  5. No painel de Formato da página, expanda Informações da página e ative o Drillthrough. Adiciona Project[Product name] como campo de perfuração.

  6. Adicione elementos visuais para mostrar o histórico de estado:

    • Cartão: Total de atualizações de estado
    • Seccionador de botões: Divisão por estado
    • Tabela: Todas as atualizações de estado (ID de atualização, Data de atualização, Estado, Notas, Atualizado por)
    • Gráfico de linhas: Atualizar a atividade ao longo do tempo
  7. Adicione um botão Voltar para que os utilizadores possam voltar à página principal do relatório. No separador Inserir, selecione Botão>Voltar.

Publicar o relatório

  1. Guarde o seu relatório e publice-o no serviço Power BI.

  2. Copie a URL do relatório e adicione-a à sua biblioteca de variáveis como POWERBI_REPORT_URL.

Testar o fluxo de trabalho

Teste o fluxo de atualização de estado do pedido

Uma vez publicado, pode usar o fluxo de tarefas translítico para solicitar uma atualização de estado:

Captura de ecrã que mostra os passos numerados para solicitar uma atualização de estado: 1) selecionar um projeto, 2) introduzir uma mensagem, 3) selecionar Enviar mensagem do Teams para o canal, 4) ver confirmação, 5) Notificação do Teams aparece com o botão Atualizar Estado do Projeto.

  1. Escolha um projeto para atualizar - Selecione uma linha de projeto na tabela para definir o contexto do filtro.

  2. Ou enviar uma mensagem para o canal do Teams - Inserir uma mensagem no campo de entrada (por exemplo, "Podemos ter uma atualização sobre isto?").

  3. Selecione o botão Enviar mensagem das equipas para o canal .

  4. Uma confirmação de pedido submetido aparece quando a ação é concluída com sucesso.

  5. Verifique o seu canal do Teams para o Cartão Adaptativo de Atualização de Estado do Projeto com os detalhes da solicitação.

  6. O proprietário do projeto pode selecionar Atualizar Estado do Projeto no Cartão Adaptativo para abrir o relatório e atualizar o seu estado.

Captura de ecrã que mostra a notificação do Cartão Adaptativo no Teams a pedir uma atualização de estado com o botão Atualizar Estado do Projeto.

Teste o fluxo de estado da atualização

Uma vez publicado, pode usar o fluxo de tarefas translítico para atualizar o estado de um projeto:

Captura de ecrã que mostra os passos numerados para atualizar o estado de um projeto: 1) selecionar um projeto, 2) escolher um estado, 3) adicionar notas, 4) selecionar Atualizar, 5) ver confirmação, 6) aparecer uma notificação no Teams.

  1. Escolha um projeto para atualizar - Selecione uma linha de projeto na tabela para definir o contexto do filtro.

  2. Qual é o novo estatuto? - Usar o slicer de botões para selecionar um novo estado (por exemplo, Em Progresso).

  3. Adicionar notas para esta atualização de estado - Inserir notas no slicer de entrada (por exemplo, "Começou a gravar a demo").

  4. Selecione o botão Atualizar para escrever a alteração de estado de volta no lakehouse e enviar uma notificação no Teams.

  5. Uma confirmação de pedido submetido aparece quando a ação é concluída com sucesso.

  6. Verifique o canal do Teams para o Cartão Adaptativo de Atualização de Estado do Projeto com os detalhes da alteração de estado.

Captura de ecrã que mostra a notificação do Adaptive Card no Teams após uma atualização de estado.

Fluxos de tarefas transanalíticas

Visuais do relatório

Funções DAX

Dados do Fabric

Microsoft Teams