En la entrada pasada, revisamos los elementos básicos para entender las fórmulas M de Power Query. Hoy vamos a dar un paso adelante y veremos las partes mas relacionadas a la programación que ofrece este lenguaje.
Si no viste la entrada pasada, te la dejo por aquí.
Expresiones
Las expresiones son todo aquello que puede ser evaluado a un valor, lo que también aplica a los valores mismos. Por ejemplo, la expresión «1» es evaluada al valor «1», aunque por lo regular uno piensa en las expresiones como compuestos de funciones u operaciones más complejas.
Siendo así en casos como «1 +1 » evalúa a 2; o «10 > 5» evalúa a true; o la expresión «Excel» y «Cute» se evalúa a «Excel Cute»; también tenemos la expresión Text.Upper(«Excel Cute») evaluando a «EXCEL CUTE».
La lista completa de operadores la puedes consultar aquí
Operadores
Junto con la librería estándar, el código M también cuenta con una lista de funciones especiales llamadas operadores. Estas toman exactamente dos valores (o expresiones que evalúan a un valor) y los regresa como un solo valor.
Aritmética
El código M viene con las funciones básicas de una calculadora con las que también cuenta nuestro Excel básico (+, -, *, /), por medio de las cuales podemos añadir, sustraer, multiplicar o dividir valores respectivamente. También pueden usarse con otros varios tipos de valores más allá de números. Por ejemplo, se le puede añadir una duración a una fecha:
«#date(2020,04,28) + #duration(3, 0, 0, 0)» será evaluado a 2020-05-01.
Comparación
Es posible comparar valores en código M usando los símbolos de comparación correspondientes para menor que, mayor que, igual o menor que, igual o mayor que, igual y no es igual (<, >, <=, >=, =, <>; respectivamente). Estos nos sirven para ser usados con diversos tipos de valores. Por ejemplo, para comparar dos listas con el operador igual.
De tener «{1,2,3,4} = {1,2,3}» se nos evaluaría como false puesto que ambas listas no son iguales.
Concatenación y Fusión
Se puede concatenar un texto así como se pueden fusionar listas, registros y tablas usando el símbolo «&». Por ejemplo, «Excel» & «Cute» será evaluado como «Excel Cute».
Logica
Se pueden hacer operaciones en valores booleanos o expresiones que sean evaluadas a valores booleanos por medio de los operadores «not», «and» y «or».
Let Statement
Por medio de este se le permite a un conjunto de valores ser evaluado y asignados a nombres de variables para luego ser usados en una expresión subsecuente que siga el statement «in».
let a = 1, b = 2, c = a + b in c
Esta expresión está hecha de tres expresiones que son evaluadas luego del statement «let». Cada expresión es separada por una coma, excepto por la última antes del statement «in». En este ejemplo, las expresiones enteras «let» e «in» serán evaluadas a 3:
let c = a + b, b = 2, a = 1 in c
Podría pensarse que las expresiones dentro de un statement «let» necesitarían aparecer en el orden que necesitan para ser evaluadas, lo cual no es así. El código de arriba es perfectamente válido y también evaluará a 3. El evaluador en el código M se encarga de calcular de manera automática el orden de cálculos necesarios basado en depedencias de expresión.
Si bien sería más fácil leer código M si está escrito en orden de evaluación, hay otra ventaja. Las expresiones aparecerán como pasos separados en la ventana de Pasos Aplicados. Al escribirse sin orden, estas expresiones van a aparecer como un solo paso combinado:
let a = 1, b = 2 in a + b
También se pueden evaluar expresiones dentro de la parte «in» de una expresión «let… in…»
Nombres de variables
let
#"¿Esta es una variable?" = 1 + 1
in
#"¿Esta es una variable?"
Siguiendo el ejemplo de arriba, se puede asignar un nombre a las expresiones usando los carácteres #»». Es posible incluso usar espacios y otros carácteres especiales. Las únicas excepiones serían las palabras clave reservadas.
Los nombres de variables será lo que aparezca en los pasos aplicados del editor de consultas, por lo cual poder usar espacios como carácteres es una gran ventaja.
Each Statements
Cada expresión «each» es una taquigrafía para declarar funciones tomando un solo parámetro «_» (guión bajo):
let Source = #table({"Números"}, {{1}, {2}, {3}, {4}, {5}}), #"Added Custom" = Table.AddColumn(Source, "Double", each 2*[Números]) in #"Added Custom"
En este ejemplo estamos creando una nueva columna que multiplique la columna Numeros por dos en cada fila.
let Source = #table({"Números"}, {{1}, {2}, {3}, {4}, {5}}), #"Added Custom" = Table.AddColumn(Source, "Double", () => 2*[Números]) in #"Added Custom"
Y así podemos crear la misma consulta usando el síntaxis con guión bajo, lo cual es semánticamente equivalente al statement «each». Usar cualquiera de las dos consultas arrojará el mismo resultado.
Statements If Else Then
El código M es bastante escaso comparado a otros lenguajes de programación en el área de expresiones lógicas, dado que no cuenta con statements de select case o loop. Lo único con lo que cuenta son expresiones «if… then… else»:
if [expresión lógica a probar]
then [hacer esto si arroja true]
else [hacer esto si arroja false]
La síntaxis es bastante directa y funciona igual que en muchos otros lenguajes de programación. Puede aparecer todo en una línea o separado en varias para facilitar su lectura.
Statements Try Otherwise
Los errores son algo que pueden suceder cuando se intentan hacer operaciones que requieren tipos particulares de datos. Por ejemplo, intentar multiplicar un número con un valor de texto resultará en un error:
let Source = #table({"Número", "Número y Texto"}, {{2, 2}, {2, "Excel"}}), #"Added Custom" = Table.AddColumn(Source, "Producto", each try [Número]*[Número y Texto] otherwise 0) in #"Added Custom"
Estos errores pueden evitarse por medio de una expresión «try… otherwise…»
Esto evitará los errores en los resultados de consultas y te permitirá reemplazar estos errores con cualquier valor o expresión.
Funciones
Una función es un mapeo de un conjunto de valores de parámetros a un valor. Junto con las funciones en la líbrería estándar, el código M también nos permite crear nuestras propias funciones:
let Product = (x,y) => x * y, Result = Product(2,3) in Result
Esta consulta define una función que multiplica dos números, después la consulta llama y evalúa la función con los valores 2 y 3, que son evaluados a 6.
Funciones con parámetros opcionales
Existen dos tipos de funciones parametrales: un parámetro obligatorio y un parámetro opcional. El parámetro requerido debe ser siempre específicado cuando una función es utilizada. Los parámetros opcionales no necesitan ser específicados cuando se usa una función. Si el parámetro opcional no es encontrado, entonces el valor que se pasa a la función será «null»:
let Product = (x, optional y) => if y is null then x else x * y, Result = Product(2) in Result
Esta función tiene un segundo argumento opcional. Luego, la consulta llama y evalúa la función usando solo el parámetro requerido con un valor de 2, lo cual se evalúa a 2. Es importante notar que la función necesita tomar en cuanta que y equivale a null, de otro modo un argumento opcional faltante puede resultar en una función que evalúe a un error.
Funciones recursivas
También es posible escribir una función que se refiera a sí misma por medio del operadir de alcance, que se corresponde con el símbolo «@»:
let Fibonacci = (n) => if n = 1 then 1 else if n = 2 then 1 else @Fibonacci(n-1) + @Fibonacci(n-2), Result = Fibonacci(7) in Result
La secuencia Fibonacci es un ejemplo de una función que es definida de manera recursiva. El número de texto en la secuencia es definido como la suma de los dos números previos, por lo que para llegar al enésimo número, se necesita saber el (n-1)mo y (n-2)mo número.
Esta función encontrará el enésimo número Fibonacci añadiendo los (n-1)mo y (n-2)mo números Fibonacci.
Funciones Query
Los ejemplos de arriba definen una función dentro de una consulta que luego es llamada y evalúa la función dentro de la consulta. Es posible crear una consulta que sea una función (una función query) y que pueda ser llamada y evaluada desde otras consultas:
let FunctionResult = (Argumento1, Argumento2,…) => let /Código M que evalúa en la función va aquí/ in Result in FunctionResult
Este es el formato general necesario para crear una función query. Nótese que también se va a necesitar un statement «let…in…» dentro del statement «let…in…» de la función query para poder desarrollar múltiples pasos.
Comentario de código
Como podría esperarse de cualquier lenguaje de programación, es posible añadir comentarios a tu código para futuras consultas a la hora de editar o hacer cambios. Hay dos tipos de comentario posibles dentro del código M: los de una sola línea y los de múltiples líneas.
Los de una sola línea pueden ser creados si se le precede por dos líneas diágonales «//». Todo lo que se encuentre antes de estos dos carácteres será interpretado como código M, y lo mismo pasará con todo lo que haya después de las mismas.
Código M va aquí
Código M va aquí //Esta es una línea de comentario
Código M va aquí
Y sobre los comentarios en líneas múltiples, estos pueden ser creados si se pone el comentario entre los carácteres «/» y «/». Todo lo que esté fuera de estos será interpretado como código M, y todo lo que esté entre ellos será interpretado como comentario.
Conclusiones
Power Query es una gran función dentro de Excel que nos puede ayudar a automatizar y simplificar la importación de datos y transformación de los mismos. Se puede hacer mucho usando solo el punto grafical y dando click a la interfaz sin siquiera tocar el código M, pero conforme los requerimientos sean más avanzados, puede que llegue un momento donde sea necesario usar el editor de código M o incluso crearlo desde cero.
Cualquier lenguaje de programación es imposible de leer si no se conocen las bases primero. El propósito de esta guía es introducir las bases por medio de las cuales funciona el código M para que puedas empezar a crear consultas más avanzadas.
Cualquier duda nos leemos abajo.