🔍

Funciones de Información

ISBLANK, ISERROR, ISNUMBER, ISINSCOPE, HASONEVALUE, CUSTOMDATA y todas las funciones que te cuentan en qué contexto está tu medida

Principiante Intermedio Avanzado
🔍
🔢

IS de tipo — verificar el tipo de dato

FUNCIÓN DEVUELVE TRUE CUANDO... EJEMPLO
ISNUMBER(x) x es un número ISNUMBER(42) → TRUE
ISTEXT(x) x es texto (string) ISTEXT("hola") → TRUE
ISLOGICAL(x) x es TRUE o FALSE ISLOGICAL(TRUE) → TRUE
ISDATE(x) x es una fecha/hora ISDATE(TODAY()) → TRUE
ISNONE(x) x es NONE (tipo especial interno) Uso muy raro
ISNUMBER(<valor>) | ISTEXT(<valor>)
Principiante — Intermedio
Validan el tipo de dato de una expresión. Muy útiles para limpiar datos donde una columna puede contener mezcla de tipos (común al importar desde Excel o CSV).

Ejemplo — datos mixtos:

// Columna 'Productos'[Precio] importada de Excel con algún texto ("N/A", "pendiente"):
Precio Seguro =
IF(
    ISNUMBER('Productos'[Precio]),
    'Productos'[Precio],
    0
)

// Limpiar columna que debería ser número:
Precio Limpio =
IF(
    ISNUMBER(VALUE('Productos'[Precio_texto])),
    VALUE('Productos'[Precio_texto]),
    BLANK()
)

// Detectar códigos que no son numéricos (posiblemente erróneos):
'Productos'[Código Inválido] =
IF(ISNUMBER(VALUE('Productos'[Código])), FALSE, TRUE)
🔍

IS de valor — verificar el valor

ISBLANK(<valor>)
Principiante
Devuelve TRUE si el valor es BLANK() — el valor nulo de DAX. Fundamental para controlar el comportamiento de medidas cuando no hay datos.
// Mostrar "Sin datos" cuando no hay ventas en el período:
Ventas Display =
IF(
    ISBLANK([Total Ventas]),
    "Sin datos en este período",
    FORMAT([Total Ventas], "#,##0 €")
)

// Evitar calcular variaciones cuando no hay dato anterior:
Variación YoY =
VAR Anterior = CALCULATE([Total Ventas], SAMEPERIODLASTYEAR('Calendario'[Date]))
RETURN
IF(
    ISBLANK(Anterior),
    BLANK(),  -- no mostrar nada si no hay dato del año anterior
    DIVIDE([Total Ventas] - Anterior, Anterior)
)

// ISBLANK vs = BLANK():
ISBLANK([Ventas])   -- la forma correcta
[Ventas] = BLANK()  -- también funciona pero menos idiomática
ISEMPTY(<tabla>)
Intermedio
Devuelve TRUE si la tabla no tiene filas. Imprescindible para verificar si un filtro o una tabla calculada tiene resultados antes de operar con ella.
// ¿El cliente tiene pedidos en el período seleccionado?
Tiene Pedidos =
IF(
    ISEMPTY(RELATEDTABLE('Pedidos')),
    "Sin pedidos",
    "Activo: " & COUNTROWS(RELATEDTABLE('Pedidos')) & " pedidos"
)

// Evitar errores al procesar tablas vacías:
Mejor Cliente =
VAR TablaFiltrada = FILTER('Clientes', [Total Ventas] > 10000)
RETURN
IF(
    ISEMPTY(TablaFiltrada),
    "Ningún cliente supera 10.000 €",
    MAXX(TablaFiltrada, [Total Ventas])
)
ISONORAFTER(<valor1>, <orden1>, <valor2>, <orden2>, ...)
Avanzado (nicho)
Devuelve TRUE si los valores especificados son posteriores o iguales a los valores de orden dado. Usada principalmente para paginación en queries DAX avanzadas (reemplaza TOPNSKIP en algunos patrones).
// ¿Es la fila actual posterior a (2024, "Electrónica") en orden ascendente?
ISONORAFTER(
    'Calendario'[Año], 2024, ASC,
    'Productos'[Categoría], "Electrónica", ASC
)
// Útil para cursor-based pagination en API de DAX
🎯

