jueves, enero 08, 2015

Contar registros únicos en rangos grandes

En la nota anterior sobre registros únicos vimos cómo encarar el recuento usando tablas dinámicas. Esta vez Eduardo, el de la nota anterior, apareció en mi oficina y sin mucha ceremonia se sentó del otro lado del escritorio mirándome con el ceño fruncido.

- ¿Te acordás del asunto de contar registros únicos con tablas dinámicas?
- Si, seguro. Publiqué una nota en el blog.
- La leí, pero tengo otro problema.
- Si...
- Tengo una tabla con ventas a clientes. Cada cliente aparece muchas veces. Quiero poner en una celda cuántos clientes hay la lista, es decir, sin repeticiones.
- Ah! podés leer mi nota sobre contar valores únicos en Excel.
- La leí y apliqué la fórmula, pero lo lleva mucho tiempo calcular.
- ¿Cuántos registros hay en tu tabla?
- Más o menos, cuatrocientos mil.
- ¿¡¡Cua-tro-cientos-mil!!?, respondí pronunciando cada una de las sílabas por separado para enfatizar.
- Si, y cada mes agrego más.

Lo que Eduardo descubrió es que CONTAR.SI no es la más veloz de las funciones de Excel. Aplicar CONTAR.SI a un rango de 400 mil celdas es una de las mejores maneras de explicar el concepto de eternidad.

Como Eduardo insiste en no usar Filtro Avanzado o Quitar Duplicados y, además, está prohibido mencionar Access en su presencia, tuve que buscar alguna otra solución.

La fórmulas que intentaba usar Eduardo son:

=SUMA(1/CONTAR.SI(miRango,miRango)) en forma matricial
=SUMAPRODUCTO((miRango<>"")/CONTAR.SI(miRango,miRango))

Como puede observarse, ambas fórmulas utilizan la función CONTAR.SI, por lo que la solución que le propuse fue esta UDF (función definida por el usuario)


Function contar_unicos(rngSeleccion As Range)

    Dim collUnicos As New Collection
    Dim rngCell As Range


    On Error Resume Next
    For Each rngCell In rngSeleccion
        collUnicos.Add rngCell, CStr(rngCell)
    Next rngCell
    On Error GoTo 0

    contar_unicos = collUnicos.Count

End Function


Usando una macro que Charles Williams de Decisions Models tuvo la gentileza de colgar en el sitio de artículos técnicos del Office Dev Center, medí el tiempo de cálculo de las distintas fórmulas.

Para investigar el tiempo de cálculo de las distintas opciones usé un ejemplo con un rango de 20 mil celdas conteniendo números aleatorios. El examen del tiempo de cálculo de las fórmulas lo hice usando rangos de 5 mil, 10 mil y 20 mil registros


El valor en la celda G2 permite controlar el tamaño del rango; la celda G3 contiene la fórmula a examinar y la celda G4 recibe el valor del tiempo de cálculo hecho con la macro (apretando el botón "Tiempo de cálculo").

En mi máquina (Dell Latitude E5540 con procesador Intel Core i5-4300, 8 GB RAM, Excel 2010 64-bit), estos fueron los resultados en segundos:



Podemos ver que la UDF Contar_Unicos es mucho más rápida que las que usan CONTAR.SI. Además, la diferencia crece con la cantidad de celdas a procesar. Con 5 mil celdas, Contar_Unicos es casi 33 veces más rápida que las otras; con 10 mil celdas la diferencia llega a 78 veces y con 20 mil celdas 160 veces.

Otro detalle interesante es que el tiempo de cálculo de las fórmulas no es proporcional a la cantidad de registros. Al aumentar la cantidad de registros en un 100% (de 5000 a 10000), el tiempo de cálculo de las fórmulas con CONTAR.SI crece en un 300%; un aumento del 300% en los registros (de 5000 a 20000 celdas) resulta en un aumento del 1500% en el tiempo de cálculo.

El tiempo de cálculo de la UDF con 400 mil registros fue 3 segundos.


martes, diciembre 23, 2014

Como contar registros únicos en tablas dinámicas

Eduardo, colega de trabajo, es inteligente, aplicado y no le gusta depender del departamento de informática. Por eso, maneja una serie de pequeñas bases de datos en Excel (para el horror del departamento de IT ya mencionado). Para generar sus reportes usa principalmente tablas dinámicas de las cuales, para ponerlo de alguna manera, está perdídamente enamorado. A tal punto que todos mis intentos de mostrarle las bondades de otras herramientas como, por poner un ejemplo, Filtro Avanzado, siempre fracasan en forma rotunda.
Por eso cuando Eduardo entró ayer en mi oficina, sólo por la mirada, me di cuenta que algo le estaba pasando. No era una visita de cortesía.

