lunes, 10 de abril de 2017

Emulación botonera tres posiciones con VBasic para excel y grabadora de macros



Voy a emular una botonera de tres botones y tres posiciones con VBasic para excel usando la grabadora de macros. La grabadora de macros, cuando la activamos, recoge lo estemos haciendo y nos da el código VBasic que nos permite repetir o automatizar vía programa la tarea realizada.
La botonera emulada es una botonera de tres botones con un led asociado a cada botón. Al pulsar uno de los botones pasa una  posición hundida, su led se enciende y los otros dos botones saltan a una posición resaltada y sus luces se apagan. Supongamos que es la botonera de un aparato para encender o apagar algo remotamente. Las tres posiciones son apagado, encendido y programación por tiempo. Como esto es una emulación de la botonera la parte de programación por tiempo no está incluida.
  • Los botones son formas (shapes) rectangulares o circulares con un formato tridimensional. Aparentan volumen.
  • Antes de empezar hay que imaginar un primer diseño de lo que será la botonera. 
  • En este caso uno de los rectángulos hace de fondo, con formato plano, y los otros tres rectángulos presentan un formato 3D. Uno de los botones parece pulsado y los otros dos sobresalen.
  • El led asociado al  botón pulsado luce y no lucen el resto de los led.
  • La emulación de un led encendido la hago con un aumento de color.
Grabadora de macros: Mis libros sobre VBasic están un poco desactualizados. Al cambiar de máquina cambié de versión de office, y por tanto de excel. Algunas cosas que se pueden hacer hoy hace unos años no se podían hacer.
  • Manualmente preparamos, sin profundizar, el tipo y formato de los botones.
  • Una vez encontrado el diseño, activamos la grabadora de macros. En mi actual excel, Vista->Macros->Grabar Macro.
  • Insertamos un rectángulo.
  • Detenemos la grabadora.
  • Vemos el código generado. Nos genera un código similar a:

 ActiveSheet.Shapes.AddShape(msoShapeRectangle, 301.5, 46.5, 68.25, 36.75).Select

  • Jugando un poco con los valores numéricos vemos que esos valores son los valores izquierda y superior (arriba) de la esquina superior izquierda, y ancho y alto del rectángulo. 
  • Activamos grabadora. 
  • Damos formato al rectángulo. Datos el formato deseado del botón resaltado.
  • Damos el formato de botón pulsado y paramos la grabación.
  • Vemos el código generado.

Sub Macro2()

'
' Macro2 Macro
'

'
    With Selection.ShapeRange.ThreeD
        .BevelTopType = msoBevelCircle
        .BevelTopInset = 6
        .BevelTopDepth = 6
    End With

    With Selection.ShapeRange.ThreeD
        .BevelTopType = msoBevelRelaxedInset
        .BevelTopInset = 6
        .BevelTopDepth = 6
    End With
End Sub


  • Repito el proceso para los led. Inicio grabadora y creo un circulo. Le doy formato y color, le cambio de color a un tono mas brillante y detengo la grabadora.
  • Nos da un código parecido a:

Sub Macro3()

'

' Macro3 Macro
'

'
    ActiveSheet.Shapes.AddShape(msoShapeOval, 361.5, 60, 21, 19.5).Select
    With Selection.ShapeRange.ThreeD
        .BevelTopType = msoBevelCircle
        .BevelTopInset = 6
        .BevelTopDepth = 6
    End With
    With Selection.ShapeRange.Fill
        .Visible = msoTrue
        .ForeColor.RGB = RGB(192, 0, 0)
        .Transparency = 0
        .Solid
    End With
    With Selection.ShapeRange.Fill
        .Visible = msoTrue
        .ForeColor.RGB = RGB(255, 0, 0)
        .Transparency = 0
        .Solid
    End With
