Mostrando entradas con la etiqueta Eventos. Mostrar todas las entradas
Mostrando entradas con la etiqueta Eventos. Mostrar todas las entradas

lunes, 9 de marzo de 2020

Lanzar una macro al producirse un evento de tipo Change

Puede descargar el archivo target.xlsm

Hoja 1


Vamos a crear el rango de color amarillo donde al escribir algo se lance automáticamente una macro que nos saluda. Esto se consigue con la programación por eventos que tiene Excel.


Primero programamos la macro 'saluda' en un módulo de nuestro editor de Visual Basic (VBA).


 Sub saluda()  
 MsgBox ("Hola, ¿qué tal?")  
 End Sub  

Luego nos vamos a la zona de programación para la Hoja1 que es en la que nos encontramos y creamos un evento de tipo Change. Es el siguiente.


 Private Sub Worksheet_Change(ByVal Target As Range)  
 Dim R As Range  
 Set R = Range("$B$6:$B$8")  
 If Intersect(Target, R) Is Nothing Then  
  Application.EnableEvents = False  
  Target.Value = UCase(Target.Value)  
  Application.EnableEvents = True  
  Target.Font.ColorIndex = 5  
 Else  
  If Target.Value > 1000 Then  
   Target.Font.ColorIndex = 3  
  Else  
   Target.Font.ColorIndex = 0  
  End If  
  saluda  
 End If  
 End Sub  



Hoja 2

Otro método para poder actuar sobre un rango concreto consiste en definir el rango indicando las columnas y filas en las que se encuentra.


 Private Sub Worksheet_Change(ByVal Target As Range)  
 If Target.Column = 2 And Target.Row >= 5 And Target.Row <= 8 Then  
  [E5] = Application.WorksheetFunction.Sum(Range("B5:B8"))  
 End If  
 End Sub  

miércoles, 5 de agosto de 2015

Préstamo a tipo variable con AA que reduce la duración

Puede descargar el fichero AA_reduce_tiempo.xlsm

Hoja0


Supongamos un préstamo a tipo variable sobre el que podemos efectuar aportaciones adicionales en forma de Amortización Anticipada (AA) para reducir la duración total del préstamo. Las mensualidades no disminuyen por el hecho de haber amortizado anticipadamente, sino que siguen su evolución prevista incluso con variaciones ante cambios en el tipo de interés aplicado. Lo que cambia es la duración total del préstamo, que se acorta al incidir la AA en la reducción del Capital Vivo.



Para resolver este caso necesitamos elaborar tres cuadros de amortización:
  1. Cuadro de amortización 1. Representa la evolución del préstamo sin considerar que se pueden efectuar pagos adicionales con concepto de AA.
  2. Cuadro de amortización 2. La mensualidad se obtiene copiando la del cuadro 1. El resto del cuadro se calcula y se añade la columna de AA. Al incluir importes en la AA se consigue que en los periodos finales se obtengan capitales vivos negativos.
  3. Cuadro de amortización 3. Es igual que el cuadro 2 salvo por que los últimos periodos con capitales vivos negativos desaparecen, salvo la fila donde aparece el primer capital vivo negativo. En esa fila, se han de realizar los ajustes necesarios para amortizar únicamente lo necesarios para que el capital vivo sea cero y el capital amortizado en ese mes sea justo igual al principal del préstamo.
La tabla del Euribor muestra únicamente el número de periodos necesarios según los años que hemos indicado previamente en la celda amarilla de los años.


Lo mismo sucede con los tres cuadros de amortización que muestran únicamente el número de meses necesarios según los años de duración de préstamo. Para 5 años muestran 60 meses.



El tercer cuadro es el definitivo y en él se muestran únicamente los meses necesarios para la amortización del préstamo. Se puede observar que en este ejemplo hemos pasado de los 60 meses iniciales, ya que se indicó una duración de 5 años, a los 26 meses totales que dura el préstamo debido a la fuerte reducción que supone haber realizado las dos amortizaciones anticipadas, una de 120.000 € y otra de 170.000 €.


En el último mes del cuadro 3 se ha de ajustar el importe amortizado para que justamente se llegue a amortizar el principal. Observe que la última mensualidad es inferior a la de su año debido a este ajuste.

