Compartir a través de


DAX Funciones definidas por el usuario (versión preliminar)

Nota:

DAX Las funciones definidas por el usuario se encuentran actualmente en versión preliminar.

DAX Las funciones definidas por el usuario (UDF) permiten empaquetar DAX la lógica y reutilizarla como cualquier otra DAX función. Las UDF presentan una nueva FUNCTION palabra clave, parámetros opcionales (escalar, tabla y referencias) y asistentes de comprobación de tipos que hacen que la creación sea más segura y clara. Después de definir una UDF, puede usarla en una medida, una columna calculada, un cálculo visual o incluso otras funciones definidas por el usuario. Los usuarios pueden centralizar las reglas de negocio, mejorar la capacidad de mantenimiento y evolucionar los cálculos de forma segura con el tiempo. Las funciones son primera clase de objetos de modelo que puede crear y administrar en DAX la vista de consulta y la vista TMDL, y se pueden ver en el Explorador de Modelos en el nodo Funciones.

Habilitación de funciones definidas por el usuario

Para probar UDF en escritorio:

  1. Vaya a Opciones de archivo > y opciones de configuración>.
  2. Seleccione Características de vista previa y compruebe DAX las funciones definidas por el usuario.
  3. Seleccione Aceptar y reinicie Power BI Desktop.

Definición y administración de funciones definidas por el usuario

Hay varias ubicaciones para definir y administrar funciones:

  • DAX vista de consulta (DQV). Definir y modificar funciones en DQV. DQV también incluye consultas rápidas del menú contextual (Evaluar, Definir y evaluar, y Definir todas las funciones en este modelo) para ayudarle a probar y gestionar las UDFs rápidamente.
  • Vista TMDL. Las UDF también se pueden crear y editar en TMDL. La vista TMDL también incluye Script TMDL a en el menú contextual.
  • Explorador de modelos. Las funciones existentes se pueden ver en el nodo Funciones en el Explorador de modelos.

Al definir una UDF, siga estos requisitos de nomenclatura:

Nombres de función:

  • Debe tener un formato correcto y único dentro del modelo.
  • Puede incluir puntos para el espacio de nombres (por ejemplo, Microsoft.PowerBI.MyFunc). No se puede iniciar ni terminar con un período o tener períodos consecutivos.
  • Aparte de los puntos, los nombres solo pueden contener caracteres alfanuméricos o caracteres de subrayado. No se permiten espacios ni caracteres especiales.
  • No debe estar en conflicto con las funciones integradas DAX o las palabras reservadas (por ejemplo, measure, function, define).

Nombres de parámetro:

  • Solo puede contener caracteres alfanuméricos o caracteres de subrayado. No se permiten períodos.
  • No debe ser una palabra reservada.

Uso de la vista de consulta DAX

Puede definir, actualizar y evaluar funciones definidas por el usuario en DAX la vista de consulta. Para obtener información adicional sobre la DAX vista de consulta, consulte DAX la vista de consulta.

Formulario general

DEFINE
    /// Optional description above the function
    FUNCTION <FunctionName> = ( [ParameterName]: [ParameterType], ... ) => <FunctionBody>

Sugerencia

Use /// para descripciones de funciones. Los comentarios de una sola línea (//) o de varias líneas (/* */) no aparecerán en descripciones de funciones de IntelliSense.

Ejemplo: Función fiscal simple

DEFINE
    /// AddTax takes in amount and returns amount including tax
    FUNCTION AddTax = 
        ( amount : NUMERIC ) =>
            amount * 1.1

EVALUATE
{ AddTax ( 10 ) }
// Returns 11

Guardar en el modelo

Para guardar una UDF desde la vista de consulta DAX en el modelo:

  • Haga clic en Actualizar modelo con cambios para guardar todas las UDF en la consulta.
  • O bien, haga clic en Actualizar modelo: agregue una nueva función encima de la función definida para guardar una única UDF.

