Gestión proactiva de errores en Power Query: el patrón de la tabla de control
En cualquier proyecto serio de Business Intelligence, el error no es una posibilidad, es una certeza. Los orígenes de datos, especialmente cuando dependen de entradas manuales en Excel o exportaciones de ERPs antiguos, suelen presentar columnas con tipos de datos inconsistentes, fechas imposibles o valores nulos en campos obligatorios. El problema no es que el dato venga mal; el problema es que tu proceso de carga se detenga o, peor aún, que el informe muestre resultados incorrectos sin que nadie se dé cuenta.
Como consultor, he visto demasiados modelos de Power BI que fallan en producción porque alguien escribió una letra en una columna de ‘Importe’. La solución habitual de ‘Quitar errores’ es peligrosa: estás borrando información sin dejar rastro. Si borras una fila de una venta de 10.000 € porque el campo ‘Unidades’ tenía un error, tu contabilidad no cuadrará y habrás perdido la trazabilidad. Necesitamos un patrón que capture el error, lo aísle y permita al usuario de negocio corregirlo sin detener el motor de BI.
Este artículo detalla cómo implementar una arquitectura de validación en Power Query usando el operador try...otherwise y consultas de referencia para generar una tabla de control de errores. Este enfoque es fundamental para mantener la confianza en el dato y evitar el mantenimiento reactivo constante.
Por qué fallan las validaciones estándar
Power Query tiene funciones nativas para gestionar errores, como ‘Quitar filas con errores’ o ‘Reemplazar errores’. Sin embargo, estas opciones son insuficientes para entornos profesionales por tres razones principales:
- Invisibilidad: Si quitas los errores, el informe se actualiza correctamente, pero los totales son falsos. El desarrollador no recibe alertas y el usuario final toma decisiones con datos incompletos.
- Falta de contexto: No sabes qué fila falló ni por qué. ¿Fue un error de conversión de texto a número? ¿Un nulo en una clave primaria? Sin esta información, la limpieza del origen es una adivinanza.
- Impacto en el rendimiento: Aplicar pasos de limpieza genéricos en tablas de millones de filas sin una estrategia de query folding puede degradar el rendimiento. Es mejor validar de forma quirúrgica.
Antes de aplicar cualquier técnica, es vital entender la Optimización de Modelos Semánticos en Power BI, ya que la forma en que estructuramos los datos en la carga impacta directamente en cómo el motor VertiPaq los comprime y almacena.
El operador try…otherwise: la base técnica
En el lenguaje M, el operador try es el equivalente al try-catch de otros lenguajes de programación. Cuando aplicas try a una expresión, Power Query devuelve un registro (Record) que contiene dos campos: HasError (booleano) y Value (el resultado si no hay error) o Error (un registro con los detalles del fallo si lo hay).
Si usamos try...otherwise, simplificamos el resultado devolviendo un valor alternativo en caso de fallo. Aunque es útil para evitar que la consulta se detenga, para una tabla de control preferimos el try completo para capturar el mensaje de error técnico.
// Ejemplo básico de captura de error en una columna de Importe
let
Origen = Excel.CurrentWorkbook(){[Name="Ventas"]}[Content],
// Intentamos convertir a número y capturamos el resultado
Validacion = Table.AddColumn(Origen, "Control_Importe", each try Number.From([Importe]))
in
ValidacionCon este código, la columna ‘Control_Importe’ no contiene números, sino registros. Si el valor original era «100», el registro dirá [HasError=false, Value=100]. Si era «ABC», dirá [HasError=true, Error=[...]]. Esta es la semilla para nuestra tabla de auditoría.
Patrón de diseño: Consultas de Datos vs. Consultas de Error
Para implementar esto correctamente sin ensuciar el modelo de datos final, seguimos un patrón de tres niveles. Este método se apoya en el uso inteligente de las tablas de referencia en Power Query.
1. La consulta Staging (Base)
Cargamos el origen de datos (por ejemplo, la tabla ‘Ventas_Brutas’) y realizamos las transformaciones mínimas obligatorias. Esta consulta debe tener la carga deshabilitada (clic derecho > Deshabilitar carga). No aplicamos tipado estricto todavía, para evitar que el motor lance errores antes de tiempo.
2. La consulta Producción (Limpia)
Creamos una referencia a la consulta Base. Aquí filtramos todas las filas que sabemos que están mal. Por ejemplo, eliminamos filas donde el ‘ID_Pedido’ es nulo o donde la ‘Fecha’ es inválida. Esta es la tabla que cargamos al modelo de datos para que los usuarios consuman.
3. La consulta de Control (Errores)
Creamos otra referencia a la consulta Base. Aquí filtramos solo las filas que tienen errores o valores nulos prohibidos. Añadimos una columna que explique el motivo del rechazo. Esta tabla se carga también al modelo (o a un informe técnico aparte) para que el equipo de IT o el responsable del Excel de origen sepa exactamente qué corregir.
| Escenario | Acción en Tabla Producción | Acción en Tabla Control | Riesgo de Negocio |
|---|---|---|---|
| Nulo en Importe | Fila eliminada | Registrada como «Importe Ausente» | Alto (Venta no contabilizada) |
| Texto en Fecha | Fila eliminada | Registrada como «Formato Fecha Incorrecto» | Medio (Error de atribución temporal) |
| Cliente no existe | Fila mantenida (con ID Genérico) | Registrada como «Maestro Incompleto» | Bajo (Análisis de ‘Otros’) |
Implementación avanzada con M
Para automatizar la creación de la tabla de control, podemos crear una función personalizada que recorra varias columnas críticas. Sin embargo, para la mayoría de proyectos, basta con un paso de agregación de errores. Aquí tienes un ejemplo de cómo generar la tabla de auditoría capturando el motivo del error técnico:
let
Origen = Ventas_Base, // Referencia a la tabla staging
// Añadimos validación por columna
CheckErrores = Table.AddColumn(Origen, "Log_Error", each
let
checkFecha = try Date.From([Fecha]),
checkImporte = try Number.From([Importe])
in
if checkFecha[HasError] then "Error Fecha: " & checkFecha[Error][Message]
else if checkImporte[HasError] then "Error Importe: " & checkImporte[Error][Message]
else if [ID_Cliente] = null then "Cliente Nulo"
else null
),
// Filtramos solo las filas que tienen algún mensaje en el log
SoloErrores = Table.SelectRows(CheckErrores, each ([Log_Error] <> null)),
// Mantenemos columnas clave para identificar el origen del problema
Final = Table.SelectColumns(SoloErrores, {"ID_Pedido", "Fecha", "ID_Cliente", "Importe", "Log_Error"})
in
FinalEste código es extremadamente útil porque no solo detecta que hay un error, sino que captura el mensaje nativo que devuelve Power Query (como «No podemos convertir el valor ‘NaN’ a tipo Number»). Al cargar esta tabla en una página oculta de tu informe, puedes crear una alerta que avise si la tabla de control tiene más de 0 filas.
Trade-offs y decisiones de arquitectura
Implementar este sistema de control tiene un coste. Nada es gratis en la arquitectura de datos. El principal inconveniente es que estamos duplicando el procesamiento del origen (una vez para la tabla limpia y otra para la de errores). Si el origen de datos es una base de datos SQL lenta y no hay query folding, el tiempo de actualización podría duplicarse.
Para mitigar esto, asegúrate de que la consulta de Staging (la base) haga el trabajo pesado de filtrado y transformación inicial, y que las consultas derivadas (Limpia y Control) solo realicen el filtrado final. Si trabajas con volúmenes masivos, considera mover esta lógica a una capa de transformación previa, como un Dataflow en Power BI Service o un Notebook en Microsoft Fabric.
Es importante diferenciar entre un error de datos y un error conceptual. Para estos últimos, es preferible usar DAX. Por ejemplo, entender la diferencia entre columnas calculadas y medidas en DAX te ayudará a decidir si una validación de rango (ej. ¿el precio es negativo?) debe hacerse en la carga o en la visualización.
Lista de errores frecuentes a capturar
- Errores de tipo: Intentar convertir texto a número o fecha. Es la causa número uno de fallos de actualización.
- Valores nulos en claves: Un nulo en una columna que luego se usará para una relación romperá la integridad del modelo. Para entender el impacto, revisa cómo afectan las relaciones y la ambigüedad en Power BI.
- Truncamiento de datos: Cadenas de texto que exceden el límite esperado o que contienen caracteres especiales no soportados por el destino.
- Falta de integridad referencial: IDs de productos o clientes que no existen en las tablas maestras (aunque esto se suele gestionar mejor con un ‘Left Anti Join’).
Preguntas frecuentes
¿Por qué no usar simplemente ‘Quitar errores’?
Porque ‘Quitar errores’ es destructivo y silencioso. Si una actualización de datos elimina 500 filas por errores de formato, el informe terminará con éxito, pero tus KPIs estarán mal calculados. La tabla de control hace que el error sea visible y gestionable.
¿Este método afecta mucho al rendimiento del informe?
En modelos pequeños y medianos, el impacto es despreciable. En modelos de gran volumen (Big Data), duplicar la consulta puede ser costoso. En esos casos, es mejor realizar la validación en la capa de Bronze/Silver de un Data Lake o mediante vistas en SQL antes de que Power Query intervenga.
¿Cómo aviso al usuario de que hay errores en la tabla de control?
La forma más profesional es crear una medida DAX que cuente las filas de la tabla ‘Errores’. Puedes colocar una tarjeta en la cabecera del dashboard que solo se muestre (mediante formato condicional) si el conteo es mayor a cero, alertando al usuario de que los datos mostrados están incompletos.
Checklist de implementación
- He deshabilitado la carga de la consulta de Staging.
- La tabla de Producción filtra nulos en columnas de relación (FKs).
- La tabla de Control utiliza
trypara capturar el mensaje de error técnico. - He verificado que la tabla de Control incluye una columna de ‘Origen’ o ‘ID’ para localizar el dato erróneo.
- He añadido una validación visual en el informe para monitorizar el tamaño de la tabla de control.