Hoja1


El caso de la Hoja0 se resolvió usando fórmulas hasta el año 50, que se ocultan o se ven según el número de años que indiquemos en los datos. En la Hoja1 proponemos una solución que no utiliza fórmulas ya escritas en la hoja de cálculo sino que el cuadro de amortización se crea por parte de una macro que actúa de forma automática al variar los datos de las celdas amarillas, que son donde introducimos los datos del caso práctico.




Sub Euribor()
Dim edad As Double
Dim lista As Byte 'da el nº de años enteros
Dim i As Integer, n As Byte
Dim A
Application.Calculation = xlManual
Worksheets("Hoja1").Activate
edad = Range("C5")
If Int(edad) - edad = 0 Then
   lista = edad
Else
   lista = Int(edad) + 1
End If

Range("B10").Select
Selection.CurrentRegion.Select
n = Selection.Rows.Count - 1
[A] = Range("C11:C" & n + 10).Value

Range("B" & lista + 11 & ":E60").Clear

Range("B11:E11").Copy
Range("B11:E" & lista + 10).Select
ActiveSheet.Paste

For i = 11 To WorksheetFunction.Min(lista + 10, n + 10)
   Cells(i, "C") = A(i - 10, 1)
Next i

For i = 1 To lista
   Cells(i + 10, "B") = i
Next i
Application.CutCopyMode = False
Range("C5").Select
Application.Calculation = xlAutomatic
End Sub
Sub Genera()
Dim i As Integer, j As Integer
Dim A() As Double 'para la tabla del Euribor
Dim B() As Double 'para los cuadros de amortización
Dim n As Byte, m As Integer
Dim ultimo As Integer
Dim aqui As String
Worksheets("Hoja1").Activate
n = Range("C5").Value 'años
m = Range("C6").Value 'meses
ReDim A(2, n)
ReDim B(2, 9, m) 'Cuadro, columna, fila
For i = 1 To n
   A(1, i) = Cells(i + 10, "C").Value 'toma el Euribor
   A(2, i) = (A(1, i) + Range("C7").Value) / 12  'Calcula i12
Next i
B(1, 6, 0) = Range("C4").Value
B(2, 6, 0) = Range("C4").Value
Range("M11") = Range("C4").Value
For i = 1 To m
   B(1, 1, i) = Int((i - 1) / 12) + 1 'año
   For j = 1 To n
      If B(1, 1, i) = j Then B(1, 2, i) = A(2, j) 'Tipo int. mensual
   Next j
   'B(1, 3, i) = WorksheetFunction.Pmt(B(1, 2, i), m - i + 1, -B(1, 6, i - 1))
   B(1, 3, i) = B(1, 6, i - 1) / ((1 - ((1 + B(1, 2, i)) ^ -(m - i + 1))) / B(1, 2, i)) 'mensualidad
   B(1, 4, i) = B(1, 6, i - 1) * B(1, 2, i) 'intereses
   B(1, 5, i) = B(1, 3, i) - B(1, 4, i) 'amortización
   B(1, 6, i) = B(1, 6, i - 1) - B(1, 5, i) 'Cap. Vivo
   B(1, 7, i) = B(1, 7, i - 1) + B(1, 5, i) 'Cap. amort.
   B(1, 7, i) = Cells(i + 11, 15) 'AA

   'Cuadro 2
   B(2, 2, i) = B(1, 2, i)
   B(2, 3, i) = B(1, 3, i) + B(1, 7, i) 'nueva mensualidad
   B(2, 4, i) = B(2, 6, i - 1) * B(2, 2, i) 'intereses
   B(2, 5, i) = B(2, 3, i) - B(2, 4, i) 'amortización
   B(2, 6, i) = B(2, 6, i - 1) - B(2, 5, i) 'Cap. Vivo
   B(2, 7, i) = B(2, 7, i - 1) + B(2, 5, i) 'Cap. amort.
   B(2, 8, i) = Cells(i + 11, 15) 'AA
   
   If B(2, 6, i) <= 0 And B(2, 6, i - 1) > 0 Then ultimo = i 'último mes
Next i

'Borrar
   aqui = ActiveCell.Address
   Range("G" & ultimo + 12 & ":O613").Clear
   Range(aqui).Select
    