IS de contexto de filtro — ¿Qué hay filtrado?

Las funciones más útiles para medidas dinámicas

HASONEVALUE(<columna>)
Intermedio
Devuelve TRUE si hay exactamente UN VALOR visible en la columna dentro del contexto actual. Perfecto para verificar que un slicer tiene exactamente una selección antes de actuar sobre ella.
// Título del visual que muestra el país si hay uno seleccionado:
Título País =
IF(
    HASONEVALUE('Clientes'[País]),
    "Ventas en " & VALUES('Clientes'[País]),
    "Ventas por país"
)

// Actuar diferente según si hay uno o varios países:
KPI País =
IF(
    HASONEVALUE('Clientes'[País]),
    "País: " & SELECTEDVALUE('Clientes'[País]) & " — " & FORMAT([Total Ventas], "#,##0 €"),
    FORMAT([Total Ventas], "#,##0 €") & " (múltiples países)"
)
HASONEFILTER(<columna>)
Avanzado
Devuelve TRUE si hay exactamente UN FILTRO directo sobre la columna. Diferencia con HASONEVALUE: HASONEFILTER mira si hay un filtro activo, no si hay un único valor. Una columna puede tener un filtro que incluya varios valores (ej: IN {"España", "Francia"}).

Diferencia HASONEVALUE vs HASONEFILTER:

// Slicer con "España" seleccionado:
HASONEVALUE('Clientes'[País])   → TRUE  (hay exactamente un valor visible)
HASONEFILTER('Clientes'[País])  → TRUE  (hay exactamente un filtro directo)

// Slicer con "España" y "Francia" seleccionados:
HASONEVALUE('Clientes'[País])   → FALSE (hay dos valores visibles)
HASONEFILTER('Clientes'[País])  → TRUE  (hay un filtro, que incluye dos valores)

// Sin slicer (todos los países):
HASONEVALUE('Clientes'[País])   → FALSE
HASONEFILTER('Clientes'[País])  → FALSE
ISFILTERED(<columna_o_tabla>)
Avanzado
Devuelve TRUE si la columna o tabla tiene algún filtro DIRECTO aplicado en el contexto actual. Distinto de ISCROSSFILTERED que incluye filtros indirectos también.
// ¿Hay algún filtro en el país?
Hay Filtro País = ISFILTERED('Clientes'[País])
// TRUE si hay un slicer de País activo con cualquier selección

// Mensaje contextual:
Contexto Filtro =
SWITCH(
    TRUE(),
    ISFILTERED('Clientes'[País]) && ISFILTERED('Productos'[Categoría]),
    "Filtrado por País y Categoría",
    ISFILTERED('Clientes'[País]),
    "Filtrado por País: " & SELECTEDVALUE('Clientes'[País], "varios"),
    ISFILTERED('Productos'[Categoría]),
    "Filtrado por Categoría: " & SELECTEDVALUE('Productos'[Categoría], "varias"),
    "Sin filtros activos"
)
ISCROSSFILTERED(<columna_o_tabla>)
Avanzado
Devuelve TRUE si la columna o tabla tiene filtros aplicados, ya sea directamente O a través de relaciones (filtrado cruzado). Más amplio que ISFILTERED.

Diferencia ISFILTERED vs ISCROSSFILTERED:

// Si tienes filtro en Productos[Categoría] y hay relación Productos → Ventas:
ISFILTERED('Ventas'[Importe])        → FALSE (el filtro es indirecto)
ISCROSSFILTERED('Ventas'[Importe])   → TRUE  (hay filtro a través de la relación)
ISCROSSFILTERED('Ventas')            → TRUE  (la tabla está siendo filtrada por relación)
📐

IS de scope — saber en qué nivel de jerarquía estás