- ¿Cómo hago para saber cuántos clientes tengo en mi base de datos?
 - Dado que todo lo hacés con tablas dinámicas, te sugiero que arrastres el campo de clientes al área de los datos usando la función Contar para totalizar.
- Si, es lo que hice; pero cada cliente aparece en más de una fila en la base de datos y entonces me cuenta la cantidad de veces que cada cliente aparece, no la cantidad de clientes.
- Por supuesto, así funcionan las tablas dinámicas.
- Pero, ¿cómo, no hay una función para contar registros únicos?
- Si y no...
- Uf, ya empezaste. ¿Si o no?
- En Excel 2013 hay una función para contar registros únicos en un reporte dinámico; en Excel 2010 y anteriores, no.
- ¡Ah! Yo uso Excel 2010, ¿cómo hago?
- Creando un campo auxiliar en la base de datos.

Supongamos que nuestra base de datos es la tabla de facturas de la base de datos Northwind

Para contar cuántos clientes hay en la base de datos creamos una tabla dinámica arrastrando los campos País y Cliente al área de las filas y nuevamente el campo Cliente al área de datos usando la función Contar (dado que el campo Cliente no contiene valores numéricos, Excel usará esta función en forma automática)

Inmediatamente podemos ver que en Argentina hay 3 clientes, pero la tabla dinámica muestra 11.
En las versiones de Excel anteriores a Excel 2013, tenemos que usar una columna auxiliar.
Insertamos la columna Auxiliar entre los campos Cliente y Dirección; en esta columan ponemos la fórmula =CONTAR.SI($B$3:B3,B3) que copiamos a todas las filas


El campo Auxiliar muestra el número de orden de aparación de cada cliente. Ahora podemos usar este campo como filtro de la tabla dinámica para que muestre sólo los registro donde el valor de Auxiliar es 1

Ahora podemos ver que la cuenta es correcta


Con Excel 2013, las cosas son más sencillas. No necesitamos crear ningún campo auxiliar. Sencillamente creamos la tabla dinámicas a partir de la base de datos. En el asistente de tablas dinámicas nos aseguramos de marcar la opción "Agregar estos datos al Modelo de datos" (esta opción sólo existe en Excel 2013)

Una vez creada la tabla, arrastramos el campo País al área de filas y el campo Cliente al área de los datos; seleccionamos el área de datos y abrimos el menú de configuración del campo. En la casilla de elección del tipo de cálculo tenemos una nueva función: "Recuento distinto"


Elegimos esta función y apretamos aceptar


Podemos ver que el encabezamiento del campo ha cambiado de "Recuento de cliente" a "Recuento distinto de Cliente" y que efectivamente tenemos 84 clientes en la base de datos.

Personalmente pienso que la traducción tendría que haber sido "Recuento único".


martes, diciembre 16, 2014

Otra forma de crear Hipervínculos en Excel

Los hipervinculos son una excelente herramienta para crear vínculos a celdas u objetos en hojas o cuadernos y también a archivos y páginas Web. Pero también tienen sus bemoles y una visita a los foros de Excel en la red revela que uno de los problemas es que cada tanto los hipervínculos desaparecen o dejan de apuntar adonde deberían.

Pero en esta nota no vamos a hablar de la desaparición de los hipervínculos, sino mostrar otra forma de crearlos, casi instantánea.

Hace unos años atrás mostré una técnica que implica el uso de macros. Hoy vamos a mostrar otra técnica que usa el "drag and drop". Esta técnica es muy útil cuando no tenemos una gran cantidad de hojas.

Uno de los usos más prácticos de los hipervínculos en Excel es crear un índice del contenido del cuaderno. Supongamos que tenemos un cuadernos con datos de cuatro sucursales de un empresa y queremos crear una hoja con hipervínculos que apunten a cada una de las hojas.



En la hoja "indice" queremos crear los hipervínculos a cada una de las hoja de las sucursales.

Seleccionamos la hoja Norte, por ejemplo, y en ella la celda B3 que contiene el texto "Sucursal Norte"


Ahora arrastramos la celda usando el botón derecho del mouse y apretando simultáneamente la tecla Alt. Arrastramos la celda hasta apuntar a la pestaña de la hoja "indice", lo que la activará.
Una vez en la hoja "indice", dejamos de apretar la tecla Alt y posicionamos el mouse en la celda indicada. Al soltar el botón del mouse aparecerá en menú contextual donde elgimos la opción "Crear hipervínculo aquí"


Excel crea automáticamente el hipervínculo, ahorrándonos la molestia de tener que definir el texto.

Esta técnica funciona solamente en cuadernos que han sido previamente guardados.

Este video demuestra la técnica