De Power BI al correo, sin capacidad Premium
Cómo automatizar el envío diario de una tabla de Power BI por correo usando solo Pro y conectores estándar de Power Automate.
Un lunes cualquiera me llegó una petición que suena trivial:
«¿Puedes hacer que esta tabla del reporte llegue a las 10:30 pm al correo del equipo?»
Trivial no era. Tres días después tenía un flujo funcionando, y por el camino me encontré con catorce problemas distintos que nadie había documentado juntos. Este artículo es lo que me hubiera gustado leer el lunes por la mañana.
Resumen
- Si no tienes capacidad Premium o Fabric, la exportación de imagen del reporte no está disponible y las suscripciones nativas fallan en varios escenarios muy comunes.
- La salida es dejar de pensar en «mandar una imagen del visual» y empezar a consultar el modelo semántico directamente con DAX, reconstruyendo la tabla como HTML propio dentro de Power Automate.
- Con eso, los destinatarios dejan de necesitar licencia. Solo la necesita la cuenta que ejecuta la consulta.
- Hay dos patrones: A (tabla simple, 5 pasos) y B (formato condicional y varias secciones, más control y más mantenimiento).
- Al final tienes el catálogo de fallas con causa raíz y solución, para que diagnostiques en minutos lo que a mí me costó días.
Sección 01La restricción que lo condiciona todo
Antes de escribir una línea de DAX hay que ser honesto sobre con qué contamos realmente para resolver el problema. La restricción era esta:
La solución debe operar únicamente con Power BI Pro y Power Automate en su nivel estándar. Sin capacidad Premium, Embedded o Fabric. Sin conectores premium de Power Automate.
Esta frase no es un detalle administrativo. Es la que descarta los dos caminos obvios y obliga al diseño que verás más abajo. Si tú sí tienes capacidad de pago, no leas el resto: usa las suscripciones nativas y ahórrate el mantenimiento.
Sección 02Lo que probé primero, y por qué no funcionó
Vale la pena contarlo, porque probablemente vas a intentar lo mismo.
2.1 · Exportar la imagen del reporte a archivo
Descartado. La acción de exportación de reportes a archivo (imagen o PDF) exige que el reporte viva en un workspace respaldado por capacidad Premium, Embedded o Fabric. En capacidad compartida (Pro estándar) la acción simplemente no está disponible.
No es un problema de permisos ni de configuración: es de infraestructura. No hay workaround.
Y cuidado con una confusión que sale cara: Premium Per User tampoco sirve. Suena a Premium, pero es una licencia por usuario, no una capacidad, y la exportación a archivo no funciona con ella. Más de uno ha pagado PPU para resolver justo esto y se ha quedado igual.
2.2 · Suscripción nativa de Power BI
Descartado en la mayoría de entornos reales. Las suscripciones nativas pueden enviar una imagen de la página del reporte con Pro. Pero fallan cuando concurre alguna de estas tres condiciones, que son sorprendentemente frecuentes:
- La identidad corporativa no tiene buzón asociado. La cuenta existe en el directorio, pero no tiene Exchange. No hay a dónde enviar.
- El buzón real está fuera del tenant. El correo del equipo vive en un proveedor externo, y Pro no permite suscribir destinatarios externos.
- Hay destinatarios sin licencia. Suscribirlos exige capacidad de pago.
Y aunque ninguna aplique, queda un límite de diseño: el formato del correo es fijo. No puedes maquetar, no puedes poner tu propio encabezado, no puedes agrupar tres tablas en un mismo envío.
2.3 · La decisión de diseño
Aquí está el cambio mental que resuelve todo:
Deja de intentar enviar el visual. Consulta el modelo.
El visual es una representación. El dato vive en el modelo semántico, y hay una API pública para preguntarle cosas: la ejecución de consultas (executeQueries), que Power Automate expone como la acción Run a query against a dataset.
Consecuencia bonita: como el correo sale desde una cuenta con buzón real mediante un conector de correo estándar, los destinatarios no necesitan licencia de Power BI. Reciben un correo, no un reporte.
Sección 03Antes de empezar: entorno y precondiciones
El entorno exacto con el que validé esto
- Power BI Desktop
- 2.156.951.0 (Microsoft Store, actualizada el 21/07/2026)
- Power BI Service
- Licencia Pro, capacidad compartida
- Power Automate
- Nivel estándar, sin conectores premium
- Modelo semántico
- Modo Import, refresco programado
- Envío de correo
- Conector estándar desde una cuenta con buzón real
- Última verificación
- Agosto de 2026
Una precisión que importa: la versión de Desktop es donde modelé y de donde salió el DAX del Performance Analyzer. El flujo en sí corre contra el Service y contra Power Automate, que son servicios evergreen y no tienen número de versión. Si Microsoft cambia el comportamiento de una acción, no lo verás en este número: lo verás en tu flujo.
Y estas son las precondiciones. No pierdas una tarde para descubrirlas al final.
| Requisito | Detalle |
|---|---|
| Modo del modelo | Import. La documentación solo descarta de forma explícita los modelos alojados en Analysis Services, pero en la práctica DirectQuery, Direct Lake y las conexiones en vivo devuelven un «no encontrado» que despista muchísimo, porque el modelo evidentemente sí existe. |
| Configuración del tenant | Un administrador debe activar Semantic Model Execute Queries REST API (en tenants más antiguos aparece como Dataset Execute Queries REST API), dentro de Configuración de integración. No es el endpoint XMLA: ese es otro ajuste distinto, y activarlo no habilita esto. Merece la pena decírselo con ese nombre exacto a quien te lo tenga que abrir. |
| Licencia | Pro para la cuenta que ejecuta la consulta. Los destinatarios, ninguna. |
| Cuenta de envío | Con buzón real: Exchange con licencia, o un proveedor externo vía conector estándar. |
| Permisos | Lectura y compilación (Build) sobre el modelo semántico. Y una trampa fácil de sufrir: aunque tengas Build, si tu rol en el workspace es solo Visor, el modelo no llega a aparecer en el desplegable de Power Automate. Hace falta rol de colaborador para poder seleccionarlo. |
| Límites de la API | 100.000 filas o 1.000.000 de valores por consulta, lo que se alcance primero. Más 15 MB por respuesta y 120 consultas por minuto y usuario. |
| Ventana de refresco | El envío debe ocurrir después del último refresco programado del modelo. |
Sección 04Patrón A — Tabla simple, formato uniforme
Aplica cuando la tabla tiene una sola sección y un estilo uniforme: sin colores por celda o fila que dependan del dato.
Son cinco pasos. Vamos uno por uno.
Paso 1 · Recurrence
El disparador programado.
- Interval / Frequency: el que necesites (Day / 1).
- Time zone: tu zona horaria local. No lo dejes en UTC. Este campo evita la mitad de los problemas de «ayer/hoy» que verás en el catálogo de fallas.
- At these hours / minutes: la hora fija de envío.
Regla de oro: la hora de envío va después del último refresco programado del modelo, con margen. Si el refresco es a las 22:00 y suele tardar 20 minutos, no programes el envío a las 22:15.
Paso 2 · Run a query against a dataset
Aquí ocurre lo importante. La acción pide workspace, dataset y una consulta DAX. Este es el esquema que uso como base:
DEFINE
VAR _FiltroBase =
FILTER (
KEEPFILTERS ( VALUES ( 'Tabla'[Dimension] ) ),
NOT ( 'Tabla'[Dimension] IN { BLANK() } )
)
VAR _Core =
SUMMARIZECOLUMNS (
ROLLUPADDISSUBTOTAL ( 'Tabla'[Dimension], "EsTotal" ),
_FiltroBase,
"M1", [Medida1],
"M2", [Medida2]
)
VAR _Ventana =
TOPN ( 100000, _Core, [EsTotal], 1, [M1], 0 )
EVALUATE
_Ventana
ORDER BY
[EsTotal] ASC,
[M1] DESCTres convenciones que importan:
ROLLUPADDISSUBTOTALañade la fila de total y una bandera (EsTotal) que te dice si esa fila es el subtotal.- Ordenar la bandera en ascendente manda el total al final. Las filas de detalle traen
0, el total trae1.ASClo empuja abajo. Si lo ponesDESC, el total te aparece arriba (falla P6). - Un
TOPNholgado evita truncar filas. Ponlo cerca del límite de la API, no en1000«por si acaso». Eso sí, el techo real no se mide solo en filas; en la falla P8 explico por qué.
Un truco que ahorra tiempo: construye el visual en Power BI Desktop, abre el Performance Analyzer, copia la consulta DAX generada y úsala como punto de partida. Pero léela antes de pegarla, porque suele traer basura (ver falla P4).
Paso 3 · Parse JSON y Select
Van juntos porque son la misma idea en dos mitades: el Parse JSON le da estructura tipada al resultado y el Select decide qué se ve y cómo.
3a · Parse JSON
La acción devuelve las filas en firstTableRows. En la entrada del Parse JSON pon:
body('Run_a_query_against_a_dataset')?['firstTableRows']Y el esquema, con las propiedades anulables. Esto es crítico: si declaras "type": "string" a secas y llega un null, el flujo revienta.
{
"type": "array",
"items": {
"type": "object",
"properties": {
"Tabla[Dimension]": { "type": ["string", "null"] },
"[M1]": { "type": ["number", "null"] },
"[M2]": { "type": ["number", "null"] },
"[EsTotal]": { "type": ["integer", "null"] }
}
}
}Fíjate en la forma de los nombres: las columnas del modelo llegan como Tabla[Columna] y las medidas como [Medida], con los corchetes incluidos. Cópialos exactos desde una ejecución de prueba.
3b · Select
Esta acción hace dos trabajos: renombrar las columnas a los títulos que verá el destinatario, y formatear números y fechas.
| Clave (lo que se ve en el correo) | Valor |
|---|---|
| Segmento | item()?['Tabla[Dimension]'] |
| Ventas | formatNumber(item()?['[M1]'], 'N0', 'es-ES') |
| Cumplimiento | formatNumber(item()?['[M2]'], 'P2', 'es-ES') |
El formateo se hace aquí, no en el DAX. Así el DAX devuelve números limpios y el flujo decide la presentación. El sufijo del formato es el de .NET: N0 para miles sin decimales, P2 para porcentaje con dos.
Si vas a usar el Patrón B, este es el momento de arrastrar la columna de color. Se añade una fila más al Select, con un nombre que empiece por guion bajo para recordar que es auxiliar:
| Clave | Valor |
|---|---|
_color | item()?['[Color Fila]'] |
En el Patrón A esa fila sobra. En el Patrón B es la que hace todo el trabajo, y por eso se explica más abajo.
Paso 4 · Create HTML table + Compose
Create HTML table con From = salida del Select y Columns = Automatic. Te devuelve una tabla HTML sin ningún estilo, literalmente <table><tr><th>…
Para que no parezca un correo de 1998, un Compose que inyecta CSS reemplazando las etiquetas:
replace(
replace(
replace(
body('Create_HTML_table'),
'<table>',
'<table style="border-collapse:collapse;width:100%;font-family:Segoe UI,Arial,sans-serif;font-size:13px;">'
),
'<th>',
'<th style="background-color:#0E2233;color:#FFFFFF;padding:8px 10px;text-align:left;border:1px solid #D7DFE6;">'
),
'<td>',
'<td style="padding:7px 10px;border:1px solid #D7DFE6;color:#0E2233;">'
)Es feo, pero es la forma más corta de estilizar una tabla generada automáticamente.
Paso 5 · La fecha y el envío
Un Compose para la fecha, convertida a zona local antes de formatear:
formatDateTime( convertTimeZone(utcNow(), 'UTC', 'SA Pacific Standard Time'), 'dd/MM/yyyy' )
Sustituye el identificador de zona por el tuyo (E. South America Standard Time, Central Standard Time (Mexico), Romance Standard Time…). Y después, Send an email (V2), pegando el HTML en la vista de código del cuerpo (el botón </>), no en el editor visual.
Y esto es lo que recibe el equipo
Este es el resultado, con datos de ejemplo. Nadie en la lista de destinatarios tiene licencia de Power BI: para ellos esto es un correo más, y esa es exactamente la idea.
Cuatro cosas sobre HTML en correo que aprendí a golpes
- Outlook clásico renderiza con el motor de Word. Olvídate de flexbox, grid y
position: maqueta con tablas anidadas, como en 2005. El Outlook nuevo de Windows ya usa un motor de navegador y admite CSS actual, pero esto no se arregla solo: Microsoft mantiene el soporte del Outlook clásico hasta 2029 como mínimo, y las empresas grandes son justo las últimas de la fila en migrar. Vas a tener los dos motores en la misma bandeja durante años, así que escribe para el peor. - CSS inline siempre. Un bloque
<style>en el<head>se descarta en varios clientes. - Ancho en píxeles, no en porcentaje, si necesitas control real. Y no pases de unos 600 px de ancho útil.
- Prueba en móvil. Más de la mitad de tus destinatarios van a abrir ese correo desde el teléfono, fuera del horario de oficina.
Sección 05Patrón B — Formato condicional y múltiples secciones
Extiende el Patrón A cuando necesitas (a) resaltar filas o celdas según el dato, o (b) meter varias tablas en un mismo correo, una por segmento.
5.1 · Por qué el Patrón A no alcanza
Create HTML table aplica el mismo estilo a todas las celdas. No puede leer el valor de cada fila para decidir un color. No hay parámetro, no hay opción escondida: la acción genera la tabla completa de una vez y tú solo puedes hacer reemplazos globales sobre el resultado.
Para pintar por valor, hay que construir el HTML a mano, fila por fila.
5.2 · El truco: que el color venga del modelo
En vez de meter la lógica de color en el flujo, donde es horrible de mantener, la pongo como medida en el modelo:
Color Fila =
SWITCH (
TRUE (),
[Cumplimiento] >= 1, "#2F6B4F",
[Cumplimiento] >= 0.85, "#B4531A",
"#A03030"
)Ventajas: la regla vive junto al resto de la lógica de negocio, se prueba en Desktop y si cambian los umbrales no hay que tocar el flujo.
La medida entra en la consulta como una columna más y llega al Parse JSON como [Color Fila]. De ahí la recoge el Select en la clave _color que viste en el paso 3b, y es esa clave la que se lee en el bucle. Si te saltas ese paso, todas las filas te van a salir blancas y vas a revisar el bucle durante media hora sin encontrar nada.
5.3 · Construcción manual, paso a paso
Al inicio del flujo, un Initialize variable de tipo String por cada sección, arrancando con el encabezado:
concat(
'<table style="border-collapse:collapse;width:100%;font-family:Segoe UI,Arial,sans-serif;font-size:13px;">',
'<tr>',
'<th style="background-color:#0E2233;color:#FFFFFF;padding:8px 10px;text-align:left;">Segmento</th>',
'<th style="background-color:#0E2233;color:#FFFFFF;padding:8px 10px;text-align:right;">Ventas</th>',
'</tr>'
)Dentro de un Apply to each sobre la salida del Select, un Append to string variable:
concat(
'<tr style="background-color:',
if(equals(item()?['_color'], null), '#FFFFFF', item()?['_color']),
';color:',
if(equals(item()?['_color'], null), '#111111', '#FFFFFF'),
';">',
'<td style="padding:7px 10px;border:1px solid #D7DFE6;">',
coalesce(item()?['Segmento'], ''),
'</td>',
'<td style="padding:7px 10px;border:1px solid #D7DFE6;text-align:right;">',
coalesce(item()?['Ventas'], ''),
'</td>',
'</tr>'
)Fuera del bucle, un último Append con '</table>'.
Dos detalles que separan un flujo que funciona de uno que funciona siempre:
- La columna de color viaja en el Select como campo auxiliar (yo la llamo
_color) y se consume solo dentro del atributostyle. Nunca se emite como celda visible. - El control de concurrencia del
Apply to eachtiene que estar desactivado. Viene así de fábrica, pero se activa con un clic y es tentador cuando el bucle va lento. Si lo activas, varias iteraciones escriben sobre la misma variable a la vez y no solo se desordenan las filas: se pierden. Dos iteraciones leen el mismo valor y una pisa a la otra. Lo peor es que el flujo termina en verde, sin error, así que lo descubres cuando alguien te dice que en el correo faltan clientes.
El correo que sale de aquí
Mismo flujo de fondo, resultado muy distinto: dos tablas separadas en un solo envío y una fila en rojo que salta a la vista antes de leer un solo número.
5.4 · Optimización opcional: elimina el bucle
Si la tabla tiene cientos de filas, el Apply to each se vuelve lento: es una acción por fila. Hay una alternativa mucho más rápida.
Usa un Select en modo texto (el botón que cambia de mapa a expresión única) donde cada elemento ya sea el <tr> completo, y luego únelos:
join(body('Select_filas_HTML'), '')Un solo paso, sin bucle. La lógica del concat es idéntica; solo cambia dónde vive.
5.5 · Patrón A o Patrón B: cómo decidir
Y si prefieres decidirlo en veinte segundos:
Sección 06El catálogo de fallas
Esta es la parte que más me hubiera servido tener. Cada problema con su causa raíz y su solución, para que lo uses como guía de diagnóstico rápido.
La imagen exacta del reporte no es exportable con Pro
La exportación a archivo exige capacidad Premium o Fabric.
Abandonar la idea de «imagen» y consultar el modelo para reconstruir la tabla como HTML propio.
La suscripción nativa no entrega el correo
La identidad de Power BI no tiene buzón, y el buzón real es externo al tenant: destinatario externo, no permitido en Pro.
Enviar desde una cuenta con buzón real mediante conector de correo estándar. Los destinatarios dejan de necesitar licencia.
empty() falla sobre valores numéricos
Hablo de la opción incluir nulos de la propia acción de consulta, no del esquema del Parse JSON. Con esa opción desactivada, las celdas con dato llegan como enteros, y empty() solo acepta texto, arrays u objetos.
Sustituir empty(x) por equals(x, null) en las expresiones de formato.
La consulta traía dos EVALUATE
El DAX copiado del Performance Analyzer incluía un segundo EVALUATE destinado al formato condicional del visual.
La acción ejecuta un solo EVALUATE. Elimina el bloque auxiliar y conserva únicamente el que devuelve la tabla.
La fila de Total no cuadraba con las filas visibles
El filtro de limpieza (excluir filas vacías) se aplicaba después del rollup, así que el total seguía sumando filas ocultas.
Aplicar el filtro antes del rollup, como subconsulta de filtro por valor, para que el total refleje exactamente lo mostrado.
El Total aparecía arriba en lugar de abajo
La bandera de total se ordenaba en sentido descendente.
Ordenarla en ascendente, y ajustar el criterio equivalente en el TOPN, para enviarla al final.
Diferencias de cifras entre capturas
En reportes de «día en curso» el modelo se refresca durante el día, así que dos lecturas en momentos distintos difieren. Y ojo: refrescar el reporte no refresca el modelo.
Validar siempre contra el Service tras el mismo refresco, y alinear la hora de envío para que ocurra después del último refresco programado.
Truncamiento de filas al agregar una dimensión
Al cruzar por más dimensiones —añadir fecha, por ejemplo— el número de filas se multiplica y supera el límite del TOPN. Y hay un segundo techo que casi nadie menciona: la API no cuenta filas, cuenta celdas. Con 5 columnas caben 100.000 filas; con 20 columnas, solo 50.000.
Elevar el TOPN, y contar columnas además de filas. Si la tabla es ancha, tu techo real está muy por debajo de las 100.000 filas que aparecen en la documentación.
El formato condicional no se reflejaba en el correo
Create HTML table aplica estilo uniforme; no puede pintar por valor de fila.
Migrar al Patrón B, construyendo el HTML fila por fila y leyendo una medida de color incluida en la consulta.
Columnas vacías por nombres con caracteres especiales
Al referenciar columnas con item()?['Nombre'], los nombres con punto, símbolo de porcentaje u otros caracteres especiales no hacen match exacto entre el Select y el Append.
Nombrar las columnas internas sin caracteres especiales y garantizar coincidencia carácter a carácter entre Select y Append. Los títulos visibles del encabezado sí pueden llevar tildes: solo se muestran, no se referencian.
Fecha literal interpretada como expresión
Escribir una fecha entre llaves de expresión hace que el motor intente evaluarla como una operación aritmética.
Usar una fecha dinámica generada por un Compose, convertida a zona local, o texto plano sin llaves.
«Ayer / hoy» incorrecto por zona horaria
La hora del sistema está en UTC. De madrugada hora local, en UTC el día ya cambió.
Convertir a zona horaria local antes de calcular el día, con convertTimeZone.
Copia de flujo inactiva y bloques cruzados
Una copia de flujo nace apagada. Y al duplicar bloques es fácil que una etapa apunte a la fuente equivocada, o que las variables no se inicialicen al inicio.
Activar la copia, revisar conexiones, declarar todas las variables al inicio del flujo, y verificar que cada Parse JSON consuma la salida de su propia consulta.
La consulta corre bien en Desktop pero muere en el flujo
La acción tiene su propio tiempo máximo de ejecución, de alrededor de dos minutos, y no se amplía tocando la configuración del flujo. Una consulta que en Desktop tarda tres minutos aquí no llega a terminar nunca.
Aligerar la consulta: menos columnas, más agregación resuelta en el modelo, filtros más estrechos. Si aun así no baja de dos minutos, suele ser señal de que le estás pidiendo al correo algo que en realidad debería ser un reporte.
Sección 07Checklist de operación y mantenimiento
Imprímela y pégala al lado del flujo.
- La hora de envío queda después del refresco programado del modelo, con margen.
- Las cifras se validan contra el Service, no contra el entorno de desarrollo, y tras el mismo refresco.
- En Patrón B: los nombres de columna son idénticos entre Select y Append.
- En Patrón B: todas las variables se declaran al inicio del flujo.
- En Patrón B: cada tabla se cierra fuera del bucle.
- En Patrón B: el control de concurrencia del
Apply to eachestá desactivado. - Si cambian nombres de columnas en el modelo, se revisa el esquema del
Parse JSONy las referencias del Select/Append. - En copias de un flujo: activarlas, revisar conexiones y verificar que cada etapa consuma su propia fuente.
- Las fechas del cuerpo del correo son dinámicas y localizadas, nunca valores fijos.
- Hay una alerta o un
Configure run afterque avise si el flujo falla. Un correo que deja de llegar es más peligroso que uno con un error visible.
Sección 08Glosario
| Término | Qué significa |
|---|---|
Ejecución de consultas (executeQueries) | API que corre una consulta DAX contra un modelo publicado y devuelve datos. Es la base de la acción Run a query against a dataset. |
| Exportación a archivo | Genera imagen o PDF del reporte. Requiere capacidad de pago; no se usa aquí. |
| Conector estándar | Conector de Power Automate disponible sin licencia premium. |
| Rollup / subtotal | Fila de total agregada al resultado por la función de rollup. |
| Modelo Import | Datos cargados en el modelo; cambian solo al refrescar, no en tiempo real. |
| Dataset / modelo semántico | El mismo objeto. Microsoft renombró «dataset» a «modelo semántico», pero el nombre antiguo sigue vivo en muchos sitios: la acción de Power Automate todavía se llama Run a query against a dataset. Si ves los dos términos mezclados, no te estás perdiendo nada. |
| Formato condicional | Estilo, por ejemplo un color, que depende del valor de cada fila o celda. |
Sección 09Lo que me llevé de todo esto
Tres ideas que aplico ahora en cualquier automatización, no solo en esta.
La restricción define la arquitectura
No perdí tiempo buscando cómo saltarme el licenciamiento; lo acepté como dato de entrada y diseñé desde ahí. La solución elegante casi nunca es la que pelea contra el terreno.
El visual no es el dato
Cada vez que te pidan «mandar lo que se ve en el reporte», pregúntate si de verdad necesitas la imagen o solo los números. Casi siempre son los números, y los números tienen una API.
Un total que no cuadra cuesta más que un correo que no llega
Si el correo falla, alguien te escribe. Si el total está mal por 50 unidades durante tres meses, nadie te escribe y todos toman decisiones con datos rotos. Valida los totales primero.
Sección 10Fuentes oficiales
- Datasets - Execute Queries (API REST de Power BI) learn.microsoft.com/rest/api/power-bi/datasets/execute-queries
- La acción «Run a query against a dataset» en Power Automate powerbi.microsoft.com/blog/unlocking-new-self-service-bi-scenarios-with-executequeries-support-in-power-automate
- Exportar reportes de Power BI a archivo: requisitos de capacidad learn.microsoft.com/power-bi/developer/embedded/export-to
- Suscripciones por correo a reportes y paneles learn.microsoft.com/power-bi/collaborate-share/end-user-subscribe
- Configuración de integración del tenant (Dataset Execute Queries REST API) learn.microsoft.com/fabric/admin/service-admin-portal-integration
- Función ROLLUPADDISSUBTOTAL (DAX) learn.microsoft.com/dax/rollupaddissubtotal-function-dax
- Función SUMMARIZECOLUMNS (DAX) learn.microsoft.com/dax/summarizecolumns-function-dax
¿Te has topado con alguna de estas catorce? ¿O con una decimoquinta que debería estar en la lista? Cuéntamela en los comentarios y la incorporo al artículo con tu crédito.