ISINSCOPE(<columna>)
Avanzado
Devuelve TRUE si la columna especificada está en el nivel actual de agrupación del visual. Esencial para escribir medidas que se comporten diferente en distintos niveles de una jerarquía (filas de detalle vs subtotales vs gran total).

Por qué es tan importante:

Cuando tienes una matriz con jerarquías (País > Región > Ciudad), la misma medida se evalúa en diferentes contextos:

  • Fila de Ciudad: contexto de Ciudad (el más detallado)
  • Fila de Región: contexto de Región (subtotal)
  • Fila de País: contexto de País (subtotal mayor)
  • Gran total: sin contexto de ninguna columna de la jerarquía

ISINSCOPE te dice en qué nivel está evaluándose la medida en ese momento.

Ejemplo básico — diferente cálculo por nivel:

// En una matriz País > Región > Ciudad:
Métrica Inteligente =
SWITCH(
    TRUE(),
    ISINSCOPE('Geografía'[Ciudad]),    [Total Ventas],    -- nivel Ciudad
    ISINSCOPE('Geografía'[Región]),    [Total Ventas],    -- nivel Región
    ISINSCOPE('Geografía'[País]),      [Total Ventas],    -- nivel País
    [Total Ventas]                                         -- gran total
)

// Caso práctico — porcentaje solo en niveles de detalle:
% Contribución =
IF(
    ISINSCOPE('Productos'[Producto]),  -- solo a nivel producto
    DIVIDE(
        [Total Ventas],
        CALCULATE([Total Ventas], ALLEXCEPT('Productos', 'Productos'[Categoría]))
    ),
    BLANK()  -- en subtotales y total: no mostrar porcentaje
)

// Mostrar icono distinto según nivel:
Indicador Nivel =
SWITCH(
    TRUE(),
    ISINSCOPE('Geografía'[Ciudad]),  "📍 " & [Total Ventas],
    ISINSCOPE('Geografía'[Región]),  "🗺️ " & [Total Ventas],
    ISINSCOPE('Geografía'[País]),    "🌍 " & [Total Ventas],
    "🌐 Gran Total: " & [Total Ventas]
)

// Mostrar margen % en detalle pero recuento en subtotales:
KPI Adaptativo =
IF(
    ISINSCOPE('Productos'[SKU]),
    FORMAT([Margen %], "0.0%"),      -- en filas de producto: margen
    FORMAT([Nº Pedidos], "#,##0")    -- en subtotales: número de pedidos
)
🏆 Best practice
ISINSCOPE es la solución correcta para medidas que deben mostrar cosas distintas en distintos niveles de jerarquía. Muchas personas intentan usar ISFILTERED o HASONEVALUE para esto con resultados inconsistentes — ISINSCOPE es la herramienta diseñada exactamente para este caso.
ISATLEVEL(<columna>)
Avanzado
Devuelve TRUE si la columna está en el nivel de agrupación ACTUAL (no en un nivel padre). Similar a ISINSCOPE pero más estricto — ISINSCOPE devuelve TRUE en el nivel Y en todos los niveles inferiores de la jerarquía; ISATLEVEL solo en el nivel exacto.

Diferencia con ISINSCOPE:

// Jerarquía: País > Región > Ciudad
// Fila de "Madrid" (nivel Ciudad):

ISINSCOPE('Geografía'[País])    → TRUE  (Madrid está dentro de un País)
ISINSCOPE('Geografía'[Región])  → TRUE  (Madrid está dentro de una Región)
ISINSCOPE('Geografía'[Ciudad])  → TRUE  (estamos en nivel Ciudad)

ISATLEVEL('Geografía'[Ciudad])  → TRUE  (estamos EN el nivel Ciudad)
ISATLEVEL('Geografía'[País])    → FALSE (no estamos en el nivel País)
👤

Información del usuario y entorno

USERNAME()
Intermedio
Devuelve el nombre del usuario actual en formato DOMINIO\usuario. Útil para personalizar informes y para auditoría.
// Mostrar saludo personalizado:
Saludo = "Hola, " & USERNAME() & " 👋"

