miércoles, marzo 15, 2017

Nuevo catálogo de imágenes con Excel

Han pasado casi siete años desde que publiqué el último post sobre el tema de catálogos de imágenes con Excel. Este tema se encuentra entre los más leídos por mis lectores (aunque debo señalar que no recomiendo crear este tipo de aplicaciones con Excel).

En el post mencionado uso Vba (macros) para incrustar las imágenes guardadas en una carpeta en la hoja. La técnica consiste en guardar las direcciones de las imágenes en una tabla de Excel. En otra hoja el usuario introduce un texto que hace referencia a la dirección de la imagen y de esta manera, con el código, introducimos la imagen en la hoja de Excel. Esto tiene muchas ventajas pero presenta la dificultad de tener que actualizar la lista de referencia-dirección de la imagen.

Usando Power Query podemos crear una consulta que mantenga actualizada la lista de direcciones, en lugar de tener que usar todo tipo de códigos complicados.
Supongamos que queremos construir un modelo donde al ingresar el usuario el nombre de un país en la celda contigua aparece la bandera del país elegido. En nuestro ejemplo tenemos todos los archivos de las imágenes de las banderas en la carpeta “Banderas”


El proceso lo muestro en este video



Una vez creada la conexión, solo tenemos que apretar el botón Actualizar para mantener la tabla de referencias actualizada


El próximo paso es crear el nombre definido "rngPaisDireccion" que se refiere a la tabla completa, sin los encabezados



En otra hoja creamos esta tabla, con los encabezados y una fila vacía


Creamos un nombre definido que se refiere a todas las celdas de la columna Pais ("PicList"), que luego usaremos en el código


Como ven, ya hemos agregado dos botones para activar las macros. Una para insertar las banderas correspondientes a los nombres de los países que ingresemos en la columna A y otro para remover los países que ingresamos y las imágenes de sus banderas.

El código para insertar las banderas es

 Sub insert_pic()  
   Dim strFileName As String  
   Dim iTop As Integer  
   Dim rngCellPic As Range  
   'comprobar que se introdujeron paises  
   If WorksheetFunction.CountA(Range("PicList")) < 1 Then  
     MsgBox "No se anotaron paises", vbCritical  
     Exit Sub  
   End If  
   Application.ScreenUpdating = False  
   For Each rngCellPic In Range("PicList")  
   'defiinir alto de fila a 60 y centrar  
   With rngCellPic  
     .RowHeight = 60  
     .VerticalAlignment = xlCenter  
   End With  
   'introducir la bandera  
   strFileName = WorksheetFunction.VLookup(rngCellPic, Range("rngPaisDireccion"), 2, 0)  
   ActiveSheet.Shapes.AddPicture Filename:=strFileName, _  
       linktofile:=msoFalse, _  
       savewithdocument:=msoCTrue, _  
       Left:=rngCellPic.Offset(0, 1).Left + 15, _  
       Top:=rngCellPic.Offset(0, 1).Top + 5, _  
       Width:=50, Height:=50  
   Next rngCellPic  
   Application.ScreenUpdating = True  
 End Sub  

El código para limpiar todas las filas de la tabla es el siguiente


 Sub clean_all()  
   Dim rngCell As Range  
   Dim shpImage As Shape  
   Application.ScreenUpdating = False  
   'delete pictures  
   For Each shpImage In shList.Shapes  
     If shpImage.AlternativeText <> "NoDelete" Then shpImage.Delete  
   Next shpImage  
   For Each rngCell In Range("PicLIst")  
     rngCell.RowHeight = 14.25  
   Next rngCell  
   On Error Resume Next  
   Range("PicList").EntireRow.Delete  
   On Error GoTo 0  
   Application.ScreenUpdating = True  
 End Sub  

El modelo en funcionamiento


jueves, marzo 02, 2017

Generar reportes con Power Query

