Linguagem

M

Itens reutilizáveis de M organizados por tipo de objeto e categoria/biblioteca. Extensão canônica .pq.

Itens
18
Categorias
9
Exibindo
18

Formatação

1

fnFormatWithLeadingZeros

Formata um número com zeros à esquerda.

BásicoUDFv1.0.0
let
  Source = (pNumero as nullable any, pNumeroDeCaracteres as nullable number) as nullable text =>
    let
      vNumero = Number.Abs(Number.From(pNumero)),
      vDigitos = Number.Abs(Number.From(pNumeroDeCaracteres)),
      Resultado = Text.PadStart(Text.From(vNumero), vDigitos, "0")
    in
      Resultado,
  documentation = [
    Documentation.Name = "fnFormatWithLeadingZeros",
    Documentation.Description = "Formata um número com zeros à esquerda.",
    Documentation.Category = "Formatação",
    Documentation.Author = "Paulo André Jesus",
    Documentation.Examples = {[Description = "Formata 7 com 3 dígitos", Code = "fnFormatWithLeadingZeros(7, 3)", Result = "007"]}
  ]
in
  Value.ReplaceType(Source, Value.ReplaceMetadata(Value.Type(Source), documentation))
  • m
  • udf
  • formatacao
  • texto

Formatação de Texto

1

fnFormataNome

Formata nomes completos com tratamento especial para partículas (de, van, von...), apóstrofos, hífens, prefixos Mc/Mac e partículas compostas.

AvançadoUDFv2.4.0
let
    fnFormataNome = (NomeCompleto as text) as text =>
    let
        ParticulasSimples = {
            "da", "das", "de", "do", "dos", "d",
            "del", "dela", "y", "el",
            "di", "du",
            "e", "der",
            "von",
            "van",
            "bin", "bint", "ibn", "al",
            "ben", "bat",
            "ap",
            "of",
            "no",
            "l", "m"
        },
        ParticulasCompostas = {
            "de la", "de lo", "de los", "de las",
            "von und zu",
            "van der"
        },
        TrataMcMac = (palavra as text) as text =>
            if Text.StartsWith(palavra, "mac") and Text.Length(palavra) > 3 then
                "Mac" & Text.Upper(Text.Range(palavra, 3, 1)) & Text.Lower(Text.Range(palavra, 4))
            else if Text.StartsWith(palavra, "mc") and Text.Length(palavra) > 2 then
                "Mc" & Text.Upper(Text.Range(palavra, 2, 1)) & Text.Lower(Text.Range(palavra, 3))
            else
                palavra,
        TextoInicial = List.Accumulate(
            ParticulasCompostas,
            Text.Lower(Text.Trim(NomeCompleto)),
            (acc, part) => Text.Replace(acc, part, "@@" & Text.Replace(part, " ", "") & "@@")
        ),
        Palavras = Text.Split(TextoInicial, " "),
        TrataApostrofo = (palavra as text) as text =>
            let
                tipoApostrofo =
                    if Text.Contains(palavra, "’") then "’"
                    else if Text.Contains(palavra, "'") then "'"
                    else null,
                partes =
                    if tipoApostrofo <> null then Text.Split(palavra, tipoApostrofo) else {palavra},
                resultado =
                    if List.Count(partes) = 2 and List.Contains(ParticulasSimples, Text.Lower(partes{0})) then
                        Text.Upper(Text.Start(partes{0}, 1)) & tipoApostrofo &
                        Text.Upper(Text.Start(partes{1}, 1)) &
                        Text.Lower(Text.End(partes{1}, Text.Length(partes{1}) - 1))
                    else if List.Count(partes) = 2 then
                        Text.Upper(Text.Start(partes{0}, 1)) & tipoApostrofo &
                        Text.Upper(Text.Start(partes{1}, 1)) &
                        Text.Lower(Text.End(partes{1}, Text.Length(partes{1}) - 1))
                    else
                        palavra
            in
                resultado,
        TrataHifen = (palavra as text) as text =>
            Text.Combine(
                List.Transform(
                    Text.Split(palavra, "-"),
                    each
                        let
                            base = Text.Lower(_),
                            tratado =
                                if List.AnyTrue({Text.Contains(_, "'"), Text.Contains(_, "’")}) then TrataApostrofo(_)
                                else if List.Contains(ParticulasSimples, base) then Text.Lower(base)
                                else if Text.StartsWith(base, "mc") or Text.StartsWith(base, "mac") then TrataMcMac(base)
                                else Text.Upper(Text.Start(base,1)) & Text.Lower(Text.End(base, Text.Length(base) - 1))
                        in
                            tratado
                ),
                "-"
            ),
        NomeFormatado = List.Transform(
            Palavras,
            each
                if Text.StartsWith(_, "@@") and Text.EndsWith(_, "@@") then _
                else TrataHifen(Text.Lower(_))
        ),
        ResultadoParcial = Text.Combine(NomeFormatado, " "),
        ResultadoFinal = List.Accumulate(
            ParticulasCompostas,
            ResultadoParcial,
            (acc, part) =>
                let
                    palavras = Text.Split(part, " "),
                    ultima = palavras{List.Count(palavras) - 1},
                    capitalizado = Text.Upper(Text.Start(ultima, 1)) & Text.Lower(Text.End(ultima, Text.Length(ultima) - 1)),
                    recomposicao = Text.Combine(List.FirstN(palavras, List.Count(palavras) - 1) & {capitalizado}, " "),
                    placeholder = "@@" & Text.Replace(part, " ", "") & "@@"
                in
                    Text.Replace(acc, placeholder, recomposicao)
        )
    in
        ResultadoFinal,
    documentation = [
        Documentation.Name = "fnFormataNome",
        Documentation.Description = "Formata nomes completos com tratamento especial para partículas, apóstrofos, hífens, Mc/Mac e compostos.",
        Documentation.LongDescription = "Aplica capitalização correta em nomes próprios, mantendo minúsculas as partículas (como 'de', 'van'), capitalizando corretamente sobrenomes com prefixo ('McGregor', 'MacDonald'), hífens e nomes com apóstrofos ('D'Almeida', 'O’Connor'), além de preservar a forma original do apóstrofo (reto ou tipográfico).",
        Documentation.Category = "Formatação de Texto",
        Documentation.Author = "Paulo André",
        Documentation.Version = "2.4",
        Documentation.Examples = {
            [Description = "Formata corretamente sobrenomes com Mc", Code = "fnFormataNome(""LIAM MCGREGOR"")", Result = "Liam McGregor"],
            [Description = "Formata sobrenome com partícula", Code = "fnFormataNome(""CLAIRE DEL MONTE"")", Result = "Claire del Monte"]
        }
    ]
