Share via


Introdução

Descrição geral

O Microsoft Power Query proporciona uma poderosa experiência de "obtenção de dados" que engloba muitas funcionalidades. Uma das principais capacidades do Power Query é filtrar e combinar, ou seja, "misturar" dados de uma ou mais de uma coleção avançada de origens de dados suportadas. Qualquer mashup de dados é expresso usando a linguagem de fórmula do Power Query (conhecida informalmente como "M"). O Power Query incorpora documentos M numa vasta gama de produtos Microsoft, incluindo Excel, Power BI, Analysis Services e Dataverse, para permitir a combinação repetível de dados.

Este documento fornece a especificação para M. Após uma breve introdução que visa construir alguma primeira intuição e familiaridade com a língua, o documento aborda a linguagem precisamente em várias etapas progressivas:

  1. A estrutura lexical define o conjunto de textos que são lexicamente válidos.

  2. Valores, expressões, ambientes e variáveis, identificadores e o modelo de avaliação formam os conceitos básicos da linguagem.

  3. A especificação detalhada de valores, tanto primitivos como estruturados, define o domínio alvo da linguagem.

  4. Os valores têm tipos, eles próprios um tipo especial de valor, que caracterizam os tipos fundamentais de valores e carregam metadados adicionais que são específicos para as formas de valores estruturados.

  5. O conjunto de operadores em M define que tipos de expressões podem ser formadas.

  6. As funções, outro tipo de valores especiais, fornecem a base para uma rica biblioteca padrão para M e permitem a adição de novas abstrações.

  7. Erros podem ocorrer ao aplicar operadores ou funções durante a avaliação de expressão. Embora os erros não sejam valores, há maneiras de lidar com erros que mapeiam os erros de volta para os valores.

  8. Permita que as expressões permitam a introdução de definições auxiliares usadas para construir expressões complexas em etapas menores.

  9. Se as expressões suportam avaliação condicional.

  10. As seções fornecem um mecanismo de modularidade simples. (As secções ainda não foram aproveitadas pelo Power Query.)

  11. Finalmente, uma gramática consolidada reúne os fragmentos gramaticais de todas as outras seções deste documento em uma única definição completa.

Para os teóricos da linguagem de computador: a linguagem de fórmula especificada neste documento é uma linguagem funcional primariamente pura, de ordem superior, digitada dinamicamente e parcialmente preguiçosa.

Expressões e valores

O constructo central em M é a expressão. Uma expressão pode ser avaliada (calculada), produzindo um único valor.

Embora muitos valores possam ser escritos literalmente como uma expressão, um valor não é uma expressão. Por exemplo, a expressão 1 avalia para o valor 1, as expressões 1+1 avaliam para o valor 2. Esta distinção é subtil, mas importante. As expressões são receitas para avaliação; Os valores são os resultados da avaliação.