Captura de pantalla de la vista de DAX consulta en Power BI Desktop, donde se resaltan dos ubicaciones donde puede guardar una función definida por el usuario. La primera es el botón Actualizar modelo con cambios en la parte superior de la vista. La segunda es una línea de estado en el editor de código con la etiqueta Update model: Add new function (Actualizar modelo): Agregar nueva función

Uso de la vista TMDL

Puede definir o actualizar funciones definidas por el usuario en la vista TMDL. Para obtener más información sobre la vista TMDL, consulte TMDL view.

Formulario general

createOrReplace
    /// Optional description above the function
    function <FunctionName> = ( [ParameterName]: [ParameterType], ... ) => <FunctionBody>

Ejemplo: Función fiscal simple

createOrReplace
    /// AddTax takes in amount and returns amount including tax
    function AddTax = 
        (amount : NUMERIC) =>
            amount * 1.1

Guardar en el modelo

Haga clic en el botón Aplicar en la parte superior de la vista para guardar todas las UDFs del script en el modelo.

Captura de pantalla de la vista TMDL en Power BI Desktop, resaltando el botón Aplicar en la parte superior de la vista. Esta es la ubicación donde puede guardar una función definida por el usuario.

Uso del script TMDL en un proyecto de Power BI

Las UDF también se incluyen en el script TMDL del modelo semántico cuando se usa un proyecto de Power BI. Se pueden encontrar en dentro functions.tmdl de la carpeta de definición .

Captura de pantalla de Visual Studio Code de un proyecto de Power BI. El Explorador está abierto a la carpeta del modelo semántico. 'functions.tmdl' está abierto en el editor de código. Se muestran tres funciones: CustomerLifetimeValue, AverageOrderValue y AddTax.

Uso del Explorador de modelos

Puede ver todas las funciones definidas por el usuario en el modelo desde el Explorador de modelos en el nodo Funciones . Para obtener más información sobre el Explorador de modelos, vea Explorador de modelos.

Panel explorador de modelos en Power BI Desktop en el que se muestra el nodo Funciones expandida. Se enumeran tres funciones definidas por el usuario: AddTax, AverageOrderValue y CustomerLifetimeValue.

En DAX la vista de consulta, puede usar consultas rápidas en el menú contextual de una UDF dentro del Explorador de modelos para definir y evaluar fácilmente las funciones.

El panel Explorador de modelos de Power BI Desktop muestra el nodo Funciones expandido. Hay dos menús contextuales abiertos: el primer menú proporciona consulta rápida, Cambiar nombre, Eliminar del modelo, Ocultar en la vista de informe, Mostrar todos, Contraer todo y Expandir todo. La consulta rápida está resaltada y seleccionada. El segundo menú está resaltado y ofrece opciones de consulta rápida Evaluar, Definir y evaluar, Definir nueva función y Definir todas las funciones de este modelo.

En la vista TMDL, puede arrastrar y colocar funciones en el lienzo o usar Script TMDL para en el menú contextual de una UDF dentro del Explorador de modelos para generar scripts.

El panel Explorador de modelos de Power BI Desktop muestra el nodo Funciones expandido. Hay dos menús contextuales abiertos: el primer menú proporciona Script a TMDL, Cambiar nombre, Eliminar del modelo, Ocultar en la vista de informe, Mostrar todo, Contraer todo y Expandir todo. Script a TMDL está resaltado y seleccionado. El segundo menú está resaltado y ofrece opciones de Script a TMDL, pestaña de script y portapapeles.

Utilización de DMVs para inspeccionar UDFs

Puede inspeccionar las UDF en el modelo mediante vistas de administración dinámica (DMV). Estas vistas permiten consultar información sobre las funciones, incluidas las funciones definidas por el usuario (UDF).

Puede usar la función INFO.FUNCTIONS para inspeccionar las UDFs en el modelo. Para restringir el resultado solo a UDF, especifique el ORIGIN parámetro como 2.

EVALUATE INFO.FUNCTIONS("ORIGIN", "2")

Esta consulta devuelve una tabla de todas las UDF que se encuentran actualmente en el modelo, incluido su nombre, descripción y metadatos asociados.

Uso de una función definida por el usuario