in
    Value.ReplaceType(fnFormataNome, Value.ReplaceMetadata(Value.Type(fnFormataNome), documentation))
  • m
  • udf
  • texto
  • formatacao
  • nomes

Funções de Data e Hora

1

fnHorasEntreDatas

Retorna uma lista de horas completas (datetime) entre duas datas/horários — útil para gerar séries temporais horárias.

IntermediárioUDFv1.1.0
let
  Source = (Start as datetime, End as datetime) as list =>
    let
      Horas = List.Transform(
        {0 .. Number.RoundDown(Duration.TotalHours(End - Start))},
        each Start + #duration(0, _, 0, 0)
      )
    in
      Horas,
  documentation = [
    Documentation.Name = "fnHorasEntreDatas",
    Documentation.Description = "Retorna uma lista de horas (datetime) entre as datas e horários especificados.",
    Documentation.LongDescription = "Gera uma lista contendo todas as horas completas entre duas datas/horários fornecidos. Útil para criar séries temporais baseadas em intervalos de hora.",
    Documentation.Category = "Funções de Data e Hora",
    Documentation.Author = "Paulo André Jesus",
    Documentation.Version = "1.1",
    Documentation.Examples = {
      [Description = "Gerar lista de horas entre 1h e 4h29 de um dia.", Code = "fnHorasEntreDatas(#datetime(2018, 7, 8, 1, 0, 0), #datetime(2018, 7, 8, 4, 29, 0))", Result = "{#datetime(2018,7,8,1,0,0), ..., #datetime(2018,7,8,4,0,0)}"]
    }
  ]
in
  Value.ReplaceType(Source, Value.ReplaceMetadata(Value.Type(Source), documentation))
  • m
  • udf
  • data-hora
  • series-temporais

Funções de Datas

5

fnFeriados

Retorna uma tabela com os feriados fixos e móveis do Brasil para o ano fornecido. Feriados móveis calculados a partir do Domingo de Páscoa (algoritmo gregoriano).

