fx

Power Query (M)

Code Library UDF M

Biblioteca de 21 UDFs de Power Query M com código completo: validação de CPF e CNPJ (inclusive alfanumérico), formatação de texto, máscara de telefone, documento e e-mail, sufixo ordinal, feriados do Brasil, EUA e França, e datas.

21 funções

Guia de uso

1. Instalar uma função

  1. No Power Query, Nova Fonte › Consulta Nula.
  2. Abra o Editor Avançado, apague tudo e cole o Código completo da função.
  3. Renomeie a consulta com o nome da função (ex.: fnValidaCPF).
  4. Use numa coluna: Adicionar Coluna › Coluna Personalizada com fnValidaCPF([CPF]), ou Invocar Função Personalizada.

Funções com Dependências precisam das consultas listadas no mesmo arquivo (ex.: fnHolidaysInPeriodPT chama fnFeriados).

2. Padrão de documentação

Toda função termina em Value.ReplaceType, que grava a documentação no tipo da função. Ela aparece quando você seleciona a consulta da função no Power Query.

CampoOnde apareceStatus
Documentation.NameTopo da caixa de invocação da funçãoDocumentado pela Microsoft
Documentation.LongDescriptionInformações da funçãoDocumentado pela Microsoft
Documentation.ExamplesInformações da função (lista de registros Description, Code, Result)Documentado pela Microsoft
Documentation.Description, .Category, .Author, .Version, .SourceFicam nos metadados, legíveis com Value.Metadata(Value.Type(fn))Convenção deste Code Library, não documentada para funções personalizadas

⚠️ Dentro de Documentation.Examples, Code e Result são texto M: aspas duplas se escrevem dobradas ("fnValidaCPF(""123.456.789-09"")"). Aspas simples não delimitam texto em M.

3. Nomes de função

  • Convenção: fn + PascalCase, sem acento (fnClassificacaoIMC, fnTelefoneAnonimo).
  • Acento no nome funciona sem #"...": a especificação do M aceita letras Unicode em identificadores. O motivo para evitar é outro: digitar, buscar e automatizar (scripts, XMLA, CI) fica mais sujeito a erro de codificação.
  • #"..." só é obrigatório com espaço, símbolo, nome que começa com número ou palavra-chave.

Fontes

Feriados e calendário

1. Dia da semana: a numeração

fnNthWeekday, fnLastWeekday e o calendário usam 0 (segunda) a 6 (domingo) — a numeração de Date.DayOfWeek(data, Day.Monday).

OndeSegunda vale
Date.DayOfWeek(data, Day.Monday)0
Constante Day.Monday1 (Day.Sunday = 0)
DAX WEEKDAY(data, 2)1

⚠️ Com essa numeração, fim de semana é >= 5 (sábado = 5, domingo = 6).

2. Tabela de feriados no modelo

As funções fnHolidaysInPeriod* já devolvem tabela tipada e ordenada; a consulta que as usa fica com um passo só:

// TabIntHolidayPT
let
    Fonte = fnHolidaysInPeriodPT(Date.From(DataInicioProjeto), Date.From(DataFimProjeto))
in
    Fonte

Date.From protege contra parâmetro do tipo Data/Hora: passar um datetime para um parâmetro as date dá erro de conversão.

3. Duas festas na mesma data

A Páscoa cai em 21/04 (Tiradentes) em 2030; a Ascension caiu em 01/05 em 2008. Mesclar a tabela de feriados direto no calendário duplica o dia e quebra o relacionamento 1:N com as fatos. Agrupe por data antes:

let
    FeriadosPT = Table.Group(TabIntHolidayPT, {"DateReference"}, {
        {"HolidayPT", each Text.Combine(List.Distinct([HolidayPT]), " / "), type text},
        {"IsNationalHolidayPT", each List.Contains([HolidayType], "Feriado nacional"), type logical}
    })
in
    FeriadosPT

4. Nomes reservados: RangeStart e RangeEnd

Não chame de RangeStart/RangeEnd as consultas que calculam o início e o fim do projeto. Esses nomes são dos parâmetros do Incremental Refresh, que precisam ser Parâmetros de Consulta do tipo Data/Hora. Se o modelo ganhar Incremental Refresh, os nomes colidem — e uma tabela de feriados filtrada pelos parâmetros do IR traria só os feriados de cada partição. Use nomes próprios, como DataInicioProjeto e DataFimProjeto.

Fontes