fx

DAX

Funções definidas pelo usuário (UDF)

Guia das UDFs em DAX: onde criar, tipos de parâmetro, VAL × EXPR, parâmetros opcionais, checagem de tipo, uso em medida e coluna, e limitações.

Uma UDF empacota uma lógica DAX com nome e parâmetros para reutilizar em medidas, colunas calculadas, cálculos visuais e outras funções. Está disponível para todos (GA) no Desktop e no Service desde junho/2026 e exige nível de compatibilidade do modelo 1702 ou superior.

1. Onde criar

OndeComo gravar no modelo
DAX Query ViewCodeLens Update model: Add new function acima da função, ou Update model with changes para todas
TMDL viewBotão Apply. No projeto .pbip, as funções ficam em definition/functions.tmdl
Model ExplorerNó Functions: criar e editar pela barra de fórmulas

No Model Explorer, o botão direito na função oferece Consultas rápidas (Evaluate, Define and evaluate, Define all functions in this model) e Script TMDL to.

Regras de nome

  • Função: letras, números, _ e ponto para agrupar (Vendas.Margem, Calendario.DiasUteis). Sem espaço, sem começar ou terminar com ponto, sem dois pontos seguidos, sem repetir nome de função nativa ou palavra reservada (measure, function, define).
  • Parâmetro: letras, números e _. Sem ponto e sem palavra reservada.

2. Anatomia

DEFINE
    /// Aplica imposto sobre um valor.
    /// @param {NUMERIC} valor - Valor antes do imposto
    /// @param {NUMERIC} [aliquota] - Alíquota opcional; padrão 0,1 (10%)
    /// @returns O valor com imposto
    FUNCTION Fiscal.ComImposto =
        ( valor : NUMERIC, aliquota : NUMERIC = 0.1 ) =>
            valor * ( 1 + aliquota )

EVALUATE
    ROW (
        "Padrão", Fiscal.ComImposto ( 100 ),
        "Alíquota 20%", Fiscal.ComImposto ( 100, 0.2 )
    )
-- 110 e 120
  • Descrição: /// acima da função, com as tags JSDoc @param e @returns. Comentário com // ou /* */ não aparece no IntelliSense.
  • Parâmetros: de 0 a 256. Cada um aceita [tipo] [subtipo] [modo], todos opcionais. Sem nada, o parâmetro vale AnyVal val.
  • Parâmetro opcional: = <expressão padrão> torna o argumento opcional. Dá para pular no meio (MinhaFuncao ( 1, , 3 )); o mínimo de argumentos é definido pelo último parâmetro obrigatório. A expressão padrão só enxerga o que existe onde a função foi definida e não pode usar outro parâmetro opcional.

3. Tipos de parâmetro

FamíliaTipoAceitaModo
ValorANYVALEscalar ou tabela. É o padrão quando o tipo é omitidoval (padrão) ou expr
ValorSCALAREscalar, com subtipo opcionalval (padrão) ou expr
ValorTABLETabela ou expressão de tabelaval (padrão) ou expr
ExpressãoANYREFQualquer referência — equivale a não restringir o tipo de expressãosempre expr
ExpressãoMEASUREREFReferência a medidasempre expr
ExpressãoCOLUMNREFReferência a colunasempre expr
ExpressãoTABLEREFReferência a tabelasempre expr
ExpressãoCALENDARREFReferência a calendáriosempre expr
  • Tipos de valor fazem conversão implícita ("5" vira 5 num INT64). Tipos de expressão não fazem.
  • Os tipos MEASUREREF, COLUMNREF, TABLEREF e CALENDARREF chegaram em março/2026; material mais antigo só cita ANYREF.
  • 💡 Use o tipo mais específico que resolve: o IntelliSense e a validação passam a recusar o argumento errado já na chamada.

Subtipos de SCALAR — declarar o subtipo já implica SCALAR:

SubtipoAceita
INT64Número inteiro
DECIMALDecimal fixo (moeda, 4 casas)
DOUBLEDecimal de ponto flutuante
NUMERICQualquer um dos três acima
STRINGTexto
DATETIMEData/hora
BOOLEANTRUE/FALSE
VARIANTQualquer escalar
DEFINE
    /// Converte para inteiro, arredondando.
    FUNCTION Tipo.ParaInteiro = ( x : INT64 ) => x

EVALUATE
    { Tipo.ParaInteiro ( 3.4 ), Tipo.ParaInteiro ( 3.5 ), Tipo.ParaInteiro ( "5" ) }
-- 3, 4, 5 (texto não numérico dá erro)

4. VAL × EXPR: onde o argumento é calculado

ModoQuando calculaHerda do chamador
valUma vez, antes de entrar na funçãoContexto de linha e de filtro
exprDentro da função, onde o parâmetro aparece — pode ser várias vezes, e em outro contextoSó o contexto de filtro
DEFINE
    /// Recebe a tabela já filtrada: o ALL de dentro não tem efeito.
    FUNCTION Contagem.LinhasAgora = ( t : TABLE VAL ) =>
        COUNTROWS ( CALCULATETABLE ( t, ALL ( 'Calendário' ) ) )

    /// Recebe a expressão: o ALL de dentro remove o filtro de ano.
    FUNCTION Contagem.LinhasDepois = ( t : TABLE EXPR ) =>
        COUNTROWS ( CALCULATETABLE ( t, ALL ( 'Calendário' ) ) )

EVALUATE
    ROW (
        "VAL (só 2025)", CALCULATE ( Contagem.LinhasAgora ( Vendas ), 'Calendário'[Ano] = 2025 ),
        "EXPR (todos os anos)", CALCULATE ( Contagem.LinhasDepois ( Vendas ), 'Calendário'[Ano] = 2025 )
    )