IntermediárioUDFv1.0.0
let
  Source = (y as number) as table =>
    let
      a = Number.Mod(y, 19),
      b = Number.RoundDown(y / 100),
      c = Number.Mod(y, 100),
      d = Number.RoundDown(b / 4),
      e = Number.Mod(b, 4),
      f = Number.RoundDown((b + 8) / 25),
      g = Number.RoundDown((b - f + 1) / 3),
      h = Number.Mod((19 * a + b - d - g + 15), 30),
      i = Number.RoundDown(c / 4),
      k = Number.Mod(c, 4),
      l = Number.Mod((32 + 2 * e + 2 * i - h - k), 7),
      m = Number.RoundDown((a + 11 * h + 22 * l) / 451),
      n = Number.RoundDown((h + l - 7 * m + 114) / 31),
      o = Number.Mod((h + l - 7 * m + 114), 31),
      pascoa = #date(y, n, o + 1),
      FeriadosFixos = {
        [Data = #date(y, 01, 01), Feriado = "Confraternização Universal"],
        [Data = #date(y, 04, 21), Feriado = "Dia de Tiradentes"],
        [Data = #date(y, 05, 01), Feriado = "Dia do Trabalho"],
        [Data = #date(y, 09, 07), Feriado = "Dia da Independência do Brasil"],
        [Data = #date(y, 10, 12), Feriado = "Dia de Nossa Senhora Aparecida"],
        [Data = #date(y, 11, 02), Feriado = "Dia de Finados"],
        [Data = #date(y, 11, 15), Feriado = "Proclamação da República do Brasil"],
        [Data = #date(y, 12, 25), Feriado = "Natal"]
      },
      FeriadosMoveis = {
        [Data = Date.AddDays(pascoa, -47), Feriado = "Carnaval"],
        [Data = Date.AddDays(pascoa, -2), Feriado = "Sexta-feira da Paixão"],
        [Data = pascoa, Feriado = "Domingo de Páscoa"],
        [Data = Date.AddDays(pascoa, 60), Feriado = "Corpus Christi"]
      },
      Resultado = Table.FromRecords(FeriadosFixos & FeriadosMoveis)
    in
      Resultado,
  documentation = [
    Documentation.Name = "fnFeriados",
    Documentation.Description = "Retorna uma tabela com os feriados fixos e móveis do ano fornecido.",
    Documentation.LongDescription = "Calcula e retorna uma tabela contendo os feriados fixos e móveis para um ano especificado. Os feriados móveis são calculados com base na data do Domingo de Páscoa, obtida usando o algoritmo gregoriano.",
    Documentation.Category = "Funções de Datas",
    Documentation.Source = "https://en.wikipedia.org/wiki/Date_of_Easter",
    Documentation.Author = "Laennder Alves, adaptado por Paulo André Jesus",
    Documentation.Examples = {
      [Description = "Obter feriados do ano de 2025.", Code = "fnFeriados(2025)", Result = "Tabela com feriados de 2025, incluindo fixos e móveis."]
    }
  ]
in
  Value.ReplaceType(Source, Value.ReplaceMetadata(Value.Type(Source), documentation))
  • m
  • udf
  • feriados
  • brasil
  • calendario

fnHolidaysInPeriodEN

Retorna os feriados federais dos EUA (fixos e móveis) dentro de um período de datas — cobre múltiplos anos numa chamada.

AvançadoUDFv1.0.0
let
    fnHolidaysInPeriodEN = (DataInicial as date, DataFinal as date) as table =>
        let
            startYear = Date.Year(DataInicial),
            endYear = Date.Year(DataFinal),
            yearsList = {startYear..endYear},
            HolidaysByYear = List.Combine(
                List.Transform(
                    yearsList,
                    (y) =>
                        let
                            FixedHolidays = {
                                [DateReference = #date(y, 1, 1), HolidayEN = "New Year's Day"],
                                [DateReference = #date(y, 6, 19), HolidayEN = "Juneteenth National Independence Day"],
                                [DateReference = #date(y, 7, 4), HolidayEN = "Independence Day"],
                                [DateReference = #date(y, 11, 11), HolidayEN = "Veterans Day"],
                                [DateReference = #date(y, 12, 25), HolidayEN = "Christmas Day"]
                            },
                            MovableHolidays = {
                                [DateReference = fnNthWeekday(y, 1, 0, 3), HolidayEN = "Martin Luther King Jr. Day"],
                                [DateReference = fnNthWeekday(y, 2, 0, 3), HolidayEN = "Presidents' Day"],
                                [DateReference = fnLastWeekday(y, 5, 0), HolidayEN = "Memorial Day"],
                                [DateReference = fnNthWeekday(y, 9, 0, 1), HolidayEN = "Labor Day"],
                                [DateReference = fnNthWeekday(y, 10, 0, 2), HolidayEN = "Columbus Day"],
                                [DateReference = fnNthWeekday(y, 11, 3, 4), HolidayEN = "Thanksgiving Day"]
                            }
                        in
                            FixedHolidays & MovableHolidays
                )
            ),
            HolidaysFiltered = List.Select(HolidaysByYear, each [DateReference] >= DataInicial and [DateReference] <= DataFinal),
            HolidaysSorted = List.Sort(HolidaysFiltered, (a, b) => if a[DateReference] < b[DateReference] then -1 else if a[DateReference] > b[DateReference] then 1 else 0),
            HolidaysTable = Table.FromRecords(HolidaysSorted)
        in
            HolidaysTable
in
    fnHolidaysInPeriodEN
  • m
  • udf
  • feriados
  • eua
  • calendario

fnHolidaysInPeriodPT

Retorna os feriados nacionais do Brasil (fixos e móveis) dentro de um período de datas — variante multi-ano de fnFeriados.

AvançadoUDFv1.0.0
let
    fnHolidaysInPeriodPT = (StartDate as date, EndDate as date) as table =>
    let
        Years = List.Distinct({Date.Year(StartDate) .. Date.Year(EndDate)}),
        fnHolidaysByYear = (year as number) as table =>
        let
            a = Number.Mod(year, 19),
            b = Number.IntegerDivide(year, 100),
            c = Number.Mod(year, 100),
            d = Number.IntegerDivide(b, 4),
            e = Number.Mod(b, 4),
            f = Number.IntegerDivide(b + 8, 25),
            g = Number.IntegerDivide(b - f + 1, 3),
            h = Number.Mod((19 * a + b - d - g + 15), 30),
            i = Number.IntegerDivide(c, 4),
            k = Number.Mod(c, 4),
            l = Number.Mod((32 + 2 * e + 2 * i - h - k), 7),
            m = Number.IntegerDivide(a + 11 * h + 22 * l, 451),
            n = Number.IntegerDivide(h + l - 7 * m + 114, 31),
            o = Number.Mod(h + l - 7 * m + 114, 31),
            Easter = #date(year, n, o + 1),
            FixedHolidays = {
                [DateReference = #date(year, 01, 01), HolidayPT = "Confraternização Universal"],
                [DateReference = #date(year, 04, 21), HolidayPT = "Dia de Tiradentes"],
                [DateReference = #date(year, 05, 01), HolidayPT = "Dia do Trabalho"],
                [DateReference = #date(year, 09, 07), HolidayPT = "Dia da Independência do Brasil"],
                [DateReference = #date(year, 10, 12), HolidayPT = "Dia de Nossa Senhora Aparecida"],
                [DateReference = #date(year, 11, 02), HolidayPT = "Dia de Finados"],
                [DateReference = #date(year, 11, 15), HolidayPT = "Proclamação da República do Brasil"],
                [DateReference = #date(year, 12, 25), HolidayPT = "Natal"]
            },
            MovableHolidays = {
                [DateReference = Date.AddDays(Easter, -47), HolidayPT = "Carnaval"],
                [DateReference = Date.AddDays(Easter, -2), HolidayPT = "Sexta-feira da Paixão"],
                [DateReference = Easter, HolidayPT = "Domingo de Páscoa"],
                [DateReference = Date.AddDays(Easter, 60), HolidayPT = "Corpus Christi"]
            },
            Result = Table.FromRecords(FixedHolidays & MovableHolidays)
        in
            Result,
        AllHolidays = Table.Combine(List.Transform(Years, each fnHolidaysByYear(_))),
        FilteredHolidays = Table.SelectRows(AllHolidays, each [DateReference] >= StartDate and [DateReference] <= EndDate)
    in
        FilteredHolidays,
    documentation = [
        Documentation.Name = "fnHolidaysInPeriodPT",
        Documentation.Description = "Retorna uma tabela com os feriados fixos e móveis no Brasil dentro de um período específico.",
        Documentation.LongDescription = "Calcula e retorna os feriados fixos e móveis brasileiros para todos os anos dentro do intervalo de datas fornecido. Feriados móveis baseados na Páscoa, calculada via algoritmo de Gauss.",
        Documentation.Category = "Funções de Datas",
        Documentation.Source = "https://en.wikipedia.org/wiki/Date_of_Easter",
        Documentation.Author = "Adaptado por Paulo André Jesus",
        Documentation.Examples = {
            [Description = "Obter feriados entre 01/01/2023 e 31/12/2025.", Code = "fnHolidaysInPeriodPT(#date(2023, 1, 1), #date(2025, 12, 31))", Result = "Tabela com feriados entre 2023 e 2025."]
        }
    ]
in
    Value.ReplaceType(fnHolidaysInPeriodPT, Value.ReplaceMetadata(Value.Type(fnHolidaysInPeriodPT), documentation))
  • m
  • udf
  • feriados
  • brasil
  • calendario

fnLastWeekday

Calcula a última ocorrência de um dia da semana em um mês/ano — usada internamente por fnHolidaysInPeriodEN (ex.: Memorial Day nos EUA).

IntermediárioUDFv1.0.0
let
    fnLastWeekday = (Ano as number, Mes as number, DiaDaSemana as number) as nullable date =>
    let
        UltimoDia = Date.EndOfMonth(#date(Ano, Mes, 1)),
        UltimoDiaSemana = Date.DayOfWeek(UltimoDia, Day.Monday),
        Offset = if UltimoDiaSemana >= DiaDaSemana
                 then UltimoDiaSemana - DiaDaSemana
                 else 7 - (DiaDaSemana - UltimoDiaSemana),
        UltimaData = Date.AddDays(UltimoDia, -Offset)
    in
        UltimaData,
    Documentation = [
        Documentation.Name = "fnLastWeekday",
        Documentation.Description = "Calcula a última ocorrência de um dia da semana em um determinado mês e ano.",
        Documentation.LongDescription = "Recebe ano, mês e dia da semana, retorna a data da última ocorrência desse dia da semana no mês. Contagem: 0=segunda ... 6=domingo (padrão Day.Monday).",
        Documentation.Category = "Funções de Datas",
        Documentation.Author = "Paulo André Jesus",
        Documentation.Version = "1.0",
        Documentation.Examples = {
            [Description = "Última sexta-feira de março de 2025.", Code = "fnLastWeekday(2025, 3, 4)", Result = "#date(2025, 3, 28)"]
        }
    ]
in
    Value.ReplaceType(fnLastWeekday, Value.ReplaceMetadata(Value.Type(fnLastWeekday), Documentation))
  • m
  • udf
  • data
  • calendario
  • utilitario

fnNthWeekday

Calcula a N-ésima ocorrência de um dia da semana em um mês/ano — usada internamente por fnHolidaysInPeriodEN (ex.: Thanksgiving nos EUA).

IntermediárioUDFv1.0.0
let
    fnNthWeekday = (Ano as number, Mes as number, DiaDaSemana as number, N as number) as nullable date =>
    let
        PrimeiroDia = #date(Ano, Mes, 1),
        PrimeiroDiaSemana = Date.DayOfWeek(PrimeiroDia, Day.Monday),
        Offset = if PrimeiroDiaSemana <= DiaDaSemana
                 then DiaDaSemana - PrimeiroDiaSemana
                 else 7 - (PrimeiroDiaSemana - DiaDaSemana),
        EnesimoDia = Date.AddDays(PrimeiroDia, Offset + 7 * (N - 1))
    in
        EnesimoDia,
    Documentation = [
        Documentation.Name = "fnNthWeekday",
        Documentation.Description = "Calcula a enésima ocorrência de um dia da semana em um determinado mês e ano.",
        Documentation.LongDescription = "Recebe ano, mês, dia da semana e um número 'N', retorna a data da enésima ocorrência desse dia da semana no mês. Contagem: 0=segunda ... 6=domingo (padrão Day.Monday).",
        Documentation.Category = "Funções de Datas",
        Documentation.Author = "Paulo André Jesus",
        Documentation.Version = "1.0",
        Documentation.Examples = {
            [Description = "Terceira segunda-feira de janeiro de 2025.", Code = "fnNthWeekday(2025, 1, 0, 3)", Result = "#date(2025, 1, 20)"]
        }
    ]
in
    Value.ReplaceType(fnNthWeekday, Value.ReplaceMetadata(Value.Type(fnNthWeekday), Documentation))
  • m
  • udf
  • data
  • calendario
  • utilitario

Funções de Saúde

1

fnClassificacaoIMC

Classifica o IMC (Índice de Massa Corporal) com base nos intervalos da OMS, retornando código de classificação e prioridade de risco.

BásicoUDFv1.0.0
let
  Source = (ClassificarIMC as nullable number) as nullable text =>
    let
      Resultado =
        if ClassificarIMC = null then
            null
        else if ClassificarIMC < 17 then
            "01-7"
        else if ClassificarIMC >= 17 and ClassificarIMC < 18.5 then
            "02-6"
        else if ClassificarIMC >= 18.5 and ClassificarIMC < 25 then
            "03-5"
        else if ClassificarIMC >= 25 and ClassificarIMC < 30 then
            "04-4"
        else if ClassificarIMC >= 30 and ClassificarIMC < 35 then
            "05-3"
        else if ClassificarIMC >= 35 and ClassificarIMC < 40 then
            "06-2"
        else if ClassificarIMC >= 40 then
            "07-1"
        else
            null
    in
      Resultado,
  documentation = [
    Documentation.Name = "fnClassificacaoIMC",
    Documentation.Description = "Classifica o IMC (Índice de Massa Corporal) com base em intervalos predefinidos e retorna uma string de classificação.",
    Documentation.LongDescription = "Recebe um valor numérico representando o IMC e retorna uma string de classificação de acordo com os intervalos da OMS. A classificação segue o padrão 'XX-Y', onde 'XX' é o código da categoria e 'Y' a prioridade de risco (quanto menor o número, maior o risco).",
    Documentation.Category = "Funções de Saúde",
    Documentation.Author = "Paulo André Jesus",
    Documentation.Examples = {
      [Description = "Classificar IMC igual a 22.", Code = "fnClassificacaoIMC(22)", Result = "03-5"],
      [Description = "Classificar IMC nulo.", Code = "fnClassificacaoIMC(null)", Result = "null"]
    }
  ]
in
  Value.ReplaceType(Source, Value.ReplaceMetadata(Value.Type(Source), documentation))
  • m
  • udf
  • saude
  • imc

Funções de Texto

5

fnAddOrdinalSuffixEN

Adiciona o sufixo ordinal correto a um número em inglês (1st, 2nd, 3rd, 4th...).

BásicoUDFv1.0.0
let
  fnAddOrdinalSuffix = (SingleNumber as number) as text =>
    let
      LastTwoDigits = Number.Mod(SingleNumber, 100),
      LastDigit = Number.Mod(SingleNumber, 10),
      Suffix =
        if List.Contains({11, 12, 13}, LastTwoDigits) then "th"
        else if LastDigit = 1 then "st"
        else if LastDigit = 2 then "nd"
        else if LastDigit = 3 then "rd"
        else "th",
      Result = Text.From(SingleNumber) & Suffix
    in
      Result,
  documentation = [
    Documentation.Name = "fnAddOrdinalSuffixEN",
    Documentation.Description = "Adiciona o sufixo ordinal correto a um número em inglês (1st, 2nd, 3rd, 4th, etc.).",
    Documentation.LongDescription = "Recebe um número inteiro e adiciona o sufixo ordinal apropriado conforme as regras do inglês. Números terminando em 11, 12 e 13 são exceções e sempre recebem 'th'.",
    Documentation.Category = "Funções de Texto",
    Documentation.Author = "Paulo André Jesus",
    Documentation.Examples = {
      [Description = "Adicionar sufixo ao número 22.", Code = "fnAddOrdinalSuffixEN(22)", Result = "22nd"],
      [Description = "Exceção: número 11.", Code = "fnAddOrdinalSuffixEN(11)", Result = "11th"]
    }
  ]
in
  Value.ReplaceType(fnAddOrdinalSuffix, Value.ReplaceMetadata(Value.Type(fnAddOrdinalSuffix), documentation))
  • m
  • udf
  • texto
  • ordinal
  • ingles

fnAddOrdinalSuffixPT

Adiciona o sufixo ordinal correto a um número em português, com suporte a gênero (1º/1ª).

BásicoUDFv1.0.0
let
  fnAddOrdinalSuffixPT = (Numero as number, optional Genero as nullable text) as text =>
    let
      GeneroDefinido = if Genero = null then "M" else Text.Upper(Genero),
      Sufixo = if GeneroDefinido = "F" then "ª" else "º",
      Resultado = Text.From(Numero) & Sufixo
    in
      Resultado,
  documentacao = [
    Documentation.Name = "fnAddOrdinalSuffixPT",
    Documentation.Description = "Adiciona o sufixo ordinal correto a um número em português (1º, 2º, 3º para masculino e 1ª, 2ª, 3ª para feminino).",
    Documentation.LongDescription = "Recebe um número inteiro e adiciona o sufixo ordinal apropriado conforme o português do Brasil. Se o gênero for 'F', recebe sufixo 'ª'; caso contrário, 'º' (padrão masculino).",
    Documentation.Category = "Funções de Texto",
    Documentation.Author = "Paulo André Jesus",
    Documentation.Examples = {
      [Description = "Número 1, feminino.", Code = "fnAddOrdinalSuffixPT(1, "F")", Result = "1ª"],
      [Description = "Número 2, padrão masculino.", Code = "fnAddOrdinalSuffixPT(2)", Result = "2º"]
    }
  ]
in
  Value.ReplaceType(fnAddOrdinalSuffixPT, Value.ReplaceMetadata(Value.Type(fnAddOrdinalSuffixPT), documentacao))
  • m
  • udf
  • texto
  • ordinal
  • portugues

fnDocumentoAnonimo

Anonimiza números de CPF e CNPJ, mantendo parte do prefixo e sufixo visíveis. Uso típico: LGPD, ambientes de demonstração.

IntermediárioUDFv1.0.0
let
  Source = (documento as text) as text =>
    let
      Tamanho = Text.Length(documento),
      Resultado =
        if Tamanho = 14 then
          let
            PrefixoInicial      = Text.Start(documento, 3),
            SufixoFinal         = Text.End(documento, 2),
            CPFAnonimizado = PrefixoInicial & ".***.***-" & SufixoFinal
          in
            CPFAnonimizado
        else if Tamanho = 18 then
          let
            PrefixoInicial      = Text.Start(documento, 2),
            SufixoFinal         = Text.End(documento, 2),
            CNPJAnonimizado = PrefixoInicial & ".***.***/****-" & SufixoFinal
          in
            CNPJAnonimizado
        else
          "Formato inválido"
    in
      Resultado,
  documentation = [
    Documentation.Name = "fnDocumentoAnonimo",
    Documentation.Description = "Anonimiza números de CPF e CNPJ, mantendo parte do prefixo e sufixo visíveis.",
    Documentation.LongDescription = "Recebe um CPF ou CNPJ em texto e retorna uma versão anonimizada, preservando parte dos dígitos do início e do final. Suporta CPF (14 caracteres) e CNPJ (18 caracteres).",
    Documentation.Category = "Funções de Texto",
    Documentation.Author = "Paulo André Jesus",
    Documentation.Examples = {
      [Description = "Anonimizar um CPF.", Code = "fnDocumentoAnonimo('123.456.789-00')", Result = "123.***.***-00"]
    }
  ]
in
  Value.ReplaceType(Source, Value.ReplaceMetadata(Value.Type(Source), documentation))
  • m
  • udf
  • texto
  • lgpd
  • anonimizacao
  • cpf
  • cnpj

fnNuvemDePalavras

Remove palavras irrelevantes (stopwords em português) de um texto, para uso em nuvens de palavras.

IntermediárioUDFv1.0.0
let
  Source = (texto as text) as text =>
    let
      StopWords = {
        "!", ".", ":", "'", ";", ",", "?", "@", "#", "$", "%", "^", "&", "*", "(", ")", "[", "]", "\\", "/", "-", "_", "+", "=", "<", ">", "|",
        "a", "as", "o", "os", "um", "uma", "uns", "umas",
        "de", "da", "das", "do", "dos", "em", "para", "com", "sem", "por", "sobre", "entre",
        "mas", "se", "não", "sim", "que", "é", "foi", "será", "são", "eram", "está", "estavam",
        "como", "também", "então", "porque", "porém",
        "seu", "sua", "seus", "suas", "meu", "minha", "meus", "minhas", "teu", "tua", "teus", "tuas",
        "esse", "essa", "esses", "essas", "aquele", "aquela", "aqueles", "aquelas", "isto", "isso", "aquilo"
      },
      TextoNormalizado = Text.Lower(texto),
      Palavras = Text.Split(TextoNormalizado, " "),
      PalavrasFiltradas = List.Select(Palavras, each not List.Contains(StopWords, _)),
      Resultado = Text.Combine(PalavrasFiltradas, " ")
    in
      Resultado,
  documentation = [
    Documentation.Name = "fnNuvemDePalavras",
    Documentation.Description = "Remove palavras irrelevantes (stopwords) de um texto para uso em nuvens de palavras.",
    Documentation.Category = "Funções de Texto",
    Documentation.Author = "Paulo André Jesus",
    Documentation.Examples = {
      [Description = "Processar um texto removendo palavras irrelevantes.", Code = "fnNuvemDePalavras('O gato preto e o cachorro estão na casa da vizinha.')", Result = "gato preto cachorro estão casa vizinha"]
    }
  ]
in
  Value.ReplaceType(Source, Value.ReplaceMetadata(Value.Type(Source), documentation))
  • m
  • udf
  • texto
  • stopwords
  • nlp

fnTelefoneAnonimo

Anonimiza números de telefone fixos e celulares, mantendo parte do DDD, prefixo e sufixo visíveis. Uso típico: LGPD, ambientes de demonstração.

IntermediárioUDFv1.0.0
let
  Source = (telefone as text) as text =>
    let
      Tamanho = Text.Length(telefone),
      Resultado =
        if Tamanho = 14 then
          let
            DDD                 = Text.Middle(telefone, 1, 2),
            PrefixoInicial      = Text.Middle(telefone, 5, 2),
            SufixoFinal         = Text.End(telefone, 2),
            TelefoneAnonimizado = "(" & DDD & ") " & PrefixoInicial & "**-**" & SufixoFinal
          in
            TelefoneAnonimizado
        else if Tamanho = 15 then
          let
            DDD                 = Text.Middle(telefone, 1, 2),
            PrefixoInicial      = Text.Middle(telefone, 5, 2),
            SufixoFinal         = Text.End(telefone, 2),
            TelefoneAnonimizado = "(" & DDD & ") " & PrefixoInicial & "***-**" & SufixoFinal
          in
            TelefoneAnonimizado
        else
          "Formato inválido"
    in
      Resultado,
  documentation = [
    Documentation.Name = "fnTelefoneAnonimo",
    Documentation.Description = "Anonimiza números de telefone fixos e celulares, mantendo parte do DDD, prefixo e sufixo visíveis.",
    Documentation.LongDescription = "Recebe um número de telefone em texto e retorna uma versão anonimizada, preservando os dois primeiros dígitos do prefixo e os dois últimos do sufixo. Suporta telefones fixos (14 caracteres) e celulares (15 caracteres).",
    Documentation.Category = "Funções de Texto",
    Documentation.Author = "Paulo André Jesus",
    Documentation.Examples = {
      [Description = "Anonimizar um telefone celular.", Code = "fnTelefoneAnonimo('(21) 98765-4321')", Result = "(21) 98***-**21"]
    }
  ]
in
  Value.ReplaceType(Source, Value.ReplaceMetadata(Value.Type(Source), documentation))
  • m
  • udf
  • texto
  • lgpd
  • anonimizacao

Funções de Validação

2

fnValidaCNPJ

Valida um CNPJ, verificando sua estrutura e calculando os dígitos verificadores. Aceita CNPJ formatado ou não, rejeita sequências repetitivas.

IntermediárioUDFv1.0.0
let
  Source = (CNPJ as text) as logical =>
    let
      CNPJ_Limpo = Text.Select(Text.Trim(CNPJ), {"0".."9"}),
      TamanhoValido = Text.Length(CNPJ_Limpo) = 14,
      SequenciaInvalida = List.Contains(
        {"00000000000000", "11111111111111", "22222222222222", "33333333333333",
         "44444444444444", "55555555555555", "66666666666666", "77777777777777",
         "88888888888888", "99999999999999"}, CNPJ_Limpo),
      Pesos1 = {5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2},
      Pesos2 = {6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2},
      CalculaDigito = (Base as list, Pesos as list) as number =>
        let
          Soma = List.Sum(List.Transform({0..List.Count(Base)-1}, each Base{_} * Pesos{_})),
          Resto = Number.Mod(Soma, 11),
          Digito = if Resto < 2 then 0 else 11 - Resto
        in
          Digito,
      NumerosBase = List.Transform(Text.ToList(Text.Start(CNPJ_Limpo, 12)), each Number.FromText(_)),
      Digito1Esperado = Number.FromText(Text.Middle(CNPJ_Limpo, 12, 1)),
      Digito2Esperado = Number.FromText(Text.Middle(CNPJ_Limpo, 13, 1)),
      Digito1Calculado = CalculaDigito(NumerosBase, Pesos1),
      Digito2Calculado = CalculaDigito(NumerosBase & {Digito1Calculado}, Pesos2),
      CNPJ_Valido = TamanhoValido and not SequenciaInvalida and Digito1Calculado = Digito1Esperado and Digito2Calculado = Digito2Esperado
    in
      CNPJ_Valido,
  documentation = [
    Documentation.Name = "fnValidaCNPJ",
    Documentation.Description = "Valida um CNPJ, verificando sua estrutura e calculando os dígitos verificadores.",
    Documentation.LongDescription = "Esta função recebe um CNPJ, podendo estar formatado ('12.345.678/0001-95') ou sem formatação ('12345678000195'), e verifica sua validade. Ela remove caracteres indesejados, impede o uso de CNPJs inválidos (como sequências repetitivas) e valida os dígitos verificadores com base no cálculo oficial da Receita Federal.",
    Documentation.Category = "Funções de Validação",
    Documentation.Author = "Paulo André Jesus",
    Documentation.Examples = {
      [Description = "Validar um CNPJ correto.", Code = "fnValidaCNPJ('12.345.678/0001-95')", Result = "true"],
      [Description = "Validar um CNPJ inválido com sequência repetitiva.", Code = "fnValidaCNPJ('11.111.111/1111-11')", Result = "false"]
    }
  ]
in
  Value.ReplaceType(Source, Value.ReplaceMetadata(Value.Type(Source), documentation))
  • m
  • udf
  • validacao
  • cnpj
  • brasil

fnValidaCPF

Valida um CPF, verificando sua estrutura e calculando os dígitos verificadores. Aceita CPF formatado ou não, rejeita sequências repetitivas.

IntermediárioUDFv1.0.0
let
  Source = (CPF as text) as logical =>
    let
      CPF_Limpo = Text.Select(Text.Trim(CPF), {"0".."9"}),
      TamanhoValido = Text.Length(CPF_Limpo) = 11,
      SequenciaInvalida = List.Contains(
        {"00000000000", "11111111111", "22222222222", "33333333333", "44444444444",
         "55555555555", "66666666666", "77777777777", "88888888888", "99999999999"}, CPF_Limpo),
      CalculaDigito = (Base as list) as number =>
        let
          Soma = List.Sum(List.Transform({0..List.Count(Base)-1}, each Base{_} * (List.Count(Base) + 1 - _))),
          Resto = Number.Mod(Soma * 10, 11),
          Digito = if Resto = 10 then 0 else Resto
        in
          Digito,
      NumerosBase = List.Transform(Text.ToList(Text.Start(CPF_Limpo, 9)), each Number.FromText(_)),
      Digito1Esperado = Number.FromText(Text.Middle(CPF_Limpo, 9, 1)),
      Digito2Esperado = Number.FromText(Text.Middle(CPF_Limpo, 10, 1)),
      Digito1Calculado = CalculaDigito(NumerosBase),
      Digito2Calculado = CalculaDigito(NumerosBase & {Digito1Calculado}),
      CPF_Valido = TamanhoValido and not SequenciaInvalida and Digito1Calculado = Digito1Esperado and Digito2Calculado = Digito2Esperado
    in
      CPF_Valido,
  documentation = [
    Documentation.Name = "fnValidaCPF",
    Documentation.Description = "Valida um CPF, verificando sua estrutura e calculando os dígitos verificadores.",
    Documentation.LongDescription = "Esta função recebe um CPF, podendo estar formatado ('123.456.789-09') ou sem formatação ('12345678909'), e verifica sua validade. Ela remove caracteres indesejados, impede o uso de CPFs inválidos (como sequências repetitivas) e valida os dígitos verificadores com base no cálculo oficial.",
    Documentation.Category = "Funções de Validação",
    Documentation.Author = "Paulo André Jesus",
    Documentation.Examples = {
      [Description = "Validar um CPF correto.", Code = "fnValidaCPF('123.456.789-09')", Result = "true"],
      [Description = "Validar um CPF inválido com sequência repetitiva.", Code = "fnValidaCPF('111.111.111-11')", Result = "false"]
    }
  ]
in
  Value.ReplaceType(Source, Value.ReplaceMetadata(Value.Type(Source), documentation))
  • m
  • udf
  • validacao
  • cpf
  • brasil

Funções Geográficas

1

fnGrausParaDecimais

Converte coordenadas no formato de graus, minutos e segundos para um valor decimal, interpretando a direção (N/S/E/W/O) para aplicar o sinal correto.

IntermediárioUDFv1.0.0
let
  Source = (graus as text) as number =>
    let
      Fonte = graus,
      Graus = Number.From(Text.BeforeDelimiter(Fonte, "°")),
      Minutos = Number.From(Text.BetweenDelimiters(Fonte, "°", "'")) / 60,
      Segundos = Number.From(Text.BetweenDelimiters(Fonte, "'", """"")) / 3600,
      Coordenada = Text.End(Fonte, 1),
      Final =
        if Coordenada = "S" or Coordenada = "W" or Coordenada = "O" then
          - (Graus + Minutos + Segundos)
        else
          Graus + Minutos + Segundos
    in
      Final,
  documentation = [
    Documentation.Name = "fnGrausParaDecimais",
    Documentation.Description = "Converte coordenadas no formato de graus, minutos e segundos para um valor decimal.",
    Documentation.LongDescription = "Recebe uma coordenada geográfica em texto (ex.: 23°34'45\"S) e converte para decimal, interpretando a direção (N, S, E, W, O) para aplicar o sinal correto ao valor resultante.",
    Documentation.Category = "Funções Geográficas",
    Documentation.Author = "Paulo André Jesus",
    Documentation.Examples = {
      [Description = "Converter coordenada sul para decimal.", Code = "fnGrausParaDecimais('23°34'45\"S')", Result = "-23.5791666666667"]
    }
  ]
in
  Value.ReplaceType(Source, Value.ReplaceMetadata(Value.Type(Source), documentation))
  • m
  • udf
  • geografia
  • coordenadas

Text

1

fnRemoveAcentos

Remove acentos de um texto, convertendo a codificação de 1251 para UTF-8.

BásicoUDFv1.0.0
let
  Source = (texto as nullable text) =>
    let
      Binario = Text.ToBinary(texto, 1251),
      SemAcento = Text.FromBinary(Binario, TextEncoding.Utf8)
    in
      SemAcento,
  documentation = [
    Documentation.Name = "fnRemoveAcentos",
    Documentation.Description = "Remove os acentos do texto.",
    Documentation.LongDescription = "Converte a codificação do texto de 1251 para UTF-8. Durante o processo, caracteres não suportados na codificação 1251 podem ser substituídos ou removidos, resultando na perda de acentos e caracteres especiais.",
    Documentation.Category = "Text",
    Documentation.Source = "Adaptado de https://stackoverflow.com/questions/71969831/power-query-how-to-remove-diacritic-accent-symbols-from-text",
    Documentation.Version = "1.0",
    Documentation.Author = "Paulo André Jesus",
    Documentation.Examples = {
      [Description = "Exemplo de remoção de acentos", Code = "fnRemoveAcentos('ÀÁÂÃÄÅÇÈÉÊË')", Result = "'AAAAAACEEEE'"]
    }
  ]
in
  Value.ReplaceType(Source, Value.ReplaceMetadata(Value.Type(Source), documentation))
  • m
  • udf
  • texto
  • acentos

Convenção de nomes — obrigatória

Tabela / Coluna

Cns + PascalCase

CnsClienteTratado

UDF

fn + PascalCase

fnFiscalYear
Documentação embutida: UDF documentada via Value.ReplaceType com Documentation.Name, Description, LongDescription, Category, Author, Version e Examples.