// Auditoría de quién está viendo qué:
// (Guardar en tabla de log con Power Automate)
USERPRINCIPALNAME()
Intermedio — Avanzado
Devuelve el email del usuario en Power BI Service (formato usuario@empresa.com). Es la función clave para implementar Row-Level Security (RLS) dinámica.

Ejemplo — RLS dinámica:

// Tabla de permisos: Email | Región
// 'Permisos'[Email] = "maria@empresa.com", 'Permisos'[Región] = "Norte"

// Rol de seguridad dinámico:
// En la tabla Ventas, filtro de seguridad:
[RegionVenta] IN
    CALCULATETABLE(
        VALUES('Permisos'[Región]),
        'Permisos'[Email] = USERPRINCIPALNAME()
    )
// Cada usuario solo ve las ventas de su región asignada en la tabla Permisos
CUSTOMDATA()
Avanzado (nicho)
Devuelve el valor de la propiedad CustomData de la cadena de conexión. Solo disponible cuando la conexión al modelo se establece con un valor CustomData personalizado (ej: desde una aplicación embebida con Power BI Embedded).

Ejemplo — RLS multi-tenant con Power BI Embedded:

// La aplicación pasa el TenantID en CustomData al conectarse
// La medida de seguridad usa ese valor:
// [TenantID] = CUSTOMDATA()
🔎

Búsqueda en tablas — CONTAINS y CONTAINSROW

CONTAINS(<tabla>, <columna>, <valor>, ...)
Intermedio — Avanzado
Devuelve TRUE si existe al menos una fila en la tabla donde las columnas indicadas tienen los valores especificados. Busca la existencia de una combinación de valores en una tabla.
// ¿Hay alguna venta del producto P001 al cliente C123?
Existe Combinación =
CONTAINS(
    'Ventas',
    'Ventas'[IDProducto], "P001",
    'Ventas'[IDCliente], "C123"
)

// ¿Vendemos en España Y Francia?
Vendemos en Iberia =
AND(
    CONTAINS(ALL('Clientes'), 'Clientes'[País], "España"),
    CONTAINS(ALL('Clientes'), 'Clientes'[País], "Francia")
)
CONTAINSROW(<tabla>, <fila_como_tabla>)
Avanzado
Devuelve TRUE si la fila especificada (como tabla de una fila) existe en la tabla. Variante más moderna de CONTAINS para verificar filas completas.
// ¿Existe la combinación (2024, "Norte") en la tabla de datos?
CONTAINSROW(
    SUMMARIZE('Ventas', 'Calendario'[Año], 'Clientes'[Región]),
    ROW("Año", 2024, "Región", "Norte")
)
🗂️

INFO.VIEW — Consulta los metadatos de tu propio modelo

Las funciones INFO.VIEW son especiales dentro de DAX: en lugar de calcular datos de negocio, devuelven información sobre la estructura del propio modelo semántico. Son perfectas para crear documentación automática que se actualiza sola con cada refresh. Llegaron en octubre de 2024 y son una de las novedades más prácticas de los últimos tiempos. 🗂️

⚠️ Requisitos
Estas funciones requieren permiso de escritura sobre el modelo semántico. No funcionan en Power BI Desktop en modo conexión en vivo (Live Connection). A diferencia de las funciones INFO.* sin VIEW (que solo funcionan en DAX Query View), las INFO.VIEW.* sí se pueden usar en tablas calculadas, columnas calculadas y medidas.
INFO.VIEW.TABLES()
Intermedio
Devuelve una tabla con información sobre cada tabla del modelo semántico: nombre, descripción, modo de almacenamiento, si está oculta y si está marcada como tabla de fechas.

Columnas principales que devuelve:

COLUMNA TIPO DESCRIPCIÓN
[Name] Texto Nombre de la tabla
[Description] Texto Descripción (si está documentada)
[StorageMode] Texto "Import", "DirectQuery", "Dual"
[IsHidden] Booleano TRUE si está oculta en el panel de campos
[IsDateTable] Booleano TRUE si está marcada como tabla de fechas