'Cuadro 3
For i = 1 To ultimo - 1
   Cells(i + 11, 7) = i 'mes
   Cells(i + 11, 8) = B(1, 1, i) 'año
   Cells(i + 11, 9) = B(2, 2, i) 'Tasa i12
   Cells(i + 11, 10) = B(2, 3, i) 'mensualidad
   Cells(i + 11, 11) = B(2, 4, i) 'intereses
   Cells(i + 11, 12) = B(2, 5, i) 'amortización
   Cells(i + 11, 13) = B(2, 6, i) 'Cap. Vivo
   Cells(i + 11, 14) = B(2, 7, i) 'Cap. amort.
Next i
   Cells(ultimo + 11, 7) = ultimo 'mes
   Cells(ultimo + 11, 8) = B(1, 1, ultimo) 'año
   Cells(ultimo + 11, 9) = B(2, 2, ultimo) 'Tasa i12
   
   Cells(ultimo + 11, 11) = B(2, 4, ultimo) 'intereses
   Cells(ultimo + 11, 12) = B(2, 6, ultimo - 1) 'amortización
   Cells(ultimo + 11, 13) = 0 'Cap. Vivo
   Cells(ultimo + 11, 14) = B(2, 7, ultimo - 1) + B(2, 6, ultimo - 1) 'Cap. amort.
   Cells(ultimo + 11, 10) = B(2, 4, ultimo) + B(2, 6, ultimo - 1) 'mensualidad

'Formato
   aqui = ActiveCell.Address
   Range("G12:O12").Copy
   Range("G12:O" & ultimo + 11).PasteSpecial Paste:=xlPasteFormats
   Application.CutCopyMode = False
   Range(aqui).Select
End Sub


Para automatizar el recálculo automático del cuadro de amortización al cambiar los años contamos con una macro que controla el evento Change que actúa ante cambios en el Target que es la celda C5, donde introducimos los años. Las macros de este tipo no se encuentran en los módulos sino que se han de colocar en el la zona del Editor de VBA que hace referencia a la hoja con la que estamos trabajando.

Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$C$5" Then
   Euribor
   Genera
End If
If Target.Column = 15 And Target.Row >= 12 And Target.Row <= 611 Then
   Genera
End If
End Sub

lunes, 18 de mayo de 2015

El evento SelectionChange

Archivo de Excel utilizado: SelectionChange.xlsm

Vamos a crear un caso práctico sencillo que nos permitirá comprender cómo funciona el evento SelectionChange. Primero veamos lo que es un Evento.

Programación por Eventos

En muchos de los lenguajes de programación modernos existe la denominada programación por eventos que permite lanzar procedimientos cuando se detecta que ha sucedido un evento. Los eventos pueden ser de muchos tipos y dependen del lenguaje utilizado. Por ejemplo, un evento puede ser pulsar una vez el ratón, o pulsar dos veces sobre el ratón, o pulsar sobre el botón derecho, o escribir en una celda, o actualizar la hoja de cálculo, o ir a otra hoja. En otros lenguajes, un evento podría ser pasar el cursor del ratón sobre un banner que hace que la publicidad que contiene se agrande o que comience un vídeo o un sonido.

En Excel se están aumentando los eventos disponibles en cada versión, en especial los relacionados con Tablas dinámicas. En Excel 2010 son los siguientes.


El evento Worksheet.SelectionChange

El evento Worksheet.SelectionChange nos permite lanzar un procedimiento cada vez que seleccionamos un rango de celdas diferente.

Caso práctico

El caso práctico que planteamos consiste en proporcionar en una celda la suma de los valores numéricos que contengan el rango que seleccionemos. De tal forma que al ir cambiando la selección inmediatamente y sin lanzan ninguna macro por nuestra parte en la celda D4 (de color amarillo) nos de continuamente el valor de la suma de los elementos seleccionados.



La programación del evento es la siguiente que se debe colocar en la zona de código correspondiente a la Hoja1 que es donde están los elementos que deseamos sumar.

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim celda As Range
Dim suma As Double
For Each celda In Target
  If IsNumeric(celda) Then
    suma = suma + celda.Value
  End If
Next
[D4] = suma
End Sub

