Una función M que asigna los tipos de columna sola (y se documenta a sí misma)
Cualquiera que use Power Query a diario conoce el paso "Tipo cambiado". Es el que Excel añade solo al final de una consulta, y también el que te revienta la consulta el día que la fuente cambia de columnas: Table.TransformColumnTypes lleva los nombres escritos a fuego, así que si una columna desaparece o se renombra, el paso falla.
Rafa compartió esta semana una función en lenguaje M que resuelve el problema de raíz, y de paso enseña algo que casi nadie usa: cómo documentar tus propias funciones para que aparezcan con ayuda dentro del editor.
La función
``
Fx_CambioTipo = (Tabla_Par as table) as table =>
let
Nom_Col = Table.ColumnNames(Tabla_Par),
Tipos_Col = List.Transform(Record.FieldValues(Tabla_Par{0}), each Value.Type(_)),
Lista_Tipos = List.Zip({Nom_Col, Tipos_Col}),
Tabla_TipoCambio = Table.TransformColumnTypes(Tabla_Par, Lista_Tipos)
in
Tabla_TipoCambio
`
Son cuatro líneas y cada una hace una cosa concreta:
- Table.ColumnNames saca los nombres de columna reales de la tabla que le pases, sean los que sean.
- Tabla_Par{0} coge la primera fila como registro, y Record.FieldValues la convierte en lista de valores. Sobre esa lista, Value.Type deduce el tipo de cada valor: un número sale como número, una fecha como fecha, un texto como texto.
- List.Zip empareja ambas listas, que es justo el formato de pares nombre y tipo que espera el siguiente paso.
- Table.TransformColumnTypes aplica esa lista.
El resultado es un paso de cambio de tipos que no depende de que las columnas se llamen de una manera concreta. Cambia la fuente, y la función se adapta.
La parte que casi nadie conoce: documentarla
Aquí está lo verdaderamente interesante. Rafa no se queda en la función: le añade metadatos de documentación para que, al invocarla desde el editor de Power Query, muestre nombre, descripción y hasta un ejemplo, igual que las funciones nativas.
`
DocMeta = [
Documentation.Name = "Fx_CambioTipo",
Documentation.Description = "Cambia los tipos de Datos de una Tabla pasada como Argumento",
Documentation.LongDescription = "Cambia los tipos de Datos de una Tabla pasada como Argumento con base en la inferencia de los valores de la primera fila de esta",
Documentation.Examples = {[
Description = "Ejemplo cambio de tipo",
Code = "Fx_CambioTipo(...)",
Result = "Tabla con los Tipos de Datos de cada columna configurados"
]}
]
`
Y la asignación, que es el paso donde mucha gente se atasca:
`
TipoBase = Value.Type(Fx_CambioTipo),
TipoConMetaData = Value.ReplaceMetadata(TipoBase, DocMeta),
Result = Value.ReplaceType(Fx_CambioTipo, TipoConMetaData)
`
El detalle que hay que entender es que los metadatos no se le ponen a la función, se le ponen a su tipo. Por eso el recorrido es: se extrae el tipo de la función con Value.Type, se le adjunta la documentación con Value.ReplaceMetadata, y solo entonces se le dice a la función que ahora es de ese tipo documentado con Value.ReplaceType`. Intentar aplicar los metadatos directamente sobre la función no funciona.
Cuándo usarla y cuándo no
La inferencia se hace sobre la primera fila, así que hereda su limitación: si esa fila trae un valor atípico (un código numérico que en el resto de filas es texto, o un hueco), el tipo deducido será el equivocado para toda la columna. Va de maravilla para fuentes homogéneas y para prototipar rápido; en fuentes sucias conviene revisar el resultado.
---
Más allá de la utilidad concreta, el ejemplo enseña una idea que cambia la forma de trabajar en Power Query: las funciones M no son solo un atajo para no repetir pasos, son piezas reutilizables que puedes documentar y compartir con tu equipo como si fueran nativas. Se adjunta el fichero con la función completa.
El paso que Power Query añade solo y que acaba rompiéndote la consulta
Si trabajas con Power Query, has visto mil veces el paso "Tipo cambiado". Aparece automáticamente al final de casi cualquier consulta y parece inofensivo. Lo es, hasta el día en que la fuente de datos cambia.
El motivo es simple: ese paso genera una instrucción con los nombres de columna escritos literalmente. Si mañana el sistema de origen renombra una columna, la elimina o añade otra, la consulta deja de funcionar y hay que entrar a rehacer el paso a mano. En un modelo con quince consultas, eso es una tarde perdida cada vez que alguien toca el origen.
Un miembro de la comunidad compartió esta semana una función en lenguaje M que ataca el problema de raíz. Y de paso enseña algo que muy poca gente usa: cómo documentar tus propias funciones para que se comporten como las nativas dentro del editor.
Cómo funciona la asignación automática de tipos
La función recibe una tabla y devuelve la misma tabla con los tipos ya puestos. Todo el trabajo ocurre en cuatro instrucciones encadenadas.
Primero, Table.ColumnNames extrae los nombres de columna reales de la tabla que se le pase, sean los que sean. Aquí no hay nada escrito a fuego: la función se adapta a lo que le llega.
Después toma la primera fila de la tabla como registro y la convierte en una lista de valores con Record.FieldValues. Sobre esa lista aplica Value.Type a cada elemento, que es la función que deduce el tipo de un valor concreto: un número devuelve tipo número, una fecha devuelve tipo fecha, una cadena devuelve tipo texto.
En este punto hay dos listas paralelas: una con los nombres de columna y otra con los tipos deducidos. List.Zip las empareja, y el resultado es exactamente el formato de pares que espera el paso final.
Por último, Table.TransformColumnTypes aplica esa lista de pares. La diferencia con el paso automático de Power Query es que aquí la lista se ha calculado en tiempo de ejecución a partir de la tabla real, no se ha escrito previamente. Cambia la fuente y la función sigue funcionando.
La parte que casi nadie usa: documentar la función
Lo que eleva este ejemplo por encima de un truco práctico es la segunda mitad. El autor no se conforma con que la función funcione: le añade metadatos para que, al invocarla desde el editor de Power Query, muestre su nombre, una descripción corta, una descripción larga y hasta un ejemplo de uso con su resultado. Igual que hacen las funciones nativas de M.
Los metadatos se definen como un registro con campos reconocidos por el motor: Documentation.Name, Documentation.Description, Documentation.LongDescription y Documentation.Examples. Este último admite una lista de ejemplos, cada uno con su descripción, su código y el resultado esperado.
Pero hay un detalle que hace tropezar a mucha gente la primera vez, y conviene entenderlo bien: los metadatos no se aplican a la función, se aplican a su tipo. Intentar adjuntarlos directamente sobre la función no produce ningún efecto.
El recorrido correcto tiene tres pasos. Se extrae el tipo de la función con Value.Type. Se le adjunta el registro de documentación a ese tipo con Value.ReplaceMetadata. Y solo entonces se le dice a la función que a partir de ahora es de ese tipo documentado, usando Value.ReplaceType. El resultado de esa última instrucción es la función que se publica.
Una vez hecho, la función aparece en el editor con su ficha de ayuda, y cualquier compañero que la reciba sabe qué hace y cómo llamarla sin tener que leer el código.
Cuándo conviene usarla
La inferencia se hace sobre la primera fila, y eso marca su terreno de juego. Si esa fila trae un valor atípico, por ejemplo un código que ahí parece numérico pero que en el resto de filas es texto, o un hueco donde debería haber una fecha, el tipo deducido será el equivocado para toda la columna.
Va muy bien para fuentes homogéneas, para prototipar rápido y para consultas intermedias donde el tipado exacto no es crítico. En fuentes sucias o con columnas mixtas conviene revisar el resultado, o combinarla con un paso posterior que corrija los casos concretos.
Conceptos clave
Table.ColumnNames: devuelve la lista de nombres de columna de una tabla. La pieza que evita depender de nombres literales.Value.Type: deduce el tipo de un valor. Aplicado conList.Transformsobre la primera fila, da el tipado de toda la tabla.List.Zip: empareja varias listas en pares, el formato que espera la transformación de tipos.Value.ReplaceMetadatayValue.ReplaceType: la pareja que permite documentar una función M. La primera adjunta los metadatos al tipo, la segunda reasigna ese tipo a la función.
Conclusión
Hay una idea de fondo que va más allá de esta función concreta: en Power Query, las funciones M no son solo un atajo para no repetir pasos. Son piezas reutilizables que puedes documentar, versionar y compartir con tu equipo como si formaran parte del lenguaje. La mayoría de la gente que usa Power Query nunca llega a escribir una función propia, y quien lo hace rara vez la documenta. Este ejemplo cubre las dos cosas en veinte líneas.
Más casos con estas funciones
Más contenido de Excel en InflueXcel
- Optimización de Power Query para consultas masivas a API REST CasoInteresante caso de optimización en Power Query. Randolfo, desde Guatemala, necesitaba consultar el estado de más de 100 envíos de paqueterí
- Extraer datos de archivos XML complejos: Power Query, VBA y Power Automate CasoSergio plantea un problema real con datos abiertos del gobierno español: archivos XML de licitaciones públicas con más de 30 niveles de anid
- Readmisión de pacientes en 48h: Power Query, LAMBDA/MAP y AGRUPARPOR CasoAndrés Rojas plantea un reto real de datos clínicos: a partir de una tabla con más de un millón de registros de urgencias (IdPaciente, Fecha
- Power Query: rutas dinámicas para compartir ficheros sin romper conexiones CasoUn miembro de la comunidad plantea un problema muy frecuente: tiene una consulta de Power Query con una ruta de red fija (\\servidor\shared-
- Mejora un 90% el rendimiento de Power Query con SQLite TutorialPower Query es una herramienta potente para consolidar, combinar y calcular datos, pero cuando trabajamos con millones de registros y calcul
- Separar artículos concatenados en filas: 4 enfoques (fórmulas, Power Query y Python) CasoCaso interesante con cuatro enfoques muy distintos para resolver un mismo problema: una tabla tiene una columna de artículos concatenados co
- Consolidar múltiples archivos Excel con Power Query desde carpeta CasoUn miembro necesitaba consolidar datos de múltiples archivos Excel almacenados en una carpeta. El reto adicional: cada archivo contenía vari
- ¿Columnas con nombres distintos en Power Query? Tutorial¿Columnas con nombres distintos en Power Query? Aquí tienes la solución definitiva para normalizar tus datos y evitar errores al combinar fi
- Domina REGEX en Excel: Tutorial Completo desde Cero TutorialTutorial Completo sobre REGEX en Excel
- Encontrar palabras comunes entre dos textos con fórmulas CasoReto de LinkedIn que un miembro trae al grupo: dadas dos columnas con frases, encontrar las palabras que aparecen en ambas. La comunidad des