Os exemplos a seguir ilustram os diferentes tipos de valores disponíveis em M. Como convenção, um valor é escrito usando a forma literal na qual eles apareceriam em uma expressão que avalia apenas esse valor. (Observe que o indica o início de um comentário que continua até o // final da linha.)

  • Um valor primitivo é um valor de parte única, como um número, lógico, texto ou nulo. Um valor nulo pode ser usado para indicar a ausência de quaisquer dados.

    123                  // A number
    true                 // A logical
    "abc"                // A text
    null                 // null value
    
  • Um valor de lista é uma sequência ordenada de valores. M suporta listas infinitas, mas se escritas como literais, as listas têm um comprimento fixo. Os caracteres {} encaracolados e denotam o início e o fim de uma lista.

    {123, true, "A"}     // list containing a number, a logical, and 
                          //     a text 
    {1, 2, 3}            // list of three numbers 
    
  • Um registo é um conjunto de campos. Um campo é um par nome/valor em que o nome é um valor de texto exclusivo dentro do registro do campo. A sintaxe literal para valores de registro permite que os nomes sejam escritos sem aspas, um formulário também conhecido como identificadores. A seguir mostra um registro contendo três campos chamados "", "", e "ACB", que têm valores 1, , 2e 3.

    [ 
          A = 1,  
          B = 2,  
          C = 3 
    ]
    
  • Uma tabela é um conjunto de valores organizados em colunas (que são identificadas pelo nome) e linhas. Não há sintaxe literal para criar uma tabela, mas há várias funções padrão que podem ser usadas para criar tabelas a partir de listas ou registros.

    Por exemplo:

    #table( {"A", "B"}, { {1, 2}, {3, 4} } ) 
    

    Isso cria uma tabela com a seguinte forma:

    Image of an example table in the M formula language.

  • Uma função é um valor que, quando invocado com argumentos, produz um novo valor. Uma função é escrita listando os parâmetros da função entre parênteses, seguido pelo símbolo =>goes-to, seguido pela expressão que define a função. Essa expressão normalmente se refere aos parâmetros (pelo nome).

    (x, y) => (x + y) / 2`
    

Avaliação

O modelo de avaliação da linguagem M é modelado de acordo com o modelo de avaliação comumente encontrado em planilhas, onde a ordem de cálculo pode ser determinada com base nas dependências entre as fórmulas nas células.

Se tiver escrito fórmulas numa folha de cálculo como o Excel, poderá reconhecer que as fórmulas à esquerda resultam nos valores à direita quando calculadas:

Image of the formulas on the right resulting in the values on the left.

Em M, partes de uma expressão podem fazer referência a outras partes da expressão pelo nome, e o processo de avaliação determina automaticamente a ordem na qual as expressões referenciadas são calculadas.

Você pode usar um registro para produzir uma expressão equivalente ao exemplo de planilha anterior. Ao inicializar o valor de um campo, você pode fazer referência a outros campos dentro do registro usando o nome do campo, da seguinte maneira:

[  
    A1 = A2 * 2,  
    A2 = A3 + 1,  
    A3 = 1  
]

A expressão acima é equivalente à seguinte (na medida em que ambos avaliam valores iguais):

[  
    A1 = 4,  
    A2 = 2,  
    A3 = 1  
]

Os registros podem estar contidos ou aninhados em outros registros. Você pode usar o operador de pesquisa ([]) para acessar os campos de um registro pelo nome. Por exemplo, o registro a seguir tem um campo chamado contendo um registro e um campo chamado TotalSales que acessa os FirstHalfSales campos e SecondHalf do registro:

[  
    Sales = [ FirstHalf = 1000, SecondHalf = 1100 ], 
    Total = Sales[FirstHalf] + Sales[SecondHalf] 
]

A expressão acima é equivalente à seguinte quando avaliada:

[  
    Sales = [ FirstHalf = 1000, SecondHalf = 1100 ], 
    Total = 2100 
]

Os registos também podem constar de listas. Você pode usar o operador de índice posicional ({}) para acessar um item em uma lista por seu índice numérico. Os valores dentro de uma lista são referidos usando um índice baseado em zero desde o início da lista. Por exemplo, os índices 0 e são usados para referenciar o primeiro e 1 segundo itens na lista abaixo:

[ 
    Sales =  
        {  
            [  
                Year = 2007,  
                FirstHalf = 1000,  
                SecondHalf = 1100, 
                Total = FirstHalf + SecondHalf // 2100 
            ], 
            [  
                Year = 2008,  
                FirstHalf = 1200,  
                SecondHalf = 1300, 
                Total = FirstHalf + SecondHalf // 2500 
            ]  
        }, 
    TotalSales = Sales{0}[Total] + Sales{1}[Total] // 4600 
]

Listar e registrar expressões de membros (bem como expressões let) são avaliadas usando avaliação preguiçosa, o que significa que elas são avaliadas apenas conforme necessário. Todas as outras expressões são avaliadas através de uma avaliação ansiosa, o que significa que são avaliadas imediatamente quando encontradas durante o processo de avaliação. Uma boa maneira de pensar sobre isso é lembrar que a avaliação de uma lista ou expressão de registro retorna um valor de lista ou registro que se lembra de como seus itens de lista ou campos de registro precisam ser calculados, quando solicitado (por operadores de pesquisa ou índice).

Funções

Em M, uma função é um mapeamento de um conjunto de valores de entrada para um único valor de saída. Uma função é escrita nomeando primeiro o conjunto necessário de valores de entrada (os parâmetros para a função) e, em seguida, fornecendo uma expressão que calcula o resultado da função usando esses valores de entrada (o corpo da função) seguindo o símbolo goes-to (=>). Por exemplo:

(x) => x + 1                    // function that adds one to a value 
(x, y) =>  x + y                // function that adds two values

Uma função é um valor como um número ou um valor de texto. O exemplo a seguir mostra uma função que é o valor de um campo Add que é então invocado ou executado a partir de vários outros campos. Quando uma função é invocada, um conjunto de valores é especificado que são logicamente substituídos pelo conjunto necessário de valores de entrada dentro da expressão do corpo da função.

[ 
    Add = (x, y) => x + y,
    OnePlusOne = Add(1, 1),     // 2 
    OnePlusTwo = Add(1, 2)      // 3
]

Biblioteca

M inclui um conjunto comum de definições disponíveis para uso a partir de uma expressão chamada biblioteca padrão, ou apenas biblioteca para abreviar. Essas definições consistem em um conjunto de valores nomeados. Os nomes dos valores fornecidos por uma biblioteca estão disponíveis para uso dentro de uma expressão sem terem sido definidos explicitamente pela expressão. Por exemplo:

Number.E                        // Euler's number e (2.7182...) 
Text.PositionOf("Hello", "ll")  // 2

Operadores

M inclui um conjunto de operadores que podem ser usados em expressões. Os operadores são aplicados a operandos para formar expressões simbólicas. Por exemplo, na expressão os números 1 e são operandos e 2 o operador é o operador de adição (+).1 + 2

O significado de um operador pode variar dependendo do tipo de valores que seus operandos são. Por exemplo, o operador plus pode ser usado com outros tipos de valores além dos números:

1 + 2                   // numeric addition: 3 
#time(12,23,0) + #duration(0,0,2,0) 
                        // time arithmetic: #time(12,25,0)

Outro exemplo de um operador com significado dependente de operando é o operador de combinação (&):

"A" & "BC"              // text concatenation: "ABC" 
{1} & {2, 3}            // list concatenation: {1, 2, 3} 
[ a = 1 ] & [ b = 2 ]   // record merge: [ a = 1, b = 2 ]

Observe que alguns operadores não suportam todas as combinações de valores. Por exemplo:

1 + "2"  // error: adding number and text isn't supported

Expressões que, quando avaliadas, encontram condições de operador indefinidas avaliam a erros.

Metadados

Metadados são informações sobre um valor associado a um valor. Os metadados são representados como um valor de registro, chamado de registro de metadados. Os campos de um registro de metadados podem ser usados para armazenar os metadados de um valor.

Cada valor tem um registro de metadados. Se o valor do registro de metadados não tiver sido especificado, o registro de metadados estará vazio (não tem campos).

Os registros de metadados fornecem uma maneira de associar informações adicionais a qualquer tipo de valor de forma discreta. Associar um registro de metadados a um valor não altera o valor ou seu comportamento.

Um valor de registro de metadados é associado a um valor yx existente usando a sintaxe x meta y. Por exemplo, o código a seguir associa um registro de metadados e RatingTags campos com o valor "Mozart"de texto :

"Mozart" meta [ Rating = 5, Tags = {"Classical"} ]

Para valores que já carregam um registro de metadados não vazio, o resultado da aplicação de meta é o de calcular a mesclagem de registro do registro existente e do novo registro de metadados. Por exemplo, as duas expressões a seguir são equivalentes entre si e à expressão anterior:

("Mozart" meta [ Rating = 5 ]) meta [ Tags = {"Classical"} ] 
"Mozart" meta ([ Rating = 5 ] & [ Tags = {"Classical"} ])

Um registro de metadados pode ser acessado para um determinado valor usando a função Value.Metadata . No exemplo a seguir, a expressão no campo acessa ComposerRating o registro de metadados do valor no campo e, em Composer seguida, acessa o Rating campo do registro de metadados.

[ 
    Composer = "Mozart" meta [ Rating = 5, Tags = {"Classical"} ], 
    ComposerRating = Value.Metadata(Composer)[Rating] // 5
]

Deixe a expressão

Muitos dos exemplos mostrados até agora incluíram todos os valores literais da expressão no resultado da expressão. A let expressão permite que um conjunto de valores seja calculado, atribuído nomes e, em seguida, usado em uma expressão subsequente que segue o in. Por exemplo, em nosso exemplo de dados de vendas, você pode fazer:

let 
    Sales2007 =  
        [  
            Year = 2007,  
            FirstHalf = 1000,  
            SecondHalf = 1100, 
            Total = FirstHalf + SecondHalf // 2100 
        ], 
    Sales2008 =  
        [  
            Year = 2008,  
            FirstHalf = 1200,  
            SecondHalf = 1300, 
            Total = FirstHalf + SecondHalf // 2500 
        ] 
  in Sales2007[Total] + Sales2008[Total] // 4600

O resultado da expressão acima é um valor numérico (4600) que é calculado a partir dos valores vinculados aos nomes Sales2007 e Sales2008.

Se expressão

A if expressão seleciona entre duas expressões com base em uma condição lógica. Por exemplo:

if 2 > 1 then
    2 + 2
else  
    1 + 1

A primeira expressão () é selecionada se a expressão lógica () for verdadeira, e a segunda expressão (2 + 22 > 11 + 1) é selecionada se for falsa. A expressão selecionada (neste caso 2 + 2) é avaliada e torna-se o if resultado da expressão (4).

Erros

Um erro é uma indicação de que o processo de avaliação de uma expressão não poderia produzir um valor.

Os erros são gerados por operadores e funções que encontram condições de erro ou usando a expressão de erro. Os erros são tratados usando a try expressão. Quando um erro é gerado, um valor é especificado que pode ser usado para indicar por que o erro ocorreu.

let Sales = 
    [ 
        Revenue = 2000, 
        Units = 1000, 
        UnitPrice = if Units = 0 then error "No Units"
                    else Revenue / Units 
    ], 
    UnitPrice = try Number.ToText(Sales[UnitPrice])
in "Unit Price: " & 
    (if UnitPrice[HasError] then UnitPrice[Error][Message]
    else UnitPrice[Value])

O exemplo acima acessa o campo e formata o valor que produz o Sales[UnitPrice] resultado:

"Unit Price: 2"

Se o campo tivesse sido zero, então o UnitsUnitPrice campo teria gerado um erro, que teria sido tratado pelo try. O valor resultante teria então sido:

"No Units"

Uma try expressão converte valores e erros apropriados em um valor de registro que indica se a try expressão manipulou um erro, ou não, e o valor adequado ou o registro de erro extraído ao manipular o erro. Por exemplo, considere a seguinte expressão que gera um erro e, em seguida, manipula-o imediatamente:

try error "negative unit count"

Esta expressão é avaliada de acordo com o seguinte valor de registro aninhado, explicando as [HasError]pesquisas , [Error]e [Message] campo no exemplo de preço unitário anterior.

[ 
    HasError = true, 
    Error = 
        [ 
            Reason = "Expression.Error", 
            Message = "negative unit count", 
            Detail = null 
        ] 
]

Um caso comum é substituir erros por valores padrão. A try expressão pode ser usada com uma cláusula opcional otherwise para conseguir exatamente isso de forma compacta:

try error "negative unit count" otherwise 42 
// 42