Ejemplos:

// Ver todas las tablas del modelo
EVALUATE INFO.VIEW.TABLES()

// Solo tablas visibles
EVALUATE
FILTER(
    INFO.VIEW.TABLES(),
    NOT [IsHidden]
)

// Tabla calculada de documentación automática
Doc_Tablas =
SELECTCOLUMNS(
    FILTER(INFO.VIEW.TABLES(), NOT [IsHidden]),
    "Tabla",           [Name],
    "Descripción",     [Description],
    "Modo",            [StorageMode],
    "Tabla de fechas", [IsDateTable]
)
INFO.VIEW.COLUMNS()
Intermedio
Devuelve una tabla con información sobre cada columna del modelo: nombre, tabla a la que pertenece, tipo de dato, si está oculta, formato y su expresión DAX si es columna calculada.

Columnas principales que devuelve:

COLUMNA TIPO DESCRIPCIÓN
[TableName] Texto Nombre de la tabla que contiene la columna
[Name] Texto Nombre de la columna
[DataType] Texto "Integer", "Double", "String", "DateTime", "Boolean"
[IsHidden] Booleano TRUE si está oculta
[Description] Texto Descripción de la columna
[FormatString] Texto Formato aplicado
[Expression] Texto Si es columna calculada, su fórmula DAX

Ejemplos:

// Diccionario de datos automático (tabla calculada)
Diccionario_Datos =
SELECTCOLUMNS(
    FILTER(
        INFO.VIEW.COLUMNS(),
        NOT [IsHidden]
    ),
    "Tabla",       [TableName],
    "Columna",     [Name],
    "Tipo",        [DataType],
    "Descripción", [Description],
    "Formato",     [FormatString]
)

// Contar columnas de texto del modelo
N Columnas Texto =
COUNTROWS(
    FILTER(INFO.VIEW.COLUMNS(), [DataType] = "String")
)

// Detectar columnas calculadas (tienen expresión DAX)
Columnas_Calculadas =
FILTER(
    INFO.VIEW.COLUMNS(),
    NOT ISBLANK([Expression])
)
INFO.VIEW.MEASURES()
Intermedio
Devuelve una tabla con información sobre cada medida: nombre, tabla de inicio, expresión DAX completa, formato, descripción, si está oculta y su estado de validación. Perfecta para auditorías de calidad del modelo.

Columnas principales que devuelve:

COLUMNA TIPO DESCRIPCIÓN
[Table] Texto Tabla donde está definida la medida
[Name] Texto Nombre de la medida
[Expression] Texto Fórmula DAX completa
[FormatString] Texto Formato (ej: "#,##0.00 €", "0.00%")
[Description] Texto Descripción de la medida
[IsHidden] Booleano TRUE si está oculta
[State] Texto "Ready" si es válida, o mensaje de error

Ejemplos:

// Todas las medidas con su fórmula
EVALUATE INFO.VIEW.MEASURES()

// Medidas con errores (auditoría de calidad)
EVALUATE
FILTER(
    INFO.VIEW.MEASURES(),
    [State] <> "Ready"
)

// Medidas sin descripción — ¡a documentar!
Medidas Sin Documentar =
COUNTROWS(
    FILTER(
        INFO.VIEW.MEASURES(),
        ISBLANK([Description])
    )
)

// Exportar toda la documentación de medidas
Doc_Medidas =
SELECTCOLUMNS(
    INFO.VIEW.MEASURES(),
    "Tabla",       [Table],
    "Medida",      [Name],
    "Descripción", [Description],
    "Fórmula DAX", [Expression],
    "Formato",     [FormatString],
    "Estado",      [State]
)
💡 Tip
La columna [State] = 'Ready' indica que la medida es válida. Cualquier otro valor indica una medida con error — quizás una referencia rota que no sabías que existía. ¡INFO.VIEW.MEASURES es tu mejor aliada para hacer auditorías de calidad del modelo!
INFO.VIEW.RELATIONSHIPS()
Intermedio
Devuelve una tabla con información sobre cada relación del modelo: tablas y columnas que conecta, cardinalidad, dirección de filtro y si está activa o inactiva.