End Sub


  • Nuestro circulo (elipse) esta inscrito en un rectángulo. En la instrucción que añade el circulo los valores numéricos son, lo mismo que en el caso anterior, izquierda, superior, ancho y alto. Si queremos un circulo alto y ancho deben ser iguales.
  • El color lo da la función RGB (rojo, verde, azul). Es una combinación de tres los colores básicos, los valores deben estar entre 0 y 255. Cuanto mas alto es un valor mas componente de ese color hay. RGB(125,0,0) da un rojo mas oscuro que RGB(255,0,0)
  • ¿Como conocer el RGB de un color?. Con Paint. Abrimos Paint y entramos en la opción "editar colores". Seleccionamos un color básico o un color de la gama completa de colores. Abajo, a la derecha, encontramos el RGB del color seleccionado.
  • ¿Que otras propiedades puede tener el objeto shape? o cualquier otro objeto.
  • Entramos en los módulos Ver->Examinador de objetos. Salen todos, objetos y colecciones. Buscamos Shape , en singular y shapes en plural. 
  • La pregunta es ¿Como hago referencia a una forma determinada en una hoja con varias formas?
  • Se puede hacer referencia a un una forma determinada por su orden de creación (sahapes(1)) o por su nombre. Se puede asignar un nombre con la propiedad .name.
Tareas repetitivas:
Con la información obtenida con la grabadora se pueden crear todos los botones vía programación. La macro Botonera borra todos los rectángulos que haya en la hoja, los crea y les da formato.


Sub Botonera()

Dim I

NombresyColores
With Sheets("Inicio")
.Select
'******************************Borra shapes****
.Shapes.SelectAll
Selection.Delete
'***************Añade el fondo*******
.Shapes.AddShape(msoShapeRectangle, 25, 25, 115, 90).Select
'*********************************************
 For I = 1 To 3
 'izda,superior,ancho,alto
  ActiveSheet.Shapes.AddShape(msoShapeRectangle, 50, 10 + 25 * I, 80, 20).Select
  
  With Selection

  .Name = NBoton(I) 'Da nombre al botón

.Text = NBoton(I) 'Situa texto del botón
.OnAction = Progs(I) 'Asigna la macro asociada al botón
' Centra tanto verticalmente como horizontalmente el texto del botón. Obtenido con la grabadora de macros
.ShapeRange.TextFrame2.VerticalAnchor = msoAnchorMiddle
.ShapeRange.TextFrame2.HorizontalAnchor = msoAnchorCenter
   End With

    Next
    EN = False
    PT = False
    AP = True
    Leds
  Redibuja
  .Range("a1").Select
End With

End Sub

La macro para incluir los led (macro leds) es similar. Está incluida en el libro excel. 

Cada botón tiene asociada una macro que se lanza al pinchar sobre el. Cada botón tiene asociada, además, una variable booleana, EN de encendido, AP de apagado y PT de programación por tiempo, que indica su situación del botón. Cada botón, ademas, tiene un nombre con el que podemos referenciarlo.
Las macros asociadas a cada botón, en este caso, modifican las variables booleanas asociadas a los tres botones y lanzan la macro "Redibuja", en donde utilizamos las instucciones que hemos obtenido al utilizar la grabadora de macros. El mecanismo general es pasar cada botón a la posición resaltada para después, si es un botón pulsado pasarlo al formato asociado a pulsado. Lo mismo hace para el led encendido. Primero lo apaga y, si debe estar encendido, lo enciende.

Macro Auto_open(). Esta macro está asociada al evento "abrir el libro". Al abrir el libro se ejecuta directamente. En este caso solamente doy valor a unas cuantas variables publicas y redibujo la botonera. 

En vez de tres luces se puede utilizar una sola, que cambiaría de color en función de la posición de los botones. Es tan fácil como utilizar 3 leds.









martes, 4 de abril de 2017

Luces y sombras en excel. Dibujos 3D en excel.



Pequeño trabajo dedicado mas que nada a la presentación. ¿En algún momento hemos necesitado incluir algún efecto 3D en una hoja excel? 

