Supongamos esta situación:
Hemos representado en el gráfico una serie de valores que pertenecen a tres grupos (en la "vida real" podría tratarse de ventas de grupos de productos o de salarios de grupos de trabajadores, etc.).
Lo que queremos es representar cada grupo con un color distinto. Por defecto, Excel da a todos los puntos de una serie el mismo color. Podríamos cambiar el color de la columna de cada punto manualmente, pero podemos con hacerlo fácilmente usando la técnica que mostraré a continuación (y que ya he mostrado en alguna nota en el pasado).
El truco consiste en descomponer la única serie en tres series, una para cada grupo. Lo hacemos creando tres columnas auxiliares
En este ejemplo me he limitado a copiar los valores del grupo 1 a la columna D, los del grupo 2 a la columna E y los del grupo 3 a la columna F.
Para crear el nuevo gráfico seleccionamos el rango B2:B11 e inmediatamente, apretando y manteniendo apretada la tecla Ctrl. el rango D2:F11; seleccionamos Insertar-Gráfico-Columna, y obtenemos
Excel otorga automáticamente un color distinto a cada serie. Por supuesto podemos ocultar las columnas auxiliares o ponerlas en un rango oculto.
Mis perspicaces lectores habrán notado que existe un problema con las etiquetas del eje de las categorías (el eje de las X). Estas están alineadas a la izquierda, coincidiendo con el primer valor de cada grupo, cuando lo que quisiéramos es que estuvieran en el centro del grupo.
Para obligar a Excel a centrar los rótulos del eje agregamos una columna a nuestra tabla, entre las columna B y C; esta columna contiene un espacio (no está vacía, sencillamente seleccionamos la celda, apretamos la tecla de espacios e inmediatamente Enter)
Sugerencias y ayuda para Excel en español. Ejemplos de funciones y fórmulas, gráficos, automatización con Vba, Power Query y PowerPivot
jueves, noviembre 27, 2014
lunes, noviembre 24, 2014
Agregar controles en una hoja de Excel usando Vba
Los controles (casillas de verificación, cuadros combinados, botones de opción, etc.) dan un "toque profesional" a la hoja pero no siempre son la mejor opción. En general podemos encontrar soluciones más prácticas usando, por ejemplo, validación de datos y/o funciones SI.
Lo más corriente es agregar controles en la hoja en forma manual, usando el menú Desarrollador-Controles-Insertar. Existen dos colecciones de controles: Formulario y ActiveX.
En esta nota veremos como insertar controles ActiveX usando Vba.
Supongamos esta tabla de facturas con sus fechas de vencmientos
En el campo "Pagada" (columna E) anotamos "SI" cuando la factura ha sido pagada. Esto nos permite crear el informe que nos muestra los totales de facturas atrasadas, pagadas y a vencer.
Las fórmulas en el informe son:
celda H4:
celda H5:
celda H6:
la Tabla "tblFacturas" se refiere al rango B2:E16 (supongo que la mayoría de mis lectores ya hayan adoptado la sana costumbre de usar Tablas para organizar matrices de datos).
Y ahora vayamos a la cuestión de los controles incrustados en hojas de Excel. En nuestro ejemplo queremos usar casillas de verificación para señalar que una factura ha sido pagada en lugar de un "plebeyo" SI.
Queremos que nuestro informe se vea así:
Si nuestra tabla tiene pocas filas podemos simplemente agregar los controles manualmente. Las casillas están definidas sin texto, ligadas a ka celda sobre la cual están ubicadas y el valor es FALSO. Todo esto tenemos que definirlo cambiando las propiedades por defecto de la casilla. Para ahorrarnos el trabajo de hacerlo cada vez que queremos agregar una casilla podemos usar esta macro:
Sub insert_one()
With ActiveSheet.OLEObjects.Add(classtype:="Forms.Checkbox.1", _
Top:=ActiveCell.Top + 1, Left:=ActiveCell.Left + 15, _
Height:=ActiveCell.Height, Width:=ActiveCell.Width * 0.5)
.Object.Caption = ""
.LinkedCell = ActiveCell.Address
.Object.Value = False
.Object.BackStyle = fmBackStyleTransparent
End With
End Sub
El código agrega la casilla de verificación en la celda (con el método Add); luego definimos algunas propiedades:
Caption = "" para que la casilla no contenga ningún texto;
LinkedCell = Activecell.Address para ligar la casilla a la celda; esto es necesario para poder luego utilizar el valor de la casilla en nuestras fórmulas.
Value = False para que éste sea el valor por defecto en la celda vinculada a la casilla de verificación.
En la tabla de las facturas cambiamos el color de la fuente en las celdas de la columna Pagadas a blanco, para que el valor de la casilla en la celda vinculada no sea visible.
Dado que en el campo Pagada tenemos ahora valores FALSO o VERDADERO (cuando la casilla a sido marcada), tenemos que modificar nuestras fórmulas
celda H4:
Si tenemos una tabla con muchas filas podemos y queremos agregar las casillas en un única operación podemos usar esta macro (igual a la anterior a la que le hemos agregado un loop):
Sub insert_check()
Dim rngCell As Range
Application.ScreenUpdating = False
For Each rngCell In Selection
rngCell.Select
With ActiveSheet.OLEObjects.Add(classtype:="Forms.Checkbox.1", _
Top:=ActiveCell.Top + 1, Left:=ActiveCell.Left + 15, _
Height:=ActiveCell.Height, Width:=ActiveCell.Width * 0.5)
.Object.Caption = ""
.LinkedCell = ActiveCell.Address
.Object.Value = False
End With
Next rngCell
Application.ScreenUpdating = True
End Sub
Sub del_all_cb()
Lo más corriente es agregar controles en la hoja en forma manual, usando el menú Desarrollador-Controles-Insertar. Existen dos colecciones de controles: Formulario y ActiveX.
En esta nota veremos como insertar controles ActiveX usando Vba.
Supongamos esta tabla de facturas con sus fechas de vencmientos
En el campo "Pagada" (columna E) anotamos "SI" cuando la factura ha sido pagada. Esto nos permite crear el informe que nos muestra los totales de facturas atrasadas, pagadas y a vencer.
Las fórmulas en el informe son:
celda H4:
=SUMAPRODUCTO((tblFacturas[Fecha Vencimiento]<H3)*(tblFacturas[Pagada]<>"SI")*tblFacturas[Importe])
celda H5:
=SUMAR.SI(tblFacturas[Pagada],"SI",tblFacturas[Importe])
celda H6:
=SUMAPRODUCTO((tblFacturas[Fecha Vencimiento]>=H3)*(tblFacturas[Pagada]<>"SI")*tblFacturas[Importe])
la Tabla "tblFacturas" se refiere al rango B2:E16 (supongo que la mayoría de mis lectores ya hayan adoptado la sana costumbre de usar Tablas para organizar matrices de datos).
Y ahora vayamos a la cuestión de los controles incrustados en hojas de Excel. En nuestro ejemplo queremos usar casillas de verificación para señalar que una factura ha sido pagada en lugar de un "plebeyo" SI.
Queremos que nuestro informe se vea así:
Si nuestra tabla tiene pocas filas podemos simplemente agregar los controles manualmente. Las casillas están definidas sin texto, ligadas a ka celda sobre la cual están ubicadas y el valor es FALSO. Todo esto tenemos que definirlo cambiando las propiedades por defecto de la casilla. Para ahorrarnos el trabajo de hacerlo cada vez que queremos agregar una casilla podemos usar esta macro:
Sub insert_one()
With ActiveSheet.OLEObjects.Add(classtype:="Forms.Checkbox.1", _
Top:=ActiveCell.Top + 1, Left:=ActiveCell.Left + 15, _
Height:=ActiveCell.Height, Width:=ActiveCell.Width * 0.5)
.Object.Caption = ""
.LinkedCell = ActiveCell.Address
.Object.Value = False
.Object.BackStyle = fmBackStyleTransparent
End With
End Sub
El código agrega la casilla de verificación en la celda (con el método Add); luego definimos algunas propiedades:
Caption = "" para que la casilla no contenga ningún texto;
LinkedCell = Activecell.Address para ligar la casilla a la celda; esto es necesario para poder luego utilizar el valor de la casilla en nuestras fórmulas.
Value = False para que éste sea el valor por defecto en la celda vinculada a la casilla de verificación.
En la tabla de las facturas cambiamos el color de la fuente en las celdas de la columna Pagadas a blanco, para que el valor de la casilla en la celda vinculada no sea visible.
Dado que en el campo Pagada tenemos ahora valores FALSO o VERDADERO (cuando la casilla a sido marcada), tenemos que modificar nuestras fórmulas
celda H4:
=SUMAPRODUCTO((tblFacturas3[Fecha Vencimiento]<H3)* (tblFacturas3[Pagada]=FALSO())*tblFacturas3[Importe])
celda H5:=SUMAR.SI(tblFacturas3[Pagada],"VERDADERO",tblFacturas3[Importe])
celda H6:=SUMAPRODUCTO((tblFacturas3[Fecha Vencimiento]>=H3)*(tblFacturas3[Pagada]=FALSO())*tblFacturas3[Importe])
Si tenemos una tabla con muchas filas podemos y queremos agregar las casillas en un única operación podemos usar esta macro (igual a la anterior a la que le hemos agregado un loop):
Sub insert_check()
Dim rngCell As Range
Application.ScreenUpdating = False
For Each rngCell In Selection
rngCell.Select
With ActiveSheet.OLEObjects.Add(classtype:="Forms.Checkbox.1", _
Top:=ActiveCell.Top + 1, Left:=ActiveCell.Left + 15, _
Height:=ActiveCell.Height, Width:=ActiveCell.Width * 0.5)
.Object.Caption = ""
.LinkedCell = ActiveCell.Address
.Object.Value = False
End With
Next rngCell
Application.ScreenUpdating = True
End Sub
Sub del_all_cb()
lunes, noviembre 17, 2014
Cálculo de duración de procesos por turnos
Los cálculos con fechas y horas en Excel suelen ser un tanto truculentos. Veamos por ejemplo esta consulta de una de mis lectoras:
La fórmula que nos permite hacer este cálculo es la siguiente
Veamos como funciona esta fórmula:
C5>C2 determina si el proceso puede completarse en las horas del turno;
B5 contiene la fecha y hora del comienzo del proceso;
TRUNCAR(C5/C2) nos calcula cuantos días debemos agregar a la fecha de iniciación del proceso para completarlo (múltiplos de la duración del turno);
RESIDUO(C5,C2) calcula cuántas horas debemos agregar a los múltiplos de ocho horas (la duración del turno).
De esta manera, si el proceso dura más de ocho horas, la función SI aplica la primer parte de la fórmula:
B5+TRUNCAR(C5/C2)+RESIDUO(C5,C2)
Las cosas se complican un poco (más) si queremos calcular la fecha de finalización del proceso tomando en cuenta sólo los días laborables.
Contamos para ello con la función DIA.LAB, es cierto, pero hay un pequeño problema. DIA.LAB no toma en cuenta las horas, sólo las fechas, como podemos ver en este ejemplo:
Dado que el 14/11/2014 cae un viernes, el próximo día laboral es el 17/11/2014 (lunes), pero podemos ver que la fórmula no toma en cuenta la hora de comienzo, sólo la fecha.
A pesar de esto podemos usar DIA.LAB para nuestro cálculo, de esta manera:
=SI(C5>C2,DIA.LAB(B5,TRUNCAR(C5/C2))+C1+RESIDUO(C5,C2),B5+C5)
donde C1 es la hora de comienzo del turno.
Suponiendo que es 14-nov-14 8:00 am, tengo un proceso que dura 9 horas y mi turno dura 8 horas, cómo puedo hacer para que el día 15-nov-14 la hora de finalización sea 9:00amEs decir, la tarea se realiza en un turno que empieza a las 08:00 AM y dura ocho horas. Si la tarea se extiende por más de ocho horas, ésta será completada el día siguiente.
La fórmula que nos permite hacer este cálculo es la siguiente
=SI(C5>C2,B5+TRUNCAR(C5/C2)+RESIDUO(C5,C2),B5+C5)
Veamos como funciona esta fórmula:
C5>C2 determina si el proceso puede completarse en las horas del turno;
B5 contiene la fecha y hora del comienzo del proceso;
TRUNCAR(C5/C2) nos calcula cuantos días debemos agregar a la fecha de iniciación del proceso para completarlo (múltiplos de la duración del turno);
RESIDUO(C5,C2) calcula cuántas horas debemos agregar a los múltiplos de ocho horas (la duración del turno).
De esta manera, si el proceso dura más de ocho horas, la función SI aplica la primer parte de la fórmula:
B5+TRUNCAR(C5/C2)+RESIDUO(C5,C2)
Las cosas se complican un poco (más) si queremos calcular la fecha de finalización del proceso tomando en cuenta sólo los días laborables.
Contamos para ello con la función DIA.LAB, es cierto, pero hay un pequeño problema. DIA.LAB no toma en cuenta las horas, sólo las fechas, como podemos ver en este ejemplo:
A pesar de esto podemos usar DIA.LAB para nuestro cálculo, de esta manera:
=SI(C5>C2,DIA.LAB(B5,TRUNCAR(C5/C2))+C1+RESIDUO(C5,C2),B5+C5)
donde C1 es la hora de comienzo del turno.
viernes, noviembre 14, 2014
Usos poco comunes de la función ELEGIR
Si las funciones tuvieran sentimientos ELEGIR seguramente se sentiría subestimada; y con bastante razón.
La descripción de la función en la ayuda en línea de Excel reza literalmente:
Interesante! ELEGIR puede usar matrices como número de índice y las referencias pueden ser valores individuales y rangos.
Estas carcterísticas nos abren muchas más posibilidades de lo que podemos deducir de la escueta descripción en la ayuda.
Veamos algunos ejemplos:
Operaciones dinámicas con rangos.
Consideremos esta tabla de datos
Hemos definido los nombres "Plan", "Ventas" y "Diferencia" que se refieren a los respectivos rangos en la tabla. La fórmula
=SUMA(ELEGIR(1,Plan,Ventas,Diferencia))
da el total del plan de ventas de todos los productos. De la misma manera
=SUMA(ELEGIR(2,Plan,Ventas,Diferencia))
Para que la fórmula sea más dinámica podemos combinarla con la función COINCIDIR y usar vallidación de datos para crear una lista desplegable con las distintas opciones
=SUMA(ELEGIR(COINCIDIR(G2,B2:D2,0),Plan,Ventas,Diferencia))
Si bien podemos crear el mismo modelo usando INDICE, la ventaja de ELEGIR es que podemos usar rangos que este en distintas hojas.
BUSCARV de derecha a izquierda.
Uno de los usos de ELEGIR con matrices es hacer que BUSCARV (VLOOKUP) pueda trabajar de derecha a izquierda. Por ejemplo, en la tabla anterior si queremos encontrar a qué producto pertenece el importe 13,048 usamos
=BUSCARV(13048,ELEGIR({2,1},A3:A7,B3:B7),2,0)
Para entender como funciona esta fórmula podemos usar el evaluador de fórmulas (Fórmulas-Auditoría-Evaluar Fórmulas)
Podemos ver que la expresión ELEGIR({2,1},A3:A7,B3:B7) crea una matriz de dos columnas donde la primera es el importe de las ventas y la segunda los nombres de los productos.
En mi opinión el uso más importante de ELEGIR es reemplazar el sobrestimado uso de SI anidado. Como ya hemos señalado en una nota de este blog anidar funciones SI es una de las mejores maneras de cometer errores en una hoja de cálculo. Después de tres o cuatro niveles, la fórmula se vuelve practicamente incontrolable (y me disculparán todos esos cursos que insisten en enseñar a construir fórmulas SI anidadas como si fuera una gran proeza).
Para ejemplificarlo supongamos que queremos determinar el responsable de producción según el día de la semana. La fórmula para seis días de la semana, donde en la celda B3 tenemos la fecha a considerarcon sería
con Si anidado
=SI(DIA(B3)=1,"Roberto",SI(DIA(B3)=2,"Juan",SI(DIA(B3)=3,"Carlos",SI(DIA(B3)=4,"Esteban",SI(DIA(B3)=5,"Raul","Jose")))))
Con ELEGIR
=ELEGIR(DIA(B3),"Roberto","Juan","Carlos","Esteban","Raul","Jose")
Como diría Gracián, "lo bueno si breve, dos veces bueno".
Que tengan un buen fin de semana
La descripción de la función en la ayuda en línea de Excel reza literalmente:
Utiliza el argumento núm_índice para devolver un valor de una lista de argumentos de valores.La cuestión se vuelve más interesante cuando seguimos leyendo y llegamos a las observaciones:
- Si núm_índice es una matriz, cada valor se evaluará cuando se evalúe ELEGIR.
- Los argumentos de valor para ELEGIR pueden ser referencias de rango, así como valores individuales.
Interesante! ELEGIR puede usar matrices como número de índice y las referencias pueden ser valores individuales y rangos.
Estas carcterísticas nos abren muchas más posibilidades de lo que podemos deducir de la escueta descripción en la ayuda.
Veamos algunos ejemplos:
Operaciones dinámicas con rangos.
Consideremos esta tabla de datos
Hemos definido los nombres "Plan", "Ventas" y "Diferencia" que se refieren a los respectivos rangos en la tabla. La fórmula
=SUMA(ELEGIR(1,Plan,Ventas,Diferencia))
da el total del plan de ventas de todos los productos. De la misma manera
=SUMA(ELEGIR(2,Plan,Ventas,Diferencia))
Para que la fórmula sea más dinámica podemos combinarla con la función COINCIDIR y usar vallidación de datos para crear una lista desplegable con las distintas opciones
=SUMA(ELEGIR(COINCIDIR(G2,B2:D2,0),Plan,Ventas,Diferencia))
Si bien podemos crear el mismo modelo usando INDICE, la ventaja de ELEGIR es que podemos usar rangos que este en distintas hojas.
BUSCARV de derecha a izquierda.
Uno de los usos de ELEGIR con matrices es hacer que BUSCARV (VLOOKUP) pueda trabajar de derecha a izquierda. Por ejemplo, en la tabla anterior si queremos encontrar a qué producto pertenece el importe 13,048 usamos
=BUSCARV(13048,ELEGIR({2,1},A3:A7,B3:B7),2,0)
Para entender como funciona esta fórmula podemos usar el evaluador de fórmulas (Fórmulas-Auditoría-Evaluar Fórmulas)
Podemos ver que la expresión ELEGIR({2,1},A3:A7,B3:B7) crea una matriz de dos columnas donde la primera es el importe de las ventas y la segunda los nombres de los productos.
En mi opinión el uso más importante de ELEGIR es reemplazar el sobrestimado uso de SI anidado. Como ya hemos señalado en una nota de este blog anidar funciones SI es una de las mejores maneras de cometer errores en una hoja de cálculo. Después de tres o cuatro niveles, la fórmula se vuelve practicamente incontrolable (y me disculparán todos esos cursos que insisten en enseñar a construir fórmulas SI anidadas como si fuera una gran proeza).
Para ejemplificarlo supongamos que queremos determinar el responsable de producción según el día de la semana. La fórmula para seis días de la semana, donde en la celda B3 tenemos la fecha a considerarcon sería
con Si anidado
=SI(DIA(B3)=1,"Roberto",SI(DIA(B3)=2,"Juan",SI(DIA(B3)=3,"Carlos",SI(DIA(B3)=4,"Esteban",SI(DIA(B3)=5,"Raul","Jose")))))
Con ELEGIR
=ELEGIR(DIA(B3),"Roberto","Juan","Carlos","Esteban","Raul","Jose")
Como diría Gracián, "lo bueno si breve, dos veces bueno".
Que tengan un buen fin de semana
lunes, noviembre 10, 2014
Fechas de vencimiento en un día determinado
En la edad de piedra de este blog, hace varios años atrás, tratamos el tema del cálculo de fecha de pago.
En esa nota mostramos dos casos:
# - la fecha de vencimiento sucede 30 días a partir de la fecha de la factura, cuando la intención es el mismo día un mes más tarde. En este caso, suponiendo que la fecha de la factura está en la celda B3, =B3+30 sino =FECHA.MES(B3,1)
En esa nota mostramos dos casos:
# - la fecha de vencimiento sucede 30 días a partir de la fecha de la factura, cuando la intención es el mismo día un mes más tarde. En este caso, suponiendo que la fecha de la factura está en la celda B3, =B3+30 sino =FECHA.MES(B3,1)
Si usáramos =B3+30 el resultado sería 24/11/2014
# - la fecha de vencimiento debe caer en un día determinado del mes, por ejemplo el 15. Para este caso usamos la fórmula
=SI(DIA(B3)<=15,FIN.MES(B3,0)+15,FIN.MES(B3,1)+15)
(en la nota original usé una fórmula innecesariamente más complicada)
Un lector me consulta cómo calcular la fecha de pago de manera que caiga en un día determinado de la semana. Por ejemplo, una empresa que decide pagar 30 días después de la fecha de la factura pero sólo los días lunes. Consideremos esta tabla
La columna C muestra la fecha de vencimiento 30 días a partir de la fecha de la factura (el mismo día, un mes más tarde). En la celda C3 vemos que el vencimiento cae el 2/11/2014 que es un domingo; para corregir la fecha al lunes más cercano en la celda D3 ponemos la fórmula
=FECHA.MES(B3,1)+(2-DIASEM(FECHA.MES(B3,1)))
Al copiar la fórmula al resto de las celdas vemos que los vencimiento ocurren siempre los lunes (3/11/14, 10/11/14, etc.)
Esta fórmula funciona así:
=FECHA.MES(B3,1) da la fecha que aparece en la columna C (30 días de la fecha de la factura);
(2-DIASEM(FECHA.MES(B3,1))) es el "factor de correción" donde DIASEM(FECHA.MES(B3,1)) da el número de orden del día del vencimiento antes de la correción (el que aparece en la columna C), en nuestro caso 1 (domingo) y el resultado de la expresión será 2-1=1.
Algunos de mis agudos lectores ya habrán descubierto un problema potencial en este cálculo. Si observamos la factura en la fila 9 de la tabla, vemos que los 30 días caen el 8/11/2014 pero al corregir la fecha con la fórmula el pago ocurrirá 5 días antes, el 3/11/2014.
Si queremos que el pago ocurra siempre el mismo día o después de los 30 días debemos modificar nuestra fórmula a
=FECHA.MES(B3,1)+SI(DIASEM(FECHA.MES(B3,1))<=2,(2-DIASEM(FECHA.MES(B3,1))),7+(2-DIASEM(FECHA.MES(B3,1))))
Una aclaración importante: la función DIASEM usa el argumento Tipo para determinar cuál es el primer día de la semana.
En mi ejemplo el argumento Tipo está en blanco significando que el día 1 es el domingo. Si queremos el número de orden 1 sea el lunes, el valor de Tipo debe ser 2.
Suscribirse a:
Comentarios (Atom)

















