Conexiones en PowerQuery: El {M}ago Rafa y Nacho Cardenal

Conexiones en PowerQuery: El {M}ago Rafa y Nacho Cardenal

Sesión magistral con Rafael González y su dominio extremo del código M y powerquery

Power Query no solo lee datos: también puede enviarlos

En esta sesión, Nacho Cardenal y Rafa Barreda (Microsoft MVP) recorren las conexiones de Power Query con un caso completo y muy poco habitual: coger la exportación de un chat de WhatsApp, limpiarla hasta dejarla usable, y enviarla a la API de ChatGPT desde la propia consulta para obtener un resumen diario de lo que se habló.

El tema lo eligió la comunidad por votación, y la idea de fondo es la que da sentido a todo: solemos entender Power Query como una secuencia que va del origen al destino, cuando en realidad una conexión también es un sitio al que enviar información y del que recibir una respuesta.

El origen: exportar un chat de WhatsApp

El fichero de partida sale del propio WhatsApp: dentro de cualquier chat, en el menú de los tres puntos, Más > Exportar chat, eligiendo la opción sin archivos para que salga solo el texto. WhatsApp genera un fichero de texto que puedes enviarte por correo y abrir donde quieras.

El problema es que ese texto no viene en una estructura cómoda. Cada mensaje empieza por fecha y hora, pero cuando alguien escribe varios mensajes seguidos, los siguientes no repiten la cabecera: quedan sueltos, sin fecha, e incluso generan líneas en blanco.

Truco 1: renunciar al delimitador automático

Al conectar el fichero, Power Query detecta la coma como delimitador y reparte el texto en nueve columnas. Es exactamente lo que no interesa, porque muchos mensajes contienen comas y el reparto sale distinto en cada fila.

La solución de Rafa es elegir delimitador de ancho fijo con valor cero. Con eso, todo el contenido cae en una sola columna y se puede trabajar con criterio propio en vez de con el que propone el asistente.

Truco 2: limpiar los mensajes de sistema

Un chat exportado viene lleno de ruido: "creaste el grupo", "cambiaste el icono del grupo", "solicitó unirse"… Se quitan con un filtro de texto no contiene, y aquí está el detalle práctico: el modo básico solo admite dos cláusulas, pero pulsando uso avanzado puedes encadenar todas las que necesites.

Cuanto antes se eliminan filas y columnas, más ligero va todo lo que viene después. Es una regla general de Power Query que en este caso se nota mucho.

Truco 3: usar el error como detector

Este es el corazón del ejercicio. Para saber qué filas empiezan un mensaje nuevo, se divide la columna por la primera coma (delimitador situado más a la izquierda) y se intenta convertir ese trozo en fecha con Date.From.

Las filas que son cabecera de mensaje devuelven una fecha. Las que son continuación devuelven error. Y ese error es justo la señal que se buscaba.

Para convertirlo en algo manejable se envuelve con try ... otherwise null:

try Date.From([Columna1.1]) otherwise null

Así, las continuaciones quedan como null, que es un valor con el que sí se puede trabajar (con un error, el rellenado hacia abajo no funciona).

Rafa remarca la diferencia entre try y una condicional: try es la herramienta específica para errores, mientras que una condicional normal comprueba valores. Y avisa de por qué conviene tratarlos: los errores de fila te dejan seguir transformando, pero al cargar aparecen como filas vacías.

Truco 4: numerar, agrupar y volver a unir

Con los nulos identificados, el resto encaja solo:

  1. Columna de índice desde 1, para tener un código por fila.
  2. Columna condicional: si la comprobación de fecha es nula, devuelve nulo; si no, devuelve el índice.
  3. Rellenar hacia abajo: todas las continuaciones heredan el código del mensaje que las inició.
  4. Agrupar por ese código, con la opción todas las filas, que deja una mini tabla por grupo.

El último paso es el más elegante. En lugar de expandir la columna (un paso que pesa bastante), se edita el código y se usa la proyección: poniendo entre corchetes el nombre de una columna sobre la tabla del grupo, se obtiene directamente una lista. Y a esa lista se le aplica Text.Combine con un separador:

Text.Combine(_[Todo], " ")

El resultado: cada cadena de mensajes queda unida en un solo bloque. Después se repite la operación agrupando por fecha, esta vez con la barra vertical como separador, para tener todos los mensajes de cada día en una única celda.

Truco 5: llamar a la API de ChatGPT desde Power Query

Con los mensajes agrupados por día, Nacho monta una función M que simula la llamada a la API de OpenAI. La estructura es la de cualquier API: una petición con su formato y sus cabeceras, y una respuesta en JSON.

La función necesita tres cosas:

  • La URL del endpoint de la API.
  • La clave de API propia, que va en la cabecera de autorización.
  • El cuerpo de la petición: el modelo elegido y el mensaje, donde el contenido es el parámetro que recibe la función.

La respuesta llega como un JSON con estructura de árbol; hay que navegar por el nodo choices, quedarse con el primer elemento y bajar hasta el mensaje.

Una vez existe la función, se usa como cualquier otra: se añade una columna personalizada que la invoca pasándole una instrucción fija más los mensajes del día. El resultado es una columna con el resumen de cada jornada.

Dos apuntes prácticos de la sesión: el coste por consulta de texto es mínimo (del orden de céntimos), y el uso de la API está sujeto a condiciones de confidencialidad distintas a las de la web.

Conclusión

Lo que hace especial este caso no es ninguna función suelta, sino el encadenado: un formato de texto imposible se vuelve tabla gracias a aprovechar un error como detector de patrón, y esa tabla se enriquece con una llamada externa que Power Query, por sí solo, no sabría resolver.

Es un buen recordatorio de que las conexiones de Power Query no son solo la puerta de entrada de los datos. También son la puerta de salida.

Más contenido de Excel en InflueXcel