Resaltes y hundimientos:
  • Resalto emulando un botón. Funciona con todos los colores pero sobre todo con colores oscuros. Como necesitamos tres tonos de color, no pueden tener el tono mas oscuro.
  • Funciona particularmente bien con el gris. Con otros colores, los mas claros sobre todo, el efecto 3D se diluye.
  • Supongamos que la luz viene de nuestra izquierda según se mira a la pantalla. La luz que incide sobre un objeto que sobresalga ilumina el borde superior y el borde izquierdo. El borde inferior y el borde derecho permanecen en sombra. Si el objeto esta hundido es al revés, la luz ilumina los bordes inferior y derecho y deja en la sombra los otros dos bordes.
  • Si la luz viene de nuestra derecha los bordes iluminados/en sombra son borde derecho y superior y borde izquierdo e inferior.
  • Por alguna razón que no se explicar parece que funciona mejor si queremos emular una luz por la izquierda.
  • Si damos un tono mas claro a los bordes iluminados y un tono mas oscuro a los bordes en sombra conseguimos un efecto 3D, un botón realzado o un botón hundido.
  • Seleccionamos un rango de celdas, le damos un color gris medio.
  • Seleccionamos, dentro de ese rango, una celda. 
  • Seleccionamos formato de la celda.
  • Seleccionamos Borde.
  • Seleccionamos un gris mas claro que el general de las celdas. 
  • Asignamos ese color al par de bordes correspondientes al efecto deseado.
  • Hacemos lo mismo, con un tono gris mas oscuro, con los otros dos bordes.
  • Con un borde ancho el efecto 3D se diluye un poco.
Imágenes con sombra. Imagen flotante en el espacio:
  • Basta con colocar debajo de ella una imagen idéntica, en cuanto a la forma, pero con un relleno mas oscuro, desplazada ligeramente con respecto a la imagen que queremos que aparezca flotando. Un poco mas a la derecha y un poco mas a abajo, luz de izquierdas. Esto emula una sombra, lo que hace que nuestra imagen parezca que flota en el espacio.
  • Excel tiene una herramienta que permite dar un cierto volumen e  incluir sombras en las imágenes o formas insertadas. Dependiendo de la versión de excel será mas o menos completa. En mi caso tengo instalado office 2013. Con el botón derecho del ratón sobre una imagen se accede al formato de la imagen y en formato se puede jugar con el volumen y la sombra de la imagen.




Matrices de varias dimensiones en VBasic.

Matrices o arrays. Tengo una lista de actuaciones de una multinacional en las 50 provincias españolas. De esa lista debo sacar un resumen de actuaciones por provincia y mes, así como la duración media de las actuaciones con un total anual y un total nacional. Voy a utilizar una macro VBasic con una matriz de mas de una dimensión.
  • Tenemos 50 provincias mas un total nacional.
  • El informe es de los 12 meses del año mas un total anual.
  • Debe incluir tanto el número de actuaciones como la duración media.
  • Por tanto nuestra matriz debe ser de 51*13*2. (50+1,12+1, Act. y duraciones)
  • En la lista hay actuaciones terminadas y actuaciones sin terminar (franqueadas o no franqueadas). 
  • El informe es de actuaciones franqueadas por provincia y mes, independientemente de cuando se inició la actuación.
  • La macro lee de inicio a fin, de una en una, todas las líneas con actuaciones.
  •  Acumula tanto las actuaciones como las duraciones por provincia y mes.
  • Solo si la actuación esta franqueada la tiene en cuenta. 
  • Existe otro filtro, debe estar franqueada en un año determinado.
  • A siguiente código le falta situar el nombre de los meses en la primera línea del informe. Un mes para dos columnas, centrado entre dos celdas. Lo he dejado así para que aquellos que estén interesados lo hagan por su cuenta. Como ejercicio de programación.
  • Por último incluimos un botón en la hoja inicio para lanzar el proceso. Después de incluir el botón, le asignamos la macro con el botón derecho del ratón.  



