Solución de problemas e introducción a la creación de funciones en Power Query
Siempre digo que soy un #dataflow_lover. Todos mis proyectos intento desarrollarlos mediante flujo de datos aunque en ocasiones las cosas se ponen complicadas debido a algunos errores que pueden aparecer. En las últimas semanas, la integración de carpetas con sharepoint está dando algún quebradero de cabeza. Vamos a analizar uno concreto, la integración de archivos con una misma estructura desde una carpeta de sharepoint.
Para empezar, en cuanto creamos un dataflow y elegimos Carpeta de Sharepoint como Origen de datos nos encontramos con el primer error. La secuencia es la siguiente:
Esto es muy sencillo de resolver. El conector del Dataflow no está escribiendo correctamente la sentencia y basta con añadir al código lo siguiente:
SharePoint.Files("https://quolutions.sharepoint.com/sites/quolutions", [ApiVersion = 15])
Vamos a escoger sólo dos archivos de la carpeta para el ejemplo:
Le damos a las flechitas para combinar y nos devuelve un error
Esto no pasa en el desktop que va a mostrar el cuadro de diálogo de combinación de archivos y va a crear las funciones necesarias después de aceptar:
¿Cómo podemos resolver esto en Dataflow? No he encontrado documentación por ningún sitio. Incluso hay un hilo en la comunidad sin resolver: https://community.powerbi.com/t5/Service/quot-Unexpected-error-quot-when-reading-sharepoint-folder-full/td-p/841277
Como yo lo resuelvo es simplemente creando yo la función de combinación. De hecho incluso en el desktop, no me gusta la forma en que Power Query realiza la automatización de la función y suelo crear yo mi propia función. El procedimiento es sencillo.
1º Escojo sólo un archivo con el que trabajar las transformaciones, hago doble click sobre binary en uno de ellos y me devuelve la información del csv en este caso. Valdría igual con excel o cualquier otro origen.
El código que me genera es el siguiente:
let
Origen = SharePoint.Files("https://quolutions.sharepoint.com/sites/quolutions", [ApiVersion = 15]),
Navegación = Origen{[Name = "LOG_20200513.csv", #"Folder Path" = "https://quolutions.sharepoint.com/sites/quolutions/Documentos compartidos/General/Argomaniz/DATOS_VISION/"]}[Content],
#"CSV importado" = Csv.Document(Navegación, [Delimiter = ";", Columns = 17, QuoteStyle = QuoteStyle.None]),
#"Encabezados promovidos" = Table.PromoteHeaders(#"CSV importado", [PromoteAllScalars = true]),
#"Tipo de columna cambiado" = Table.TransformColumnTypes(#"Encabezados promovidos", {{"FECHA", Int64.Type}, {"HORA", type text}, {"LADO", type text}, {"A1", Int64.Type}, {"A2", Int64.Type}, {"R1_A", Int64.Type}, {"R1_B", Int64.Type}, {"R2", Int64.Type}, {"R3", Int64.Type}, {"R4", Int64.Type}, {"R5", Int64.Type}, {"R6", Int64.Type}, {"B1", Int64.Type}, {"B2", Int64.Type}, {"B3", Int64.Type}, {"B4", Int64.Type}, {"RESULTADO", type text}})
in
#"Tipo de columna cambiado"
Ahora lo que quiero es simplemente crear una función que tenga como parámetro el nombre del archivo. Para crear la función, tengo que envolver todo el código anterior en un let …. in en el que creo el parámetro y sustituir en el código anterior el nombre del archivo por el parámetro. El código de la función quedaría así:
let
archivos = (nombrearchivo as text) => //este es el parámetro creado
let
Origen = SharePoint.Files("https://quolutions.sharepoint.com/sites/quolutions", [ApiVersion = 15]),
Navegación = Origen{[Name = nombrearchivo, #"Folder Path" = "https://quolutions.sharepoint.com/sites/quolutions/Documentos compartidos/General/Argomaniz/DATOS_VISION/"]}[Content], //aquí cambiamos el nombre del archivo por el parámetro
#"CSV importado" = Csv.Document(Navegación, [Delimiter = ";", Columns = 17, QuoteStyle = QuoteStyle.None]),
#"Encabezados promovidos" = Table.PromoteHeaders(#"CSV importado", [PromoteAllScalars = true]),
#"Tipo de columna cambiado" = Table.TransformColumnTypes(#"Encabezados promovidos", {{"FECHA", Int64.Type}, {"HORA", type text}, {"LADO", type text}, {"A1", Int64.Type}, {"A2", Int64.Type}, {"R1_A", Int64.Type}, {"R1_B", Int64.Type}, {"R2", Int64.Type}, {"R3", Int64.Type}, {"R4", Int64.Type}, {"R5", Int64.Type}, {"R6", Int64.Type}, {"B1", Int64.Type}, {"B2", Int64.Type}, {"B3", Int64.Type}, {"B4", Int64.Type}, {"RESULTADO", type text}})
in
#"Tipo de columna cambiado"
in
archivos
No os lo había advertido pero lo mejor es crear la función sobre una copia de la consulta antes de hacer las transformaciones de la tabla porque ahora sobre ese archivo original es sobre el que invocaremos la función.
Vamos a quedarnos para este ejemplo con 3 logs unicamente
Nos quedamos sólo con la columna name e invocamos la función que previamente habíamos creado.
Pero a poco que conozcamos un poco como funciona M, la invocación de una función no es más que agregar una columna personalizada y eso si podemos hacerlo en los dataflow y en la fórmula pondremos:
Nombrefunción([ColumnaParametro])
Le damos a aceptar y ya nos trae cada una de las tablas con todas las transformaciones que hayamos hecho. En el ejemplo no he hecho ninguna transformación pero podríamos hacer las que quisiéramos. Sólo tenemos que expandir la tabla y listo.
Espero que sea de utilidad y que estas pequeñas piedras en el camino no os aparten de la senda de los Dataflow
Deja una respuesta