Power Query, o Datos-Obtener y Transformar para los usuarios de Excel 2016, es más que una herramienta para obtener, transformar y cargar datos. También podemos usarlo como herramienta para generar informes. La clave reside en la herramienta “Agrupar por” del editor de Power Query.

Veamos un ejemplo, basado en la base de datos Northwind (como de costumbre). Nos piden un informe que el promedio de cada operación de venta del año 2015, por agente. Nuestra base de datos contiene las ventas por cliente, agente, orden de venta y fecha.

Creamos una consulta en el editor de Power Query que, después de hacer las operaciones "de limpieza" necesarias, se ve así



Creamos el reporte con los siguientes pasos:

Empezamos por abrir el menú “Agrupar por”


En el formulario que se abre definimos


  • en "Agrupar por" elegimos la columna "Agente";
  • en "Nuevo nombre de columna" cambiamos el nombre de la  casilla (al abrir el formulario sólo se ve una casilla) a "Operaciones" y en la casilla "Operación" elegimos "Contar filas distintas" (traducción poco exitosa, en mi opinión, de Distinct Count);
  • usamos el símbolo + (a la derecha de "Columna") para agregar otro campo y en el nombre ponemos "Ventas", en la operación "Suma" y elegimos la columna Ventas para la operación.
De esta manera creamos una tabla con tres columnas: Agente, Operaciones y Ventas


Ahora podemos crear una columna calculada para el promedio de venta por agente



Este video muestra el proyecto




Todo los que no queda por hacer ahora es cargar la consulta a una hoja de Excel, dar un buen formato a los números y..listo.




jueves, febrero 23, 2017

Listas Desplegables con valores únicos con Power Query

En el pasado remoto de este blog publiqué dos posts sobre cómo crear una lista desplegable con valores únicos a partir de una tabla de datos. El escenario habitual es una tabla de datos, supongamos de ventas, a partir de la cual queremos crear una validación de datos de los nombres de los clientes.
El procedimiento habitual sería crear un nombre definido que se refiera a la columna que contiene los nombres de los clientes. El problema es que los nombres se repiten y lo queremos es una liksta de valores únicos.

El primer post, del año 2006, presentaba una solución compleja con fórmulas. Hasta tal punto compleja que publiqué un post adicional para explicar el funcionamiento de esta fórmulas.

El segundo post, del año 2011, presentaba una solución tal vez más elegante pero también compleja, incluyendo el uso de Vba (macros).

Usando Power Query  podemos construir una solución más sencilla y ésto es lo que mostraré en este post.

El escenario:

  • una hoja que contiene una tabla con datos de ventas;

  • una hoja donde queremos queremos construir una reporte sencillo: una celda que contiene el nombre del cliente, que se elige de una validación de datos y un celda donde calculamos las ventas del cliente com SUMAR.SI, basándonos en el nombre del cliente seleccionado.

donde la celda C3 contiene la fórmula 

=SUMAR.SI(tbl_Sales2016[Cliente],B3,tbl_Sales2016[Monto])

Primer paso: crear una consulta en el Power Query para generar una lista de valores únicos ordenados alfabéticamente.



Segundo paso: crear un nombre definido que se refiera al rango de los nombres de los clientes y crear la lista desplegable con validación de datos.




La gran ventaja de este modelo sobre las soluciones anteriores es que una vez construida la consulta sólo tendremos que procuparnos de actualizar la consulta cada vez que agreguemos o quitemos filas en la tabla de datos (clientes nuevos o clientes que dejan de estar en a lista).
La desventaja es que tenemos que actualizar la consulta! Es decir, tendremos que confiar que el usuario no se olvide de hacerlo.
Podemos evitar este inconveniente creando un evento de manera que cada vez que el usuario sale de la hoja "bd" la consulta se actualice. En el módulo del editor de Vb de la hoja "bd" creamos este evento Worksheet_Deactivate



 De esta manera nos aseguramos que la lista deplegable se actualizará con cada cambio en la tabla de datos.