Código:
***************************Inicio código*******

Sub ProcesoActuaciones()

Dim D, Pr, Nl, Cp, Dur, I, FI, FF, Act(51, 13, 2), AAAA, MM, AProc, J, Meses, Prvs
Meses = Array("Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre", "T.Año")
 'Act(51,13,2) matriz en donde acumulamos los datos
'Meses= Array o matriz con los meses del año. 


Set D = Sheets("Actuaciones")
Set Pr = Sheets("Prv")
Prvs = Pr.Range("b2:b52").Value
AProc = Sheets("Inicio").Range("a2").Value 'Año que se procesa. Lo lógico es colocarlo externamente a este código. Lo sitúo en la hoja Inicio celda A2

With D
Nl = .UsedRange.Rows.Count 'Cuenta el número de lineas usadas

For I = 2 To Nl 'La línea 1 contiene las cabeceras
Cp = .Range("a" & I).Value 'código de provincia
FI = .Range("b" & I).Value 'fecha de inicio
FF = .Cells(I, 3).Value 'fecha fin. Tambien podemos hacer referencia a una celda con cells(fila,columna)

If FF > FI Then ' Si la fecha finalización es mayor que la de inicio
AAAA = Year(FF) 'Año fin
MM = Month(FF) 'mes fin
    If AAAA = AProc Then 'Año de proceso
'************Acumulados provinciales****************
    Act(Cp, MM, 1) = Act(Cp, MM, 1) + 1 'Acumula actuaciones.
    Act(Cp, MM, 2) = Act(Cp, MM, 2) + FF - FI 'Acumula duraciones
    Act(Cp, 13, 1) = Act(Cp, 13, 1) + 1 'Acum. act. Año
    Act(Cp, 13, 2) = Act(Cp, 13, 2) + FF - FI 'Acum. durac. año
'************Acumulados nacionales****************
Cp = 51
    Act(Cp, MM, 1) = Act(Cp, MM, 1) + 1
    Act(Cp, MM, 2) = Act(Cp, MM, 2) + FF - FI
    Act(Cp, 13, 1) = Act(Cp, 13, 1) + 1
    Act(Cp, 13, 2) = Act(Cp, 13, 2) + FF - FI

    End If

End If
Next
End With

With Sheets("resumen")
.UsedRange.Rows.Delete 'Elimina las lineas utilizadas
For I = 1 To 51 'Para cada una de las provincias y el total nacional
'.Range("a" & I + 1).Value = I
For J = 1 To 13 'Para cada mes
.Cells(I + 2, J * 2).Value = Act(I, J, 1)
If Act(I, J, 1) > 0 Then .Cells(I + 2, J * 2 + 1).Value = Act(I, J, 2) / Act(I, J, 1) 'Las duraciones medias son el total de duraciones/nºact. en donde N.Act debe ser mayor que cero, si no daría error.
Next
Next

For J = 1 To 13 ' Colocamos los literales 
.Cells(2, J * 2).Value = "N.Act."
.Cells(2, J * 2 + 1).Value = "D.Med."
.Columns(J * 2 + 1).Cells.NumberFormat = "[h]:mm"'Damos formato a la columna con d.m.
Next
.Range("a3:a53").Value = Sheets("prv").Range("b2:b52").Value 'Colocamos los nombres de las provincias
.Range("a1").Value = "Año:" & AProc 'informe del año 
.UsedRange.Columns.AutoFit
End With

With Sheets("aux")
.Cells.Clear
.Range("b1:n1").Value = Meses
.Range("a3:a53").Value = Prvs
End With
End Sub

*****************Fin código*******************
A este código le falta situar el nombre de los meses en la primera línea del informe. Lo he dejado así para que aquellos que estén interesados lo hagan por su cuenta. Como ejercicio de programación.