Una vez definida y guardada una UDF en el modelo, puede llamarla desde medidas, columnas calculadas, cálculos visuales y otras UDF. Esto funciona de la misma manera que llamar a funciones predefinidas DAX.

Llamar a una UDF en una medida

Use una UDF en una medida para aplicar lógica reutilizable con contexto de filtro completo.

Total Sales with Tax = AddTax ( [Total Sales] )

La medida de ejemplo se muestra en la tabla siguiente:

Tabla que muestra las ventas totales y las ventas totales con impuestos. Las ventas totales con impuestos están resaltadas. El panel de Visualizaciones está abierto. Las ventas totales con impuestos se resaltan en el campo de Columnas.

Llamar a una UDF en una columna calculada

Las UDF se pueden usar en una columna calculada para aplicar lógica reutilizable a cada fila de una tabla.

Nota:

Al usar una UDF en una columna calculada, asegúrese de que la función devuelve un escalar de un tipo coherente. Consulte Parámetros para obtener más información. Si es necesario, convierta el resultado en el tipo deseado mediante CONVERT o funciones similares.

Sales Amount with Tax = CONVERT ( AddTax ( 'Sales'[Sales Amount] ), CURRENCY )

Podemos ver esta medida de ejemplo que se usa en la tabla siguiente:

Tabla que muestra el monto de ventas y el monto de ventas con impuestos. El monto de ventas con impuestos está resaltado. El panel de Visualizaciones está abierto. El monto de ventas con impuestos está resaltado en el campo Columnas.

Llamar a una UDF en un cálculo visual

Puede usar UDF en un cálculo visual para aplicar lógica directamente al objeto visual. Para obtener más información sobre los cálculos visuales, vea Cálculos visuales.

Nota:

Los cálculos visuales solo funcionan en campos presentes en el objeto visual. No pueden tener acceso a objetos de modelo que no forman parte del objeto visual y no se pueden pasar objetos de modelo (como columnas o medidas no en el objeto visual) a una UDF en este contexto.

Sales Amount with Tax = AddTax ( [Sales Amount] )

Podemos ver esta medida de ejemplo en la tabla siguiente:

En el modo de edición de cálculo visual. Tabla que muestra Importe de Ventas e Importe de Ventas con Impuestos. Importe de Ventas con Impuestos está resaltado. La fórmula de cálculo visual para Importe de Ventas con Impuestos está resaltada.

Llamar a una UDF en otra UDF

Puede anidar UDFs llamando a una función desde otra. En este ejemplo definimos nuestra UDF simple AddTax y la llamamos en otra UDF, AddTaxAndDiscount.

DEFINE
    /// AddTax takes in amount and returns amount including tax
    FUNCTION AddTax = 
        ( amount : NUMERIC ) =>
            amount * 1.1

	FUNCTION AddTaxAndDiscount = 
        (
			amount : NUMERIC,
			discount : NUMERIC
		) =>
		    AddTax ( amount - discount )

EVALUATE
{ AddTaxAndDiscount ( 10, 2 ) }
// Returns 8.8

Parámetros

DAX Las UDF pueden aceptar cero o más parámetros. Al definir parámetros para una UDF, puede especificar opcionalmente sugerencias de tipo para cada parámetro:

  • Tipo: qué tipo de valor acepta el parámetro (AnyVal, Scalar, Tableo AnyRef).
  • Subtipo (solo para tipo escalar): el tipo de datos escalar específico (Variant, Int64, Decimal, Double, String, DateTime, Boolean, o Numeric).
  • ParameterMode: cuando se evalúa el argumento (val o expr).

Las sugerencias de tipo están en el formato: [type] [subtype] [parameterMode]

Puede incluir todas, algunas o ninguna de estas sugerencias de tipo para cada parámetro para que las funciones sean más seguras y predecibles en los sitios de llamadas. Si omite todo y simplemente escribe el nombre del parámetro que se comporta como AnyVal val, lo que significa que el argumento se evalúa inmediatamente en el momento de la llamada. Esto es útil para funciones sencillas.

Tipo

El tipo define la categoría de argumento que acepta el parámetro y si se pasa como un valor o una expresión.

