sábado, marzo 29, 2014

Uso de Tablas en Excel - referencias estructuradas

El tema del uso de Tablas (Listas en Excel 2003) no es nuevo en este blog (un clic en la etiqueta Tablas/Listas en la nube de etiquetas les mostrará todas las notas). En mi opinión es una de las mejores innovaciones en Excel en los últimos años. Sin embargo no creo equivocarme si digo que relativamente pocos usuarios sacan provecho de esta herramienta.
Un posible motivo para esta reticencia sea la nueva sintaxis empleada para referenciar las celdas y rangos dentro de la tabla. Al principio esta sintaxis parece un tanto críptica para el usuario habituado a las referencias clásicas "columna/fila" (por ejemplo, A1).

Consideremos esta tabla de ventas por sucursal y zona

informe dinamico sencillo


En la celda G4 usamos esta fórmula para extraer de la tabla las ventas de cierta zona

=SUMAR.SI($C$3:$C$12,G3,$D$3:$D$12)

Ahora convirtamos esta tabla en  una Tabla (cuando uso tabla con minúscula me refiero a un rango normal de datos) y veamos cómo aparecen las referencias en la fórmula

Tabla de datos

La fórmula aparece ahora así

=SUMAR.SI(TablaVentas[Zona],G3,TablaVentas[Ventas])

La sintaxis es evidente:

"TablaVentas" se refiere al nombre de la tabla

Nombre de la tabla

[Zona] es la referencia al campo (columna) que define la zona de cada sucursal; de la misma manera [Ventas] se refiere a la columna de las ventas.

Para referirnos a otros elementos de la tabla, como la fila de los encabezamientos, usamos distintas formas que resumo en esta tabla

