Hasta hace relativamente poco tiempo abrir archivos comprimidos no era posible de manera directa con Power BI, ya que este no cuenta con un conector nativo para abrir este tipo de formatos.
Por otra parte, con el lenguaje M tampoco era posible, pero con el ingenio de muchos se logra finalmente poder hacerlo mediante una función.
He de decir que no existe una única manera de crear esta función, y algunas son más eficientes que otras.
Este post se basa en una función publicada en un artículo en el blog de Mark White (http://sql10.blogspot.com/).
Muestro paso a paso cómo podéis usarla para lograr obtener los datos del .Zip.
1- Crear la función M.
La misma se puede pegar en cualquier informe Power BI / Power Query. Lo que realiza es tomar el contenido de un archivo ZIP y devuelve una lista de archivos que contiene, junto con sus datos descomprimidos.
Para crear la función basta con abrir el Editor avanzado y pegarla, ver Fig.1
Fig.1
Nota: Código a copiar íntegramente.
(ZIPFile) =>
let
Header = BinaryFormat.Record([
MiscHeader = BinaryFormat.Binary(14),
BinarySize = BinaryFormat.ByteOrder(BinaryFormat.UnsignedInteger32, ByteOrder.LittleEndian),
FileSize = BinaryFormat.ByteOrder(BinaryFormat.UnsignedInteger32, ByteOrder.LittleEndian),
FileNameLen= BinaryFormat.ByteOrder(BinaryFormat.UnsignedInteger16, ByteOrder.LittleEndian),
ExtrasLen = BinaryFormat.ByteOrder(BinaryFormat.UnsignedInteger16, ByteOrder.LittleEndian)
]),
HeaderChoice = BinaryFormat.Choice(
BinaryFormat.ByteOrder(BinaryFormat.UnsignedInteger32, ByteOrder.LittleEndian),
each if _ <> 67324752 // not the IsValid number? then return a dummy formatter
then BinaryFormat.Record([IsValid = false, Filename=null, Content=null])
else BinaryFormat.Choice(
BinaryFormat.Binary(26), // Header payload - 14+4+4+2+2
each BinaryFormat.Record([
IsValid = true,
Filename = BinaryFormat.Text(Header(_)[FileNameLen]),
Extras = BinaryFormat.Text(Header(_)[ExtrasLen]),
Content = BinaryFormat.Transform(
BinaryFormat.Binary(Header(_)[BinarySize]),
(x) => try Binary.Buffer(Binary.Decompress(x, Compression.Deflate)) otherwise null
)
]),
type binary // enable streaming
)
),
ZipFormat = BinaryFormat.List(HeaderChoice, each _[IsValid] = true),
Entries = List.Transform(
List.RemoveLastN( ZipFormat(ZIPFile), 1),
(e) => [FileName = e[Filename], Content = e[Content] ]
)
in
Table.FromRecords(Entries)
Una vez creada se podrá visualizar y reutilizar. ver Fig.2
Fig.2
2- Una vez se tenga la función, usamos el conector de 'Carpeta', y buscamos la localización donde tenemos el archivo .Zip, ver Fig.3 y Fig.4
Fig.3
Fig.4
3- Al seleccionar la carpeta se muestran los datos que se encuentran en la ubicación, y seleccionamos transformar, ver Fig.5
Fig.5
4- Al estar en la ventana del editor de consultas elegimos solo la extensión .Zip que es la que nos interesa, ver Fig.6
Fig.6
5- Ahora pasaremos a invocar la función M antes creada.
Iremos a la opción añadir columna y luego invocar función personalizada.
Se escribe el nombre de la Columna deseado, luego se selecciona la función, y por último se escoge el contenido. Ver Fig.7
Fig.7
6- Nos quedamos con la nueva columna y removemos todas las demás. Ver Fig.8
Fig.8
7- Ahora pasamos a extraer la información. Expandimos las opciones de la columna y seleccionamos en contenido. Desmarcamos la opción de usar el nombre original de la columna como prefijo. Ver Fig.9
Fig.9
8- En este punto, debería ver una tabla que enumera cada archivo contenido en el archivo zip que seleccionó, junto con un blob binario del contenido del archivo. Para muchos tipos de archivos, como CSV y Excel, simplemente puede hacer clic en el campo Binario. Ver Fig.10
Fig.10
9- Y finalmente PowerQuery creará de manera inteligente todos los pasos necesarios para exponer el contenido del archivo. Ver Fig.11
Fig.11
10- Ahora basta con guardar los cambios y aplicar, y obtendremos un modelo listo para trabajar. Ver Fig.12
Fig.12
Nota:
Creo necesario decir que, aunque esta es una manera válida para extraer y obtener los datos, resulta en realidad tediosa por la cantidad de pasos a realizar y por la necesidad de crear una función en lenguaje M que no es trivial. Por tal motivo aconsejo realizarlo con el lenguaje Python ya que resulta realmente sencillo y basta con apenas dos líneas de código.
En otro artículo detallo cómo se puede realizar.
Si te ha servido no dudes en compartirlo y regálanos un "Me gusta", es la razón de ser de este blog. Puedes subscribirte y así no te perderás los posts que vayamos publicando.
¡Gracias y Buena suerte! ;)
Queria saber si tambien puede abrir archivos zip no validos. ya que lo he probado y no me funciono
Excelente artículo, muchas gracias Marilin, por el aporte !!
No sabía que se podía hacer con M, gracias extensibles a Mark White, creador de la función.👍👏
Estoy deseando ver la opción Python🤔
Como se suele decir, "me lo llevo" 🙂