Power Query: como começar na linguagem M
Power Query começar na linguagem M na prática: a estrutura let ... in, cada etapa como variável, tipos e o Editor Avançado para aprender lendo o M.
O código que aparece na barra e assusta quem está aprendendo
Você clica em uma coluna, escolhe uma transformação no menu, e uma linha estranha aparece lá em cima na barra de fórmulas. Depois abre uma tela cheia de let, in, nomes entre aspas e vírgulas, e a sensação é de que só um programador entende aquilo. Não é verdade. Aquilo é a linguagem M, e aprender a ler o M é o caminho mais rápido para deixar de ter medo do Power Query e passar a controlá-lo. Este guia é sobre Power Query começar na linguagem M de um jeito prático, sem enrolação, usando exatamente o código que a própria interface gera para você.
A boa notícia é que você já está escrevendo M sem saber. Cada clique na interface do Power Query vira uma linha de código nos bastidores. Quando você entende a estrutura por trás desses cliques, ganha três coisas: consegue ajustar uma consulta sem refazer tudo, entende por que algo quebrou e escreve transformações que o menu não oferece de forma pronta.
M é uma linguagem funcional, e isso muda como você pensa
Antes de qualquer código, vale entender o que o M é. M é uma linguagem funcional, feita sob medida para uma coisa só: pegar dados de uma fonte, transformá-los passo a passo e devolver uma tabela pronta para o modelo. Ela não foi criada para você programar telas, jogos ou aplicativos. Foi criada para descrever transformação de dados de forma previsível.
Ser funcional, na prática, significa que você descreve o resultado que quer a cada etapa, e não uma sequência de comandos com estado que muda o tempo todo. Cada etapa recebe uma tabela, faz uma coisa e entrega outra tabela. Isso deixa o código fácil de ler de cima para baixo, como uma receita. É o mesmo motor por trás do Power Query no Power BI, no Excel e nos dataflows, então o que você aprende aqui vale para todos eles. Se o seu contexto é montar um ambiente corporativo de relatórios, vale ler também o guia completo de Power BI para empresas no Brasil, porque o M é a base de toda a camada de ingestão.
Todo script M tem a forma let ... in
Esta é a ideia central. Abra qualquer consulta no Editor Avançado e você vai ver a mesma armação:
let
// aqui vão as etapas, uma embaixo da outra
in
// aqui vai o resultado final
O bloco let é onde você define as etapas. O bloco in diz qual etapa é o resultado que a consulta entrega. Simples assim. Tudo que fica entre let e in é uma lista de definições, e o que fica depois do in é o valor final. Veja um exemplo real e mínimo:
let
Fonte = Excel.Workbook(File.Contents("C:\dados\vendas.xlsx"), null, true),
Planilha = Fonte{[Item="Vendas",Kind="Sheet"]}[Data],
Promovido = Table.PromoteHeaders(Planilha, [PromoteAllScalars=true])
in
Promovido
Leia de cima para baixo. A primeira etapa abre o arquivo. A segunda pega a planilha certa. A terceira promove a primeira linha para cabeçalho. O in Promovido diz: entregue o resultado da última etapa. É essa a espinha dorsal de todo código M que você vai encontrar.
Cada etapa é uma variável referenciada pelo nome
Aqui mora o pulo do gato. No M, cada etapa é uma variável. O nome que aparece à esquerda do sinal de igual é o nome da variável, e a etapa seguinte usa esse nome para pegar o resultado da anterior. Repare no exemplo acima: Planilha usa Fonte, e Promovido usa Planilha. É uma corrente, onde cada elo se apoia no anterior.
Isso explica uma coisa que confunde muita gente: os nomes de etapa que aparecem no painel Etapas Aplicadas, à direita da tela, são exatamente esses nomes de variável. Quando você renomeia uma etapa clicando com o botão direito, você está renomeando a variável no código. Por isso, se você renomear uma etapa, o M atualiza a referência nas etapas seguintes para não quebrar a corrente.
A tabela abaixo mostra a correspondência entre o que você vê na interface e o que existe no código:
| Na interface | No código M |
|---|---|
| Cada linha em Etapas Aplicadas | Uma variável dentro do let |
| Nome da etapa | Nome da variável antes do = |
| Ordem das etapas | Ordem das linhas, de cima para baixo |
| A etapa selecionada mostra o resultado | O valor daquela variável |
| Etapa final carregada no modelo | A variável referenciada no in |
Como cada etapa é uma variável independente, você pode inserir uma etapa no meio, remover uma do fim ou reordenar, desde que a corrente de referências continue fazendo sentido. Esse entendimento é o que separa quem depende do menu de quem edita o M com confiança.
O M diferencia maiúsculas de minúsculas, e isso pega muita gente
Grave isto: o M diferencia maiúsculas e minúsculas. Fonte, fonte e FONTE são três nomes diferentes para o M. Isso vale tanto para nomes de etapa quanto para nomes de função. Table.PromoteHeaders funciona, mas table.promoteheaders retorna erro dizendo que o nome não foi reconhecido.
Esse detalhe é a causa número um de frustração de quem está começando. A pessoa copia um trecho de código, troca uma letra sem querer, e o Power Query devolve um erro que parece misterioso. Não é misterioso: é só o M sendo rigoroso com o texto. A tabela abaixo resume os erros mais comuns de digitação:
| O que você escreveu | O que deveria ser | Por que quebra |
|---|---|---|
table.selectrows | Table.SelectRows | Nome de função com caixa errada |
Origem referenciando origem | Nome idêntico ao definido | Maiúscula ou minúscula não bate |
text.upper | Text.Upper | Biblioteca Text sempre com T maiúsculo |
[coluna] sendo [Coluna] na fonte | Nome exato da coluna | Referência a coluna também é sensível |
A regra é simples de seguir: respeite exatamente a caixa que a interface gerou. Quando estiver em dúvida sobre o nome de uma função, use o autocompletar do Editor Avançado, que sugere o nome com a grafia certa.
Os tipos existem, e ignorá-los custa caro
O M trabalha com tipos, e conhecer os principais evita metade dos problemas de carga. Cada valor no M tem um tipo: pode ser texto, número, data, lógico, uma lista, um registro ou uma tabela. Definir o tipo certo em cada coluna não é firula: é o que garante que a data vai ser tratada como data e não como texto, e que o valor decimal não vai ser lido como milhar.
Veja os tipos que você mais vai usar no dia a dia:
| Tipo em M | Para que serve | Exemplo de valor |
|---|---|---|
type text | Texto em geral | "São Paulo" |
Int64.Type | Número inteiro | 1500 |
type number | Número decimal | 1234.56 |
type date | Data sem hora | #date(2026,11,7) |
type datetime | Data com hora | #datetime(2026,11,7,9,30,0) |
type logical | Verdadeiro ou falso | true |
Para fixar tipos numa tabela, o M usa a função Table.TransformColumnTypes. Este é o código que a interface gera quando você clica no ícone de tipo no cabeçalho da coluna:
let
Fonte = Csv.Document(File.Contents("C:\dados\clientes.csv"), [Delimiter=";", Encoding=65001]),
Promovido = Table.PromoteHeaders(Fonte),
Tipos = Table.TransformColumnTypes(Promovido, {
{"Cliente", type text},
{"Faturamento", type number},
{"DataCadastro", type date}
})
in
Tipos
Repare que cada coluna recebe seu tipo num par entre chaves. Tipo errado e erro de carga costumam andar de mãos dadas, e resolver isso de forma consistente é parte do que fazemos num projeto de Power BI de ponta a ponta.
O Editor Avançado mostra o script completo
Até aqui falamos de código, e é hora de dizer onde ele mora. No Power Query, o Editor Avançado mostra o script M completo da consulta selecionada. Para abrir, vá em Página Inicial e clique em Editor Avançado. A tela que abre exibe todo o let ... in da consulta, com todas as etapas de uma vez.
Esse é o melhor lugar para aprender. O fluxo que recomendo para quem está começando é este:
- Faça a transformação pelo menu, clicando normalmente.
- Abra o Editor Avançado e leia a linha que foi gerada.
- Compare o nome da função com o que aconteceu na tela.
- Feche, faça outra transformação e repita.
Em poucos dias você vai reconhecer os padrões. Vai perceber que remover linhas em branco vira Table.SelectRows, que filtrar vira uma condição dentro do SelectRows, que renomear vira Table.RenameColumns. A interface é o seu professor de M, e o Editor Avançado é o caderno onde a aula fica registrada.
Uma dica prática: nem toda transformação está no menu. Quando você precisa de algo que os botões não oferecem, é no Editor Avançado que você digita a função na mão. É assim que se vai além do básico, e é por isso que dominar a leitura do M vale tanto.
Nomes com espaço usam a sintaxe #"..."
Você vai notar que muitas etapas geradas pela interface aparecem entre #" e ", por exemplo #"Linhas Filtradas". Isso acontece porque o nome tem espaço. No M, um nome de variável comum não pode ter espaço nem acento. Quando o nome precisa deles, o M usa a sintaxe de identificador entre aspas, que começa com #" e termina com ".
let
Fonte = Csv.Document(File.Contents("C:\dados\vendas.csv"), [Delimiter=";"]),
#"Cabecalho Promovido" = Table.PromoteHeaders(Fonte),
#"Linhas Filtradas" = Table.SelectRows(#"Cabecalho Promovido", each [Regiao] = "Sul")
in
#"Linhas Filtradas"
Repare que a etapa seguinte se refere à anterior repetindo a sintaxe completa: #"Cabecalho Promovido". Por isso etapas com nome longo deixam o código mais verboso. Muitos consultores renomeiam as etapas para nomes curtos e sem espaço, justamente para o código ficar mais limpo e fácil de referenciar. É uma questão de estilo, mas ajuda quando a consulta cresce.
Um exemplo que junta tudo
Para fechar o raciocínio, veja uma consulta pequena que usa cada conceito que vimos: a estrutura let ... in, etapas como variáveis, tipos explícitos e uma coluna calculada escrita na mão.
let
Fonte = Csv.Document(File.Contents("C:\dados\pedidos.csv"), [Delimiter=";", Encoding=65001]),
Cabecalho = Table.PromoteHeaders(Fonte),
Tipos = Table.TransformColumnTypes(Cabecalho, {
{"Pedido", type text},
{"Quantidade", Int64.Type},
{"PrecoUnitario", type number}
}),
ComTotal = Table.AddColumn(Tipos, "Total", each [Quantidade] * [PrecoUnitario], type number),
SemZerados = Table.SelectRows(ComTotal, each [Total] > 0)
in
SemZerados
Leia de novo, de cima para baixo. Fonte abre o arquivo, Cabecalho promove o título, Tipos fixa os tipos, ComTotal cria uma coluna nova multiplicando duas outras, e SemZerados filtra o que sobrou. O in SemZerados entrega o resultado. Nenhuma linha é mágica: cada uma é uma variável que usa a anterior. Quando você lê M assim, a tela deixa de assustar. Se o seu trabalho envolve montar essa camada de forma robusta para produção, isso é parte central de um projeto de engenharia de dados bem feito.
Perguntas frequentes
Preciso saber programar para aprender a linguagem M? Não. A maioria das transformações você continua fazendo pela interface, com cliques. O que muda é que, ao aprender a ler o M que a interface gera, você ganha a capacidade de ajustar, corrigir e criar transformações que o menu não oferece pronto. É um degrau de leitura antes de ser um degrau de escrita.
Qual a diferença entre a linguagem M e o DAX? São linguagens diferentes com propósitos diferentes. O M vive no Power Query e serve para trazer e transformar os dados antes de carregar no modelo. O DAX vive dentro do modelo e serve para criar medidas e cálculos sobre os dados já carregados. Uma prepara os dados, a outra calcula em cima deles. Se quiser entender o lado do cálculo, veja o material sobre boas práticas de modelagem e DAX no Power Bi.
Por que meu código dá erro dizendo que o nome não foi reconhecido?
Quase sempre é sensibilidade a maiúsculas e minúsculas. O M diferencia caixa, então Table.SelectRows funciona e table.selectrows não. Confira letra por letra o nome da função e o nome das etapas que você referenciou. O autocompletar do Editor Avançado ajuda a acertar a grafia.
Posso apagar a etapa Changed Type que o Power Query cria sozinho?
Pode, mas com cuidado. Essa etapa de tipo automático nem sempre acerta, principalmente com data e número que dependem de localidade. Muitos preferem apagá-la e definir os tipos de forma explícita mais adiante, com Table.TransformColumnTypes, quando os nomes de coluna já estão estáveis. O importante é que os tipos estejam definidos em algum ponto antes da carga.
Para que servem aqueles nomes entre #"aspas" no código?
São nomes de etapa que contêm espaço ou acento. O M exige a sintaxe #"..." para esses casos, porque um identificador comum não aceita espaço. Se quiser um código mais limpo, renomeie as etapas para nomes curtos e sem espaço, e a sintaxe com aspas some.
Onde eu vejo o código M completo de uma consulta?
No Editor Avançado. Ele fica na aba Página Inicial do Power Query e mostra o script inteiro, com o let ... in e todas as etapas de uma vez. É o melhor lugar para estudar, comparando o código gerado com a transformação que você fez pela interface.
Power Query começar na linguagem M é ler antes de escrever
O caminho para dominar o M não passa por decorar funções. Passa por abrir o Editor Avançado depois de cada clique, ler a linha que apareceu e entender que aquilo é só uma variável apoiada na anterior, dentro de um let ... in. Faça isso por alguns dias e o código deixa de assustar. A partir daí você vai ajustar consultas com segurança, entender os erros e escrever transformações que o menu não entrega.
Se a sua equipe quer estruturar a camada de dados do Power BI com solidez, ou precisa de apoio para acelerar essa curva de aprendizado, fale com a gente. A Fynx ajuda times a transformar consultas frágeis em pipelines confiáveis.
Quer aplicar isso na sua empresa?
A Fynx implementa BI, Power BI e Power Platform de ponta a ponta. Conte seu cenário e devolvemos um diagnóstico direto ao ponto.
Falar com um especialista