Columnas principales que devuelve:

COLUMNA TIPO DESCRIPCIÓN
[FromTableName] Texto Tabla del lado "muchos"
[FromColumnName] Texto Columna de la tabla muchos
[ToTableName] Texto Tabla del lado "uno"
[ToColumnName] Texto Columna de la tabla uno
[CrossFilteringBehavior] Texto "OneDirection", "BothDirections"
[IsActive] Booleano TRUE si la relación está activa
[Cardinality] Texto "ManyToOne", "OneToOne", "ManyToMany"

Ejemplos:

// Diagrama de relaciones en texto (tabla calculada)
Doc_Relaciones =
ADDCOLUMNS(
    INFO.VIEW.RELATIONSHIPS(),
    "Relación",
        [FromTableName] & "[" & [FromColumnName] & "] → "
        & [ToTableName] & "[" & [ToColumnName] & "]",
    "Estado", IF([IsActive], "✅ Activa", "⚠️ Inactiva")
)

// Detectar relaciones bidireccionales (alerta de rendimiento)
Relaciones_Bidireccionales =
FILTER(
    INFO.VIEW.RELATIONSHIPS(),
    [CrossFilteringBehavior] = "BothDirections"
)

// Contar relaciones inactivas
Relaciones Inactivas =
COUNTROWS(
    FILTER(INFO.VIEW.RELATIONSHIPS(), NOT [IsActive])
)
⚠️ Alerta de rendimiento
Si tienes muchas relaciones con BothDirections puedes estar afectando el rendimiento del modelo. INFO.VIEW.RELATIONSHIPS te permite detectarlas todas de un vistazo.
📌 Patrón de auto-documentación completa
Combina las 4 funciones en un dashboard de calidad del modelo:

Total Tablas = COUNTROWS(INFO.VIEW.TABLES())
Total Columnas = COUNTROWS(INFO.VIEW.COLUMNS())
Total Medidas = COUNTROWS(INFO.VIEW.MEASURES())
Total Relaciones = COUNTROWS(INFO.VIEW.RELATIONSHIPS())

% Medidas documentadas = DIVIDE(COUNTROWS(FILTER(INFO.VIEW.MEASURES(), NOT ISBLANK([Description]))), COUNTROWS(INFO.VIEW.MEASURES()))

Con estas 5 medidas en un visual de tarjeta tienes un scorecard del estado de documentación de tu modelo.
⚙️

INFO.VIEW.* vs INFO.* — ¿cuál usar?

Además de las 4 funciones INFO.VIEW, DAX tiene más de 50 funciones INFO.* (sin VIEW) disponibles desde diciembre de 2023. Son los equivalentes exactos de los DMVs de Analysis Services. Aquí tienes la diferencia clave:

CARACTERÍSTICA INFO.VIEW.* INFO.*
Disponible desde Octubre 2024 Diciembre 2023
Tablas calculadas y medidas ✅ Sí ❌ No
Nombres amigables ✅ Sí ⚠️ Usa IDs numéricos
Número de funciones 4 50+
Para quién Cualquier dev Admins y power users
Dónde funciona En todo el modelo Solo DAX Query View

Las INFO.* sin VIEW usan IDs numéricos en lugar de nombres — por ejemplo, INFO.MEASURES() muestra un TableID en vez del nombre de la tabla, así que necesitas hacer un JOIN con INFO.TABLES() para obtener el nombre legible. Las INFO.VIEW.* ya resuelven eso por ti.

Ejemplo comparativo:

// ❌ INFO.MEASURES — solo en DAX Query View, devuelve TableID
EVALUATE INFO.MEASURES()
// Para ver el nombre de la tabla tienes que hacer:
EVALUATE
NATURALLEFTOUTERJOIN(
    INFO.MEASURES(),
    SELECTCOLUMNS(INFO.TABLES(), "TableID", [ID], "Tabla", [Name])
)