Hay dos familias de tipos en DAX parámetros UDF: tipos de valor y tipos de expresión:

  • Tipos de valor: este argumento se evalúa inmediatamente (evaluación diligente) cuando se llama a la función y el valor resultante se pasa a la función.
    • AnyVal: acepta un escalar o una tabla. Este es el valor predeterminado si omite el tipo de un parámetro.
    • Scalar: acepta un valor escalar (puede agregar además un subtipo).
    • Table: acepta una tabla.
  • Tipos de expresión: este argumento pasa una expresión no evaluada (evaluación diferida). La función decide cuándo y en qué contexto se va a evaluar. Esto es necesario para los parámetros de referencia y resulta útil cuando necesita controlar el contexto de filtro (por ejemplo, dentro de CALCULATE). expr Los tipos pueden ser referencias a una columna, tabla, calendario o medida.
    • AnyRef: acepta una referencia (una columna, una tabla, un calendario o una medida).

Subtipo

El subtipo le permite definir un tipo de datos específico Scalar . Si define un subtipo, no es necesario definir explícitamente el parámetro como un Scalar tipo, se asume automáticamente.

Los subtipos son:

  • Variant: acepta cualquier escalar.
  • Int64: acepta un número entero.
  • Decimal: acepta un decimal de precisión fija (como Moneda o Dinero).
  • Double: acepta un decimal de punto flotante.
  • String: acepta texto.
  • DateTime: acepta fecha y hora.
  • Boolean: acepta TRUE/FALSE.
  • Numeric: acepta cualquier valor numérico (Int64, Decimalo Double subtipos)

ParameterMode

ParameterMode controla cuándo y dónde se evalúa la expresión de parámetro. Estos son:

  • val (evaluación diligente): la expresión se evalúa una vez antes de invocar la función. A continuación, el valor resultante se pasa a la función . Esto es común para entradas escalares o de tabla simples. Este es el valor predeterminado si omite parameterMode para un parámetro.
  • expr (evaluación diferida): la expresión se evalúa dentro de la función, potencialmente en un contexto diferente (por ejemplo, contexto de fila o contexto de filtro) y posiblemente varias veces si se hace referencia a varias veces o dentro de iteraciones. Esto es necesario para los parámetros de referencia y resulta útil cuando necesita controlar el contexto de evaluación.

El Scalar tipo puede usar val o expr. Use val cuando desee que el escalar se evalúe una vez en el contexto del llamador. Use expr cuando desee aplazar la evaluación y, posiblemente, aplicar contexto dentro de la función. Vea Ejemplo: Parámetro de tabla como ejemplo.

El AnyRef tipo debe ser expr como sus referencias (columnas, tablas, medidas, etc.) deben evaluarse en el contexto de la función.

Ejemplo: conversión de tipos

DEFINE
    /// returns x cast to an Int64
    FUNCTION CastToInt = (
            x : SCALAR INT64 VAL
        ) =>
        x

EVALUATE
{ CastToInt ( 3.4 ), CastToInt ( 3.5 ), CastToInt ( "5" ) }
// returns 3, 4, 5

Esto usa un Scalar tipo, un Int64 subtipo y un val modo de parámetro para redondeo predecible y coerción de texto a número, así como garantizar que se evalúen rápidamente las expresiones. También puede lograrlo mediante la inclusión del Int64 subtipo como se muestra en el ejemplo siguiente. Las cadenas no numéricas producirán un error.

DEFINE
    /// returns x as an Int64
    FUNCTION CastToInt = (
            x : INT64
        ) =>
        x

EVALUATE
{ CastToInt ( 3.4 ), CastToInt ( 3.5 ), CastToInt ( "5" ) }
// returns 3, 4, 5

Ejemplo: Parámetro de tabla (valor frente a expresión)

Para ilustrar cómo el parámetro UDFMode afecta al contexto de filtro, tenga en cuenta dos funciones que cuentan filas en la tabla "Sales". Ambos usan CALCULATETABLE(t, ALL('Date')) en sus cuerpos, pero un parámetro se declara como una val (evaluación diligente) y el otro como expr (evaluación diferida):