A consequência prática — transição de contexto. Um parâmetro expr não herda o contexto de linha. Dentro de um iterador:

  • Referência de medida (MEASUREREF, ou uma medida passada a ANYREF) faz a transição de contexto sozinha, como toda medida.
  • Expressão como SUM ( Vendas[Valor Venda] ) não faz: sem CALCULATE, ela devolve o total geral em cada linha.
DEFINE
    /// Soma a medida dos N maiores clientes.
    /// @param {MEASUREREF} medida - Medida a ranquear e somar
    /// @param {INT64} [n] - Quantidade de clientes; padrão 10
    FUNCTION Vendas.TopClientesMedida =
        ( medida : MEASUREREF, n : INT64 = 10 ) =>
            SUMX ( TOPN ( n, VALUES ( Cliente[Nome do Cliente] ), medida ), medida )

    /// Aceita qualquer expressão escalar: o CALCULATE garante a transição
    /// de contexto em cada cliente.
    /// @param {SCALAR} valorExpr - Medida ou expressão a ranquear e somar
    /// @param {INT64} [n] - Quantidade de clientes; padrão 10
    FUNCTION Vendas.TopClientes =
        ( valorExpr : SCALAR EXPR, n : INT64 = 10 ) =>
            SUMX (
                TOPN ( n, VALUES ( Cliente[Nome do Cliente] ), CALCULATE ( valorExpr ) ),
                CALCULATE ( valorExpr )
            )

EVALUATE
    ROW (
        "Top 10 (medida)", Vendas.TopClientesMedida ( [Total de Vendas] ),
        "Top 5 (expressão)", Vendas.TopClientes ( SUM ( Vendas[Valor Venda] ), 5 )
    )

💡 Convenção da casa: parâmetro expr termina em Expr (valorExpr), para quem chama saber que a expressão será calculada dentro da função.

5. Checagem de tipo e funções auxiliares

Para aceitar tipos diferentes ou validar a entrada, teste o valor no corpo da função. Em parâmetro expr, a checagem acontece quando o parâmetro é usado, não na chamada.

CategoriaFunções
NuméricoISNUMERIC, ISNUMBER
InteiroISINT64, ISINTEGER
Decimal fixoISDECIMAL, ISCURRENCY
Ponto flutuanteISDOUBLE
TextoISSTRING, ISTEXT
LógicoISBOOLEAN, ISLOGICAL
Data/horaISDATETIME
DEFINE
    /// Tamanho do texto, ou BLANK se não for texto.
    FUNCTION Texto.Tamanho = ( s ) =>
        IF ( ISSTRING ( s ), LEN ( s ), BLANK () )

EVALUATE
    { Texto.Tamanho ( "Power BI" ), Texto.Tamanho ( 123 ) }
-- 8 e BLANK
  • TABLEOF ( referência ): devolve a tabela de uma coluna, medida ou calendário — útil com ANYREF/COLUMNREF para descobrir sobre qual tabela iterar.
  • NAMEOF ( referência ): devolve o nome do objeto como texto.
  • INFO.USERDEFINEDFUNCTIONS (): lista as funções do modelo com todos os metadados (exige permissão de escrita). INFO.FUNCTIONS ( "ORIGIN", "2" ) traz só nome e poucos dados.

6. Onde usar

OndeExemploCuidado
MedidaTotal de Vendas c/ Imposto = Fiscal.ComImposto ( [Total de Vendas] )—
Coluna calculadaValor c/ Imposto = CONVERT ( Fiscal.ComImposto ( Vendas[Valor Venda] ), CURRENCY )A função precisa devolver sempre o mesmo tipo; fixe com CONVERT
Cálculo visualValor c/ Imposto = Fiscal.ComImposto ( [Valor Venda] )Só enxerga campos do visual; sem IntelliSense para UDF
Outra UDFFUNCTION Fiscal.ComImpostoEDesconto = ( valor : NUMERIC, desconto : NUMERIC ) => Fiscal.ComImposto ( valor - desconto )Sem recursão
Cadeia de formato dinâmicaNa medida, Formato → Dinâmico, expressão Formato.Escala ( SELECTEDMEASURE () )A medida continua numérica (gráficos funcionam). No visual, deixe Unidades de exibição em Nenhum, senão o visual reescala por cima.

💡 Uma função de formato substitui a mesma lógica copiada em cada medida: Total de Vendas, Margem e Custo passam a usar uma linha só. Veja Formato.Escala na Code Library UDF DAX.

7. Limitações

  • Sem recursão (nem mútua), sem sobrecarga e sem declarar tipo de retorno.
  • Sem descrição por parâmetro no modelo (a tag @param documenta no IntelliSense).
  • Não dá para ocultar a função, colocar em pasta de exibição nem traduzir.
  • Não funciona em modelo sem tabelas.
  • Em conexão dinâmica, as funções do modelo de origem não aparecem no Model Explorer; medidas de relatório podem chamá-las, mas sem IntelliSense. Em modelo composto, medidas do modelo não chamam UDF do modelo de origem.
  • ⚠️ Segurança em nível de objeto (OLS) não passa para a função. Uma função que usa uma medida protegida não fica protegida; para quem não tem acesso, a medida simplesmente não existe. Não exponha objetos protegidos em nomes ou descrições de função.
  • Nome sem tabela ([Valor]) é lido como medida: evite referência de coluna sem a tabela dentro de UDF.
  • Parâmetro expr que não é usado no corpo nunca é calculado.
  • A função não pode devolver um enum (os argumentos fixos de funções nativas).

Funções prontas e documentadas: Code Library UDF DAX. Como testar e gravar na DAX Query View: DAX Query.

Fontes