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.

jueves, febrero 27, 2014

Uso de controles en hojas de Excel - Spin Button con valores no enteros

En la nota anterior vimos como superar la limitación del uso de números negativos en los controles Spin Button y Scroll Bar. En esta nota veremos un rodeo para usar números no enteros en estos controles.

Supongamos que queremos crear un Control de Número que vaya de 0 a 5, pero en saltos de 0.5 (en algunos países se usa la coma en lugar del punto para separar la parte decimal del número).

Excel nos deja ingresar un número no entero en la casilla Incremento,

definiciones del control


pero al apretar Aceptar cambia la definición dejando sólo la parte entera del número. En  nuestro ejemplo, la casilla Incremento mostrará 0.

Como en la nota anterior, el rodeo consiste en usar una celda auxiliar. Siguiendo con nuestro ejemplo, el valor mínimo es 0; el máximo será 10 (resulta de dividir 5 por 0.5) y el incremento 1. En nuestro ejemplo la celda vinculada es A3 y en la celda A4 ponemos la fórmula =A3/2 o su equivalente =A3*0.5

definiciones dle control

En resumen, la norma es:

  • mínimo: 0
  • máximo: máximo deseado dividido por el incremento deseado
  • incremento: 1
  • en la celda auxiliar: celda vinculada multiplicada por el  incremento deseado (o dividida por el inverso del incremento deseado)
Asi que si quisiéramos ir de 0 a 10 con incrementos de 1/3, ponemos 30 en la casilla del máximo y en la celda auxiliar (A4) =A3/3

Si usamos el Control de Número (Spin Button) de la colección ActiveX podemos dar una solución sin usar una celda auxiliar programando eventos para definir el control dinámicamente de acuerdo a valores que ingresemos en celdas de la hoja.

Siguiendo con nuestro ejemplo, ponemos el valor máximo deseado (10) en la celda E3 y el valor de incremento enla celda E4. En las propiedades del control dejamos el valor de la propiedad LinkedCell (celda vinculada) en blanco


Tal como indicamos en la nota anerior, abrimos el editor de Vb en el módulo de la hoja que contiene el control seleccionando el control y apreando Ver Código. En el módulo de la hoja ponemos estos dos eventos:

Códigos de los eventos


El evento GotFocus define el valor máximo del control de acuerdo a los valores que ingresamos en las celda E3 y E4 y el evento Change pasa el valor calculado a la celda vinculada con cada cambio del control