DEFINE
    /// Table val: receives a materialized table, context can't be changed
    FUNCTION CountRowsNow = (
            t : TABLE VAL
        ) =>
        COUNTROWS ( CALCULATETABLE ( t, ALL ( 'Date' ) ) )
    
    /// Table expr: receives an unevaluated expression, context CAN be changed
    FUNCTION CountRowsLater = (
            t : TABLE EXPR
        ) =>
        COUNTROWS ( CALCULATETABLE ( t, ALL ( 'Date' ) ) )

EVALUATE
{
    CALCULATE ( CountRowsNow ( 'Sales' ), 'Date'[Fiscal Year] = "FY2020" ),
    CALCULATE ( CountRowsLater ( 'Sales' ), 'Date'[Fiscal Year] = "FY2020" )
}
// returns 84285, 121253

CountRowsNow devuelve solo el recuento de ventas para FY2020. La tabla "Sales" ya está filtrada por el año antes de escribir la función, por lo que ALL('Date') dentro de la función no tiene ningún efecto.

CountRowsLater devuelve el recuento de ventas durante todos los años. La función recibe una expresión de tabla no evaluada y la evalúa en ALL('Date'), quitando el filtro de año externo.

Comprobación de tipos

La comprobación de tipos en UDFs se puede realizar con funciones de comprobación de tipos nuevas y existentes que puede llamar dentro del cuerpo de la función para confirmar el tipo en tiempo de ejecución de los parámetros pasados. Esto permite que las UDF usen el control de contexto, validen los parámetros por adelantado y normalicen las entradas antes del cálculo.

Nota:

Para los parámetros en modo expr parameterMode, las comprobaciones de tipo se producen cuando el parámetro se menciona en el cuerpo de la función (no en el momento de la llamada de función).

Funciones de comprobación de tipos disponibles

Las UDF pueden usar las siguientes funciones para probar valores escalares. Cada valor devuelto TRUE/FALSE depende de si el valor proporcionado es de ese tipo.

Categoría Functions
Numeric ISNUMERIC, ISNUMBER
Double ISDOUBLE
Número entero ISINT64, ISINTEGER
Decimal ISDECIMAL, ISCURRENCY
String ISSTRING, ISTEXT
Boolean ISBOOLEAN, ISLOGICAL
Fecha y hora ISDATETIME

Ejemplo: Comprobación de si el parámetro es una cadena

DEFINE
    /// Returns the length of a string, or BLANK if not a string
    FUNCTION StringLength = (
            s
        ) =>
        IF ( ISSTRING ( s ), LEN ( s ), BLANK () )

EVALUATE
{ StringLength ( "hello" ), StringLength ( 123 ) }
// Returns: 5, BLANK

Esto evita errores y permite decidir cómo controlar la entrada que no es de cadena en la función (en este ejemplo, devuelve BLANK).

Ejemplo: Aceptar varios tipos de parámetros

DEFINE
    /// Helper 1: get currency name by int64 key
    FUNCTION GetCurrencyNameByKey = (
            k : INT64
        ) =>
        LOOKUPVALUE ( 'Currency'[Currency], 'Currency'[CurrencyKey], k )
    
    /// Helper 2: get currency name by string code
    FUNCTION GetCurrencyNameByCode = (
            code : STRING
        ) =>
        LOOKUPVALUE ( 'Currency'[Currency], 'Currency'[Code], code )
    
    /// Accepts key (int64) or code (string) and returns the currency name
    FUNCTION GetCurrencyName = (
            currency
        ) =>
        IF (
            ISINT64 ( currency ),
            GetCurrencyNameByKey ( currency ),
            GetCurrencyNameByCode ( currency )
        )

EVALUATE
{ GetCurrencyName ( 36 ), GetCurrencyName ( "USD" ) }
// returns "Euro", "US Dollar"