// ✅ INFO.VIEW.MEASURES — funciona en tablas calculadas, ya
//    incluye el nombre de la tabla directamente
EVALUATE INFO.VIEW.MEASURES()

Las INFO.* más útiles en DAX Query View (para admins):

  • INFO.MEASURES() → medidas (con TableID)
  • INFO.COLUMNS() → columnas
  • INFO.TABLES() → tablas
  • INFO.RELATIONSHIPS() → relaciones
  • INFO.PARTITIONS() → particiones del modelo
  • INFO.HIERARCHIES() → jerarquías
  • INFO.CALCULATIONGROUPS() → grupos de cálculo
  • INFO.CALCULATIONITEMS() → ítems de cálculo
  • INFO.ROLES() → roles de seguridad RLS
  • INFO.KPIS() → KPIs definidos en el modelo
  • INFO.FUNCTIONS() → todas las funciones DAX disponibles
💡 Consejo
Para el trabajo del día a día usa INFO.VIEW.* — son más simples y funcionan en cualquier contexto del modelo. Reserva INFO.* para consultas administrativas avanzadas en DAX Query View o DAX Studio.
🏆

Patrones de uso

Patrón 1 — Medida robusta con validación completa:

Métrica Robusta =
VAR Denominador = [Total Pedidos]
VAR Resultado = DIVIDE([Total Ventas], Denominador)
RETURN
SWITCH(
    TRUE(),
    ISBLANK([Total Ventas]), "—",
    NOT ISNUMBER(Resultado), "Error",
    ISFILTERED('Clientes'[País]),
        "🌍 " & SELECTEDVALUE('Clientes'[País], "Varios") & ": " &
        FORMAT(Resultado, "#,##0.00"),
    FORMAT(Resultado, "#,##0.00")
)

Patrón 2 — Título dinámico con contexto:

Título Completo =
VAR Año =
    IF(HASONEVALUE('Calendario'[Año]), SELECTEDVALUE('Calendario'[Año]), "Todos los años")
VAR País =
    IF(HASONEVALUE('Clientes'[País]), SELECTEDVALUE('Clientes'[País]), "Global")
VAR Nivel = SWITCH(
    TRUE(),
    ISINSCOPE('Productos'[SKU]), "Detalle de producto",
    ISINSCOPE('Productos'[Categoría]), "Por categoría",
    "Resumen global"
)
RETURN País & " | " & Año & " | " & Nivel

Patrón 3 — RLS dinámica completa:

// Tabla de Permisos: Email, Región, Categoría
// Cada usuario ve solo sus filas autorizadas
// Filtro de seguridad en la tabla Ventas:

CALCULATE(
    COUNTROWS('Ventas'),
    TREATAS(
        CALCULATETABLE(
            SELECTCOLUMNS('Permisos', "Reg", 'Permisos'[Región]),
            'Permisos'[Email] = USERPRINCIPALNAME()
        ),
        'Clientes'[Región]
    )
) > 0

Patrón 4 — Dashboard de calidad del modelo con INFO.VIEW:

// 5 medidas para un scorecard de documentación del modelo:
Total Tablas =
    COUNTROWS(INFO.VIEW.TABLES())

Total Medidas =
    COUNTROWS(INFO.VIEW.MEASURES())

Medidas con error =
    COUNTROWS(FILTER(INFO.VIEW.MEASURES(), [State] <> "Ready"))

Medidas sin documentar =
    COUNTROWS(FILTER(INFO.VIEW.MEASURES(), ISBLANK([Description])))

% Documentación completa =
    DIVIDE(
        COUNTROWS(FILTER(INFO.VIEW.MEASURES(), NOT ISBLANK([Description]))),
        COUNTROWS(INFO.VIEW.MEASURES())
    )
🚀 Siguiente paso
¡Las funciones de información ya son tuyas — ahora tus medidas son mucho más inteligentes y adaptativas! A continuación las Funciones Financieras — las más numerosas de DAX con sus 50 funciones para análisis de inversiones, préstamos y bonos.