Objeto Sintaxis
Referencia a la tabla =TablaVentas
La celda de la fila en la columna =[@Ventas]
Fila de encabezados TablaVentas[#Encabezados]
Toda la tabla =SUMA(TablaVentas[#Todo])
Fila de totales =TablaVentas[[#Totales],[Ventas]]

Una ventaja evidente de esta sintaxis es la claridad. No hace falta ver el rango referenciado para saber qué calcula la fórmula.

Esto nos permite crear fórmulas con mucha facilidad, como podemos ver

escribir fórmula

Al comenzar a escribir la fórmula Excel nos muestra las tablas como un rango definido; pero la mejor parte viene ahora

definicion de formula

 Al poner el "["Excel nos muestra todos los rangos disponibles para nuestra fórmula. Así que si queremos calcular el total de ventas elegimos Ventas, ponemos el "]" para cerrar la definición del campo, cerramos el o los paréntesis necesarios y apretamos Enter. 

Para referirse a una celda dentro de la Tabla, Excel usa la notación [@nombre del campo]. Por ejemplo, si tenemos una columna de descuentos en nuestra tabla y queremos calcular las ventas neto

referencia a celda dentro de Tabla


Más sobre la sintaxis y el uso de referencias  estructuradas pueden leer en esta nota del sitio Office de Microsoft.

martes, marzo 18, 2014

Como sumar los ultimos n valores de un rango con celdas vacías

Aún no se ha secado la tinta de mi último post sobre la función INDICE y, por una de esas fantásticas casualidades, recibo esta consulta:

¿cómo puedo sumar los últimos tres valores de un rango que contiene celdas vacías?
La casualidad consiste en que la solución nos permitirá demostrar que INDICE da como resultado referencias a rangos y como ésto nos permite crear rangos dinámicos.

Supongamos estos datos

tabla de datos

La idea es sumar los últimos tres valores de cada fila; en H2 debe ser 280, en H3 debe ser 130, etc. En el pasado he publicado un post sobre cálculos con los últimos n valores de un rango, pero esa técnica suponía que en el rango no había celdas vacías.

La solución es usar esta fórmula matricial (fórmulas que se ingresan apretando simultáneamente Ctrl-Mayúsuculas-Enter)

=SUMA(G2:INDICE(A2:G2,K.ESIMO.MAYOR(COLUMNA(A2:G2)*(A2:G2<>""),3)))
tabla de datos

Analizamos la fórmula de adentro hacia afuera:

La expresión COLUMNA(A2:G2)*(A2:G2<>"") produce un vector de valores númericos que pueden ser el número de columna o 0 si la celda del rango está vacía. Podemos mostrar el resultado de esta expresión en forma no matricial, es decir, aplicada a cada celda del rango


El vector de valores creado es el argumento de la expresión

K.ESIMO.MAYOR(COLUMNA(A2:G2)*(A2:G2<>""),3)

que da como resultado el tercer valor en orden decreciente, es decir 3 (los valores del vector son 6,5,3,2,1 y 0).

Nuestra expresión se ha reducido ahora a INDICE(A2:G2,3) y aquí es donde podemos ver que INDICE da como resultado un rango, no un valor. El resultado de esta expresión es $C$2 y por lo tanto nuestra fórmula es ahora =SUMA(G2:$C$2), es decir =SUMA($C$2:$G$2), lo que nos da el resultado deseado.


De la misma manera podemos aplicar esta fórmula a las columnas en lugar de las filas, utilizando la función FILA() en lugar de la COLUMNA() y corrigiendo los rangos consecuentemente


En este video explico el funcionamiento de la fórmula usando la herramienta Auditoría de fórmula



lunes, marzo 17, 2014

La función INDICE, todo (o casi todo) lo que hay que saber

En la nota Traducción automática en hoja de Excel propuse dar un premio (el Planificador de Tareas JLD) a los primeros tres lectores que respondieron acertádamente a la pregunta qué tiene de particular la forma la forma en que se usa la función INDICE en el ejemplo de la nota.
Si bien hubo tres ganadores, ninguna respuesta fue totalmente exacta, lo que me impulsó a escribir esta nota.

La función INDICE es una de las más importantes y versátiles funciones del arsenal de Excel (y hay quien la corona como la más importante endilgándole superlatívamente el adjetivo "imponente").

La función INDICE permite encontrar el valor de un elemento dentro de una rango. Este rango puede ser un "vector" (un rango unidimensional de una fila como A2:M2 o de una columna como  A2:A10), o una matriz (un rango "rectangular", por ejemplo A2:M10). Para encontrar el elemento buscado debemos incluir uno o dos índices dependiendo se si trata de un vector o una matriz.

En este ejemplo


INDICE crea una referencia a la celda A2, cuyo valor es 40.  En este otro ejemplo


usamos la misma sintaxis a pesar de que el rango es "horizontal". En este caso INDICE crea una referencia a la celda B1.

Podemos concluir que:
  • que cuando usamos vectores (rangos unidimensionales) INDICE interpreta el segundo argumento como fila o columna dependiendo de la orientación de vector




  • cuando se refiere a un rango, la función INDICE crea una referencia a una celda (o celdas) en el rango.
Cuando usamos INDICE para referirnos a rangos bi-dimensionales, usamos los argumentos de fila y columna para referirnos al elemento buscado en la matriz

En este ejemplo INDICE crea una referencia a la celda B3.

Hasta aquí posiblemente no haya aportado nada dramático a los conocimientos de mis lectores. Ahora los invito a ver esta situación:


Cuando cuando falta el parámetro de fila, o es 0,  INDICE se refiere a toda la columna (en nuestro caso la columna B ya que el parámetro de columna es 2).  Pueden comprobarlo con
34+44+50+26+79+51+57 = 341
De la misma manera, si falta el parámetro columna, INDICE se refiere a toda la fila

47+50+18 = 115
Podemos aprovechar esta propiedad de INDICE para crear rangos dinámicos. La ventaja de usar INDICE en lugar de DESREF o INDIRECTO es que estas dos últimas son volátiles mientras que INDICE no lo es.
Un rango dinámico con INDICE se ve así

=A1:INDICE(A:A,CONTARA(A:A))
donde A1 es la primer celda del rango. Esta fórmula supone que no hay celdas vacías entre A1 y la última celda con valor de la columna A. Para usar esta fórmula como rango dinámica creamos un nombre que se refiera a la fórmula, por ejemplo el nombre "rango_dinamico"

nombre definido

Ahora podemos ver que a medida que agregamos valores en la columna a, el resultado en la celda C1 se va actualizando

rango dinámico



lunes, marzo 10, 2014

Hojas Excel con traducción automática

Recientemente tuve que crear una hoja que incluyera la posibilidad de presentar el contenido en distintos idiomas.
La idea era usar una única hoja, de hecho un dashboard, pero que el usuario pudiera elegir en qué idioma presentar los textos de las celdas y demás objetos en la hoja/dashboard.

Este ejemplo muestra el funcionamiento

captura de pantalla


Como puede apreciarse, cuando el usuario elige un idioma apretando alguno de los botones de opción, los titulas de los cuadros de datos y del gráfico cambian.

La traducción se puede hacer fácilmente usando la función INDICE, pero la técnica varía si se trata de una celda o de un objeto. Esto es lo que mostraré en esta nota.

Para hacerlo empezamos por crear un glosario, una tabla con los textos de las palabras que queremos traducir en los distintos idiomas. En nuestro caso creamos un glosario con Castellano, Inglés e Italiano

glosario

En la hoja del dashboard agregamos los botones de opción para la elección de los idiomas. En las definiciones del botón lo asociamos a una celda. Es una buena práctica usar las columnas de la izquierda como columnas auxiliares, de manera que podamos ocultarlas. En nuestro caso vinculamos los botones a la celda A3

Definicion del boton de opcion
Otra buena práctica en Excel es definir un nombre que se refiera a la celda; en nuestro caso definimos el nombre "cel_Idioma" que se refiere a la celda A3

nombre definido

También es recomendable enmarcar los botones de opción en un cuadro de grupos.

Cuando el usuario elige el Castellano, el valor de "cel_Idioma" es 1; si elige English, será 2 y si elige Italiano será 3.

En la celda F3 de la hoja dashboard ponemos esta fórmula:

=INDICE(glosario!B6:D6,cel_Idioma)
formula para traducir

Esta fórmula usa el valor de "cel_Idioma" para extraer el texto en el idioma correspondiente en la tabla Glosario.

Pregunta con premio (copia gratuita totalmente funcional del Planificador de Proyectos) a las primeras tres respuestas correctas:

¿Que tiene de particular la fórmula en la celda F3 del ejemplo?

 La misma técnica empleamos para todas las celda cuyo contenido queremos traducir.

Si nos fijamos en el título de la lista desplegable del gráfico, veremos que se trata de un cuadro de texto "montado" sobre una celda.

cuadro de texto

No podemos ligar un cuadro de texto, o cualquier otra forma gráfica, a una fórmula pero si podemos hacerlo a una referencia. El rodeo para lograr el efecto de traducción consiste en poner la fórmula con la función INDICE que extrae la traducción del Glosario en una celda de la columna A (de manera que luego podamos ocultarla).

Creamos un cuadro de texto (o cualquier otra forma) y la superponemos en la celda adecuada (K2 en nuestro ejemplo). Luego seleccionamos el cuadro de texto y en la barra de las fórmulas ponemos =A9 (o ponemos = y luego hacemos un clic en la celda A9)

ligar forma a celda

La celda A9 contiene la fórmula

=INDICE(glosario!B14:D14,cel_Idioma)

Otra situación es si usamos tablas dinámmicas. A pesar que las tablas ocupan celdas, no podemos introducir fórmulas en los encabezamientos de las áreas (si podemos cambiar el texto).
Para superar este problema usamos nuevamente cuadros de texto ligados a celdas ocultas que contienen la fórmula con la función INDICE. Para mimetizar los cuadros de texto con el resto de la tabla le damos un relleno sólido con el mismo color que la tabla

tabla dinamica

En este video podemos ver el dashboard en funcionamiento



martes, marzo 04, 2014

Calcular días por años entre dos fechas

Supongamos una lista de fechas de inicio y finalización de tareas (o contratos o cualquier otra actividad) que se extienden a más de una año, como en este ejemplo:

tabla de fechas


Podemos ver, por ejemplo, que la Tarea 1 empieza en el 2013 y termina en el 2015. ¿Cómo hacemos para calcular cuántos días caen en cada año?

Para resolver este problema vamos a usar una técnica no tan conocida: crear dentro de la fórmula un vector implícito (o "virtual"). El concepto quedará más claro cuando expliquemos la fórmula.

La columna "Total de días" muestra el total entre ambas fechas (incluida el día del comienzo) usando la fórmula =SIFECHA(C4,D4,"d")+1

Para poder calcular cuantos días caen dentro de cada año (2013,2014,2015), vamos a agregar tres columnas en nuestra tablam una para cada año, y en la celda F4 ponemos esta fórmula (que luego copiamos al resto de la tabla):

=SUMAPRODUCTO(--(AÑO($C4+FILA(INDIRECTO("1:"&($D4-$C4+1))))=F$3))

tabla de datos

Vamos a "disecar" la fórmula de adentro hacia afuera:


  • La expresión "($D4-$C4+1)" calcula el total de días transcurridos entre el principio y el fin de la tarea. Es equivalente al cálculo en la celda E4.
  • La expresión INDIRECTO("1:"&($D4-$C4+1)) crea una referencia al rango "1:750". Al usar esta expresión como argumento de la función FILA en forma matricial (al estar dentro de la función SUMAPRODUCTO), obtenemos un vector con los valores 1,2,3,...,750
  • Al sumar a $C4 este vector en ($C4+FILA(INDIRECTO("1:"&($D4-$C4+1))), obtenemos un vector de fechas día por día que comienza el 06/07/2013 y termina con el 25/07/2015
  • La función AÑO extrae de cada fecha el año correspondiente, por lo que obtenemos un vector de años con 750 puntos.
  • Este vector los comparamos con el año que aparece en la celda F$3, por lo que obtenemos un vector de valores VERDADERO o FALSO (si se cumple o no la condición).
  • La doble negación a la izquierda de la función AÑO convierta los valores VERDADERO en 1 y los FALSO en 0. Igualmente podríamos haber multiplicado la expresión por 1.
  • Finalmente SUMAPRODUCTO suma todos los valores del vector que cumplen con la condición. Recordemos, como puse más arriba, que SUMAPRODUCTO se comporta en forma matricial.
Podemos visualizar el proceso del cálculo usando la herramienta "Evaluar fórmula" en "Fórmulas-Auditoría de fórmulas"

formulario auditoría de fórmulas

En este video comento el proceso


domingo, marzo 02, 2014

Gráficos Excel - Fijar máximos del eje vertical con macro

En la nota anterior sobre el tema mencionamos que la solución tradicional para coordinar el máximo del eje de las Y (eje de los valores en términos de Excel) es usar una macro.
El método manual, con fórmulas y series auxiliares, tiene la ventaja que puede ser usado también en entornos donde las macros están bloqueadas, por ejemplo,  por el administrador de la red. Las deventajas son menores pero existen:

  • el valor máximo es determinado por el algoritmo de Excel, por lo que siempre será cercano al valor deseado pero no siempre exactamente igual;
  • hay que modificar cada uno de las gráficos que queremos coordinar.
Las macros son más flexibles y eficientes, ya que podemos establecer exactamente el valor que queremos que aparezca como máximo y podemos aplicarlas a todos los gráficos de la hoja.

El código es muy sencillo y podemos usarlo de dos maneras distintas: como sub (macro común) o como evento. Al usarlo como sub, tenemos que crear también la forma de disparar el código, por ejemplo, ligando la macro a un botón; al usar eventos podemos hacer que la macro corra cuando, por ejemplo, el usuario cambia algún dato en la tabla de los datos.

Como en el ejemplo de la nota anterior, tenemos dos gráficos basados en dos tablas de datos y en la celda A3 calculamos el valor máximo de ambas tablas (hemos creado el nombre "cellValMax" que se refiere a la celda A3)

definiciones del grafico
Como podemos ver en la imagen, la escala del eje de las Y es diferente en cada gráfico y por lo tanto la comparación visual es engañosa.
Como mencionamos más arriba podemos usar el código como sub (macro) o como evento; el código es el mismo pero la forma de hacerlo correr es distinta.

Uso del código como sub (macro)

En un módulo compun del editor de Vb, ponemos este código

Sub coordinar_max_graficos()
   Dim dbMax As Double
   Dim objCht As ChartObject

   dbMax = Range("cellValMax").Value
  
   For Each objCht In ActiveSheet.ChartObjects
      With objCht.Chart.Axes(xlValue)
        .MaximumScale = dbMax
        .MinimumScale = 0
      End With
   Next objCht
End Sub


En la hoja que contiene los gráficos agregamos un botón ligado a la macro




Uso del código como evento

Para usarlo como evento el código debe ir en un módulo de la hoja que contiene los gráficos. Una de las formas de acceder a este módulo es apunta con el mouse a la pestaña con el nombre de la hoja y activar la opción Ver código

ver codigo de a hoja

En nuestro caso vamos a crear un evento de manera que cuando el usuario haga algún cambio en la hoja, se dispare el código. Para esto usamos un evento del tipo Change

codigo del evento

Como puede apreciarse, el código es el mismo que en la rutina sub.

Coordinar el valor máximo del eje vertical en varios gráficos de Excel

Una participante en el foro Expertos en Excel en Español consultaba si se puede condicionar el valor máximo de un grupo de gráficos de manera que viniese determinado por el gráfico que tenga la cifra mayor.

Para ejemplificar, digamos que tenemos dos gráficos que muestran dos series de valores (val1 y val2 en la imagen)

tablas y graficos

Sin entrar en la la cuestión si poner un gráfico al lado del otro o crear un único gráfico con dos series de datos, podemos ver que en nuestro ejemplo los máximos del eje de los valores (el eje Y) son distintos en cada gráfico. Esto hace que la comparación visual sea engañosa; lo que buscamos es que en los dos gráficos el eje de los Y tenga el mismo valor máximo.

Como los valores van cambiando no podemos fijar la definición del máximo del eje. La solución tradicional es programar un evento (Vba), de manera que cuando algún valor cambia en alguna de las tablas el evento cambia el valor del máximo en ambos gráficos.

Sin embargo, existe la posibilidad de lograr el mismo efecto sin macros. El truco consiste en incluir en ambos gráficos una serie auxiliar con un sólo punto cuyo valor sea el máximo de los los valores de ambas tablas.
Además de tener el valor máximo de todos los valores de las tablas esta serie debe cumplir con otros dos requisitos:

  1. ser "invisible";
  2. ser "inmaterial", con lo que quiero decir que no influye en como el resto de los puntos de las series se muestran en los gráficos (este concepto quedará más claro en las subsiguientes explicaciones).
En nuestro ejemplo empezamos por crear la serie auxiliar poniendo esta fórmula en una celda: =MAX(D3:E7,L3:M7)

crear serie auxiliar

Como puede verse, ponemos el fórmula en la columna A, dejando la columna B libre. El motivo es poder luego ocultar la columna A para no recargar nuestro modelo mostrando datos auxiliares.

El próximo paso es agregar la serie auxiliar en los gráficos. Seleccionamos el primer gráfico y en el menú Diseño de la opción Herramienta de gráficos activamos "Seleccionar Datos-Agregar". y en el formulario que se abre ponemos estas definiciones

definiciones de la serie
Apretamos "Aceptar" y en formulario que se abre apretamos el botón "Celdas ocultas y vacías"

celdas ocultas y vacías
En el formulario de configuración de celdas ocultas y vacías marcamos la opción "Mostrar datos..."

mostrar datos

Ahora tenemos que ocuparnos de los requisitos que debe cumplir la serie auxiliar. Cambiamos el tipo de serie a "Línea" sin marcadores

gráfico línea sin marcadores

Esto hace que la la serie "desaparezca" (al tener un solo punto no aparece la línea ni el marcador; tampoco "comparte" lugar en el eje de las X con los otros puntos de la serie).

Repetimos el proceso para el segundo gráfico. Ahora podemos ver que en ambos gráficos el eje de las Y tiene el mismo valor máximo

gráficos comparados

Cada vez que cambiemos algún valor en alguna de las tablas, Excel calculará el mismo máximo para el eje de las Y en ambos gráficos.

En esta nota pueden ver la solución usando macros.