En este ejemplo se muestra cómo usar la comprobación de tipos en UDF para aceptar de forma segura varios tipos de entrada y devolver un único resultado predecible. GetCurrencyName toma un argumento, currency, que puede ser una clave de moneda de número entero o un código de moneda de texto. La función comprueba el tipo de argumento con ISINT64. Si la entrada es un entero, llama al asistente GetCurrencyNameByKey que busca el nombre de moneda en función de la clave de moneda. Si la entrada no es un entero, llama al asistente GetCurrencyNameByCode que busca el nombre de moneda en función del código de moneda.

Definir varias funciones a la vez

Las UDF permiten definir varias funciones en una sola consulta o script, lo que facilita la organización de la lógica reutilizable. Esto es especialmente útil cuando se quieren encapsular los cálculos relacionados o rutinas auxiliares juntas. Las funciones se pueden evaluar juntas o individualmente.

DEFINE
    /// Multiplies two numbers
    FUNCTION Multiply = (
            a,
            b
        ) =>
        a * b

    /// Adds two numbers and 1
    FUNCTION AddOne = (
            x,
            y
        ) =>
        x + y + 1

    /// Returns a random integer between 10 and 100
    FUNCTION RandomInt = () =>
        RANDBETWEEN ( 10, 100 )

EVALUATE
{ Multiply ( 3, 5 ), AddOne ( 1, 2 ), RandomInt () }
// returns 15, 4, 98

Ejemplo avanzado: Conversión de moneda flexible

Para mostrar cómo DAX las UDF pueden controlar la lógica más compleja, veremos un escenario de conversión de moneda. En este ejemplo se utilizan funciones anidadas y verificación de tipos para convertir una cantidad determinada en una moneda de destino mediante el tipo de cambio promedio o de cierre para una fecha determinada.

createOrReplace
	function ConvertDateToDateKey =  
		( 
			pDate: scalar variant 
		) => 
		YEAR ( pDate ) * 10000 + MONTH ( pDate ) * 100 + DAY ( pDate ) 
	
	function ConvertToCurrency = 
		( 
			pCurrency:scalar variant, 
			pDate: scalar variant, 
			pUseAverageRate: scalar boolean, 
			pAmount: scalar decimal 
		) => 
		var CurrencyKey = 
			EVALUATEANDLOG ( 
				IF ( 
					ISINT64 ( pCurrency ), 
					pCurrency, 
					CALCULATE ( 
						MAX ( 'Currency'[CurrencyKey] ), 
						'Currency'[Code] == pCurrency 
					) 
				) 
				, "CurrencyKey" 
			) 

		var DateKey = 
			EVALUATEANDLOG ( 
				SWITCH ( 
					TRUE, 
					ISINT64 ( pDate ), pDate, 
					ConvertDateToDateKey ( pDate ) 
				) 
				, "DateKey" 
			) 

		var ExchangeRate = 
			EVALUATEANDLOG ( 
				IF ( 
					pUseAverageRate, 
					CALCULATE ( 
						MAX ( 'Currency Rate'[Average Rate] ), 
						'Currency Rate'[DateKey] == DateKey, 
						'Currency Rate'[CurrencyKey] == CurrencyKey 
					), 
					CALCULATE ( 
					MAX ( 'Currency Rate'[End Of Day Rate] ), 
						'Currency Rate'[DateKey] == DateKey, 
						'Currency Rate'[CurrencyKey] == CurrencyKey 
					) 
				) 
				, "ExchangeRate" 
			) 

		var Result = 
			IF ( 
				ISBLANK ( pCurrency ) || ISBLANK ( pDate ) || ISBLANK ( pAmount ), 
				BLANK (), 
				IF ( 
					ISBLANK ( ExchangeRate ) , 
					"no exchange rate available", 
					ExchangeRate * pAmount 
				) 
			) 

		RETURN Result

La ConvertToCurrency función acepta tipos de entrada flexibles para la moneda y la fecha. Los usuarios pueden proporcionar una clave de moneda o una clave de fecha directamente o proporcionar un código de moneda o un valor de fecha estándar. La función comprueba el tipo de cada entrada y la controla en consecuencia: si pCurrency es un número entero, se trata como una clave de moneda; de lo contrario, la función asume un código de moneda e intenta resolver la clave correspondiente. pDate sigue un patrón similar, si es un número entero, se trata como una clave de fecha; de lo contrario, la función supone que es un valor de fecha estándar y se convierte en una clave de fecha mediante la ConvertDateToDateKey función auxiliar. Si la función no puede determinar una tasa de exchnage válida, devuelve el mensaje "sin tipo de cambio disponible".