domingo, 11 de diciembre de 2011

Fechador: da la fecha al cambiar un dato

Descargar el fichero: fechador.xlsm

Fechador contiene una macro que establece la fecha y la hora junto a cierta celda cuando ésta experimenta cambios. Esto se logra manejando los eventos, concretamente el evento Change que detecta cuando se produce un cambio en alguna celda de una hoja. Podemos ejecutar la macro cuando el cambio se produzca en todas las celdas, o bien únicamente en una de ellas, o en un rango, y esto lo conseguimos manejando el target. Veamos cómo se hace.

Hoja 1



Al escribir en cualquier celda de la columna D, y en particular en las celdas verdes, y bajo ellas, al pulsar INTRO, automáticamente se anotará en la celda de la derecha la fecha y hora actuales, siempre que su ordenador esté correctamente puesto en fecha y hora.

Esto se consigue con una pequeña macro que se ha de escribir, no en un Módulo como es habitual al programar macros, sino en la Hoja1. Vea la siguiente imagen. Por cierto, para pasar de un elemento a otro de los de la imagen, o de un módulo a otro, no basta con hacer click con el ratón, se ha de hacer doble click.



Al situarnos dentro del Editor de Visual Basic en la Hoja1, a la derecha aparecerá la posibilidad de manejar dos desplegables. Hemos de elegir "Worksheet" en el de la izquierda y "Change" en le de la derecha.


Código:

Private Sub Worksheet_Change(ByVal Target As Range)
Application.MoveAfterReturn = False
If Target.Count = 1 Then
  If (Target.Column = 4 And Target <> 0) Then
    Target.Offset(0, 1) = Now
  End If
End If
End Sub


Hoja 2

Nos situamos ahora en la Hoja 2. En este caso pretendemos que se indique la fecha y la hora de forma automática en la columna E, siempre que se efectúen anotaciones o cambios en cualquier celda del rango B7:D20.



Vamos al Editor de Visual Basic, y en el Explorador de Proyectos nos situamos en la Hoja2. Para ello debemos pulsar doble click sobre la Hoja2, tal y como se muestra en la siguiente imagen.



En este caso la macro cambia ligeramente.

Código:

Private Sub Worksheet_Change(ByVal Target As Range)
Application.MoveAfterReturn = False
If Target.Count = 1 Then
  If Not Intersect(Target, Range("B5:D39")) Is Nothing Then
    Cells(Target.Row, "E") = Now
  End If
End If
End Sub

sábado, 6 de marzo de 2010

Actualización automática de una Tabla Dinámica

Descargar el fichero: tdauto.xlsm

Automatizar la actualización de una Tabla Dinámica es posible creando una pequeña macro, que se lanza cuando se produce un evento. Esto es lo que se denomina programación por eventos. En este caso el evento consiste en actualizar alguna cifra de un campo concreto de la base de datos. Si se modifica cualquier otro dato de la base de datos la tabla dinámica no se actualiza, aunque sería fácil programarlo para que se actualizara al cambiar cualquier dato.


Elegimos la columna D que corresponde en la base de datos al campo "VENTAS".  Cualquier modificación en las ventas de alguno de los comerciales automáticamente quedará reflejada en la Tabla Dinámica.

El código utilizado ha sido el siguiente.

Código:

Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Column = 4 Then
   ActiveSheet.PivotTables("Tabla dinámica1").PivotCache.Refresh
End If
End Sub


Si lo que deseas es que la Tabla Dinámica se actualice ante cualquier variación en el rango B4:E39, podrías indicárselo a Excel de esta forma.
Código:

Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("B5:E39")) Is Nothing Then
   ActiveSheet.PivotTables("Tabla dinámica1").PivotCache.Refresh
End If
End Sub


Existe otra alternativa para cuando el Target es un rango. Se trata de indicar las filas y columnas que deseamos que se controlen.
Código:

Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Column >= 2 And Target.Column <= 5 And _
Target.Row >= 5 And Target.Row <= 39 Then
   ActiveSheet.PivotTables("Tabla dinámica1").PivotCache.Refresh
End If
Cuando el Target es una única celda el condicional se puede escribir así:

If Target.Address="$A$1" Then

Al escribir la celda incluir los dólares y escribir en mayúsculas.