Esta lógica se puede usar para definir una medida como Ventas totales en moneda local.

Total Sales in Local Currency = 
ConvertToCurrency (
    SELECTEDVALUE ( 'Currency'[Code] ),
    SELECTEDVALUE ( 'Date'[DateKey] ),
    TRUE,
    [Total Sales]
)

Esto se puede emparejar opcionalmente con una cadena de formato dinámico para mostrar el resultado en el formato de moneda adecuado.

CALCULATE (
    MAX ( 'Currency'[Format String] ),
    'Currency'[Code] == SELECTEDVALUE ( 'Currency'[Code] )
)

Se puede ver un resultado de ejemplo en la captura de pantalla siguiente.

Tabla que muestra la fecha completa, la moneda, las ventas totales en moneda local y las ventas totales.

Consideraciones y limitaciones

Las funciones definidas por el usuario se encuentran actualmente en versión preliminar y, durante la versión preliminar, tenga en cuenta las siguientes consideraciones y limitaciones:

General:

  • No se pueden crear o modelar DAX UDFs en el servicio.

  • No se puede ocultar o desactivar una UDF en el modelo.

  • No se pueden colocar UDFs en carpetas de visualización.

  • No hay ningún botón "crear función" en la cinta de opciones.

  • No se pueden combinar las UDFs con traducciones.

  • Las UDF no se admiten en modelos sin tablas.

  • Ninguna consulta rápida "definir con referencias" en DAX la vista de consulta.

  • Object-Level Security (OLS) no se transfiere a funciones ni viceversa. Por ejemplo, considere la siguiente función F que hace referencia a la medida MyMeasureprotegida :

    function F = () => [MyMeasure] + 42
    

    Cuando el MyMeasure se protege mediante la seguridad de nivel de objeto, la función F no se protege automáticamente. Si F se ejecuta bajo una identidad sin acceso a MyMeasure, actúa como si MyMeasure no existe. Se recomienda evitar revelar objetos seguros en los nombres de función y las descripciones.

Definición de una UDF:

  • No se admite la recursividad ni la recursividad mutua.
  • No se admite la sobrecarga de funciones.
  • No se admiten tipos de valor devuelto explícitos.

Parámetros de UDF:

  • No se admiten parámetros opcionales.
  • No se admiten descripciones de parámetros.
  • Las UDF no pueden devolver un enum valor. Las funciones integradas que aceptan enum valores como parámetros de función no podrán usar UDF en ese contexto.
  • Los parámetros sin enlazar de la pista de tipo expr no se evalúan.

Compatibilidad con IntelliSense:

  • Aunque las UDF se pueden usar en modelos de conexión dinámica o compuestos, no hay compatibilidad con IntelliSense.
  • Aunque las UDF se pueden usar en cálculos visuales, la barra de fórmulas de cálculos visuales no tiene compatibilidad con IntelliSense para UDF.
  • La vista TMDL no tiene compatibilidad adecuada con IntelliSense para las UDF.

Errores conocidos

Actualmente se conocen los siguientes problemas y pueden afectar a la funcionalidad:

  • Las referencias a un objeto de modelo tabular (por ejemplo, medida, tabla, columna) de una UDF no se actualizan automáticamente cuando se cambia el nombre de esos objetos. Si cambia el nombre de un objeto en el que depende una UDF, el cuerpo de la función seguirá contiene el nombre anterior. Debe editar manualmente la expresión UDF para actualizar todas las referencias al objeto cuyo nombre ha cambiado.
  • Algunos escenarios avanzados que implican UDF pueden dar lugar a incoherencias del analizador. Por ejemplo, los usuarios pueden ver subrayados rojos o errores de validación al pasar columnas como expr parámetros o usar referencias de columna no calificadas.