Está en la página 1de 6

DATOS REGISTRO ANTERIOR1

En algunas ocasiones podría ser que necesitáramos conocer


u operar con los datos de un registro anterior. En este
ejemplo se explica cómo podemos conseguirlo guiándonos
por un autonumérico.

Alguien podría pedirme:¿qué significa eso de que “nos


guiamos por un autonumérico”? Pues simplemente significa
que nuestros registros deben estar ordenados; dicho en
otras palabras, que no podemos introducir un registro que
necesita los datos del anterior sin haber introducido antes
ese registro anterior.

Evidentemente disponemos de mecanismos para controlar la entrada del usuario y que no se


produzca esta situación “conflictiva”. Voy a dividir este ejemplo en dos bloques, y en el
segundo os enseñaré una manera de efectuar ese control.

En el primer bloque os enseñaré cómo obtener los datos de una introducción llamémosle
“lineal”; esto es, los datos siempre dependen del registro anterior.

En el segundo bloque trataremos una introducción llamémosle “no lineal”; esto es, los datos no
dependen siempre del registro inmediatamente anterior, sino que hay algún elemento que nos
delimita un subgrupo de registros.

El primer bloque contendrá el grueso de la explicación y creo conveniente que lo entendáis,


dado que si se entiende no habrá ningún problema para entender la segunda parte. Será
también en esta segunda parte donde os explicaré un truco para ese “control” que os
comentaba unas líneas más arriba. Ese truco se basará en un campo tipo fecha.

Y como creo que ya se tiene una panorámica general de lo que se pretende vamos a ponernos
manos a la obra.

BLOQUE 1

FINALIDAD DEL EJEMPLO


Imaginemos que queremos saber cuántos días transcurren entre entregas de una mercancía.
Lógicamente vamos a necesitar saber cuál fue la última fecha de entrega, y eso nos lo da el
registro anterior al que estamos introduciendo.

MI TABLA
Vamos a crearnos una tabla muy simple que llamaremos TEntregas, con la siguiente
estructura:

1 La BD de ejemplo os la podéis bajar aquí

1
Visítame en http://neckkito.siliconproject.com.ar
MI FORMULARIO
Vamos a crearnos un formulario sobre esa tabla, que
llamaremos FEntregas. Este paso no tiene el más mínimo
secreto.

A mí me ha quedado una cosa así:

Si queréis que nadie “haga trampas” podéis sacar las propiedades del campo
[DiasTranscurridos] → Pestaña Datos → Bloqueado = Sí.

EL CÓDIGO
Vamos a plantearnos el código antes de escribirlo.

En primer lugar lo lógico sería pensar que:


1.- Escribimos una fecha de entrega
2.- Calculamos los días transcurridos
3.- Escribimos el resultado en el campo [DiasTranscurridos]

Sin embargo, también debemos plantearnos cómo resolver una situación particular: ¿qué pasa
si es el primer registro que introducimos? Porque, en este caso, no habrá ninguna fecha
anterior.

Ok. Tenemos pues ya “cogidas por el cuello” las dos situaciones posibles. Sigamos con la
siguiente pregunta: ¿cómo decirle a Access que me coja el registro anterior?

Alguien podría pensar: como tengo un autonumérico, pues lo que hago es coger el
autonumérico del registro actual, supongamos 5, y sé automáticamente que el anterior es el 4.

Si bien ese planteamiento es totalmente lógico lamentablemente no es válido, dado que


imaginemos que, por el motivo que sea, hemos borrado el registro con identificador igual a 4.
Eso significaría que Access nunca nos encontraría el registro 4, dado que no existe.

2
Visítame en http://neckkito.siliconproject.com.ar
Veamos, de manera abstracta, las soluciones que adoptaremos:

a) Buscaremos el valor máximo del Id que tengamos en la


tabla a través de la función DMax(), pero excluyendo el
registro en el que estamos.

Con ello, si tenemos los registros 1, 2, 5, 8, y estamos en el


10, el máximo sería 10, pero como lo excluimos el máximo
es el 8, que coincide con nuestro registro anterior.

b) Aprovecharemos, ya que buscamos el valor máximo,


para controlar si, efectivamente DMax() nos devuelve algún
valor. Eso lo haremos a través de la función Nz()

Si estamos introduciendo el registro 1, ¿cuál será el valor máximo (excluyendo el 1)? Pues no
hay valor máximo, lo que implica que estaremos en un registro inicial.

La plasmación de lo anterior en un código sería:

 Búscame el máximo Id excluyendo el registro en el que estoy


 Si no devuelves valor → estamos en un registro inicial → Los días serán 0
 Si devuelves valor → haremos que el DMax() nos devuelva la fecha del registro anterior,
restaremos fechas y escribiremos el resultado.

El código lo activaremos cuando se haya escrito la fecha de entrega, y eso se hace en el


evento “Después de actualizar” del campo [FechaEntrega]2

Así pues el código que generaremos en dicho evento será el siguiente:


Private Sub FechaEntrega_AfterUpdate()
Dim regAnterior As Variant 'Variant porque le haremos tomar o bien un valor
'numérico o un valor de fecha, según el caso

'Si no se ha escrito ninguna fecha salimos sin hacer nada


If IsNull(Me.FechaEntrega.Value) Then Exit Sub

'Buscamos la fecha del registro anterior; esto es, del registro


'que tiene el Id más alto excluyendo el del registro en el que estamos
regAnterior = Nz(DMax("FechaEntrega", "TEntregas", "Id<" & Me.Id.Value), 0)

'Si es el primer registro la función Nz() hace que regAnterior tome el


'valor 0. Eso significa que estamos en el primer registro
If regAnterior = 0 Then
'Escribimos el valor en el campo [DiasTranscurridos]
Me.DiasTranscurridos.Value = regAnterior
Else 'En caso contrario restamos fechas
Me.DiasTranscurridos.Value = Me.FechaEntrega.Value - regAnterior
End If
End Sub

Como podéis ver el código está comentado y recoge lo que antes hemos expresado “en
abstracto”.

2 Para generar código debemos sacar las propiedades del control → Pestaña Eventos, y nos situamos en la parte “blanca” a la
derecha del evento que queremos programar. Veremos un pequeño botón de puntos suspensivos. Si hacemos clic sobre él nos
aparecerá una ventana que nos pedirá qué operación deseamos realizar. Le indicamos que queremos “generar código”.

3
Visítame en http://neckkito.siliconproject.com.ar
BLOQUE 2
Vamos a seguir con nuestra tabla, pero vamos a copiar
FEntregas y lo vamos a pegar como FEntregas2.

¿Y cuál va a ser la finalidad de esta segunda parte?

Como comentaba en la introducción, ahora hay un elemento


que nos condiciona el orden de los registros. En el bloque 1
mirábamos los días transcurridos entre entrega y entrega;
en este segundo bloque el elemento condicionador va a ser
el transportista, y lo que queremos obtener son los días
transcurridos entre entrega y entrega de cada uno de los
transportistas.

Dicho más claro: si tenemos estos datos:

Seur → Entrega el 01/01/15


DHL → Entrega el 05/01/15
Seur → Entrega el 15/01/15

Lo que queremos saber es cuántos días ha tardado sólo Seur en entregarnos la mercancía, así
que el resultado sería 14 días (del 01/01 al 15/01, sin tener en cuenta la entrega de DHL).

En realidad el proceso es el mismo que hemos aplicado en la explicación del bloque 1, sólo que
ahora debemos “añadir” ese elemento diferenciador (el repartidor) en el proceso.

Así que en el campo [FechaEntrega] de FEntregas2 vamos a cambiar el código que tenemos
por el que sigue:


Private Sub FechaEntrega_AfterUpdate()
Dim regAnterior As Variant 'Variant porque le haremos tomar o bien un valor
'numérico o un valor de fecha, según el caso

'Si no se ha escrito ninguna fecha salimos sin hacer nada


If IsNull(Me.FechaEntrega.Value) Then Exit Sub

'Si no hay repartidor avisamos y salimos


If IsNull(Me.Repartidor.Value) Then
MsgBox "Debe indicar un repartidor", vbInformation, "SIN DATOS"
Exit Sub
End If

'Buscamos la fecha del registro anterior; esto es, del registro


'que tiene el Id más alto excluyendo el del registro en el que estamos
'Aquí incluimos el efecto del transportista, en la parte del filtro
regAnterior = Nz(DMax("FechaEntrega", "TEntregas", "Repartidor='" & Me.Repartidor.Value _
& "' AND Id<" & Me.Id.Value), 0)

'Si es el primer registro de ese repartidor la función Nz() hace que regAnterior tome el
'valor 0. Eso significa que estamos en el primer registro
If regAnterior = 0 Then
'Escribimos el valor en el campo [DiasTranscurridos]
Me.DiasTranscurridos.Value = regAnterior
Else 'En caso contrario restamos fechas
Me.DiasTranscurridos.Value = Me.FechaEntrega.Value - regAnterior
End If
End Sub

Os he marcado en negrita los cambios respecto del código del bloque 1

4
Visítame en http://neckkito.siliconproject.com.ar
Fijaos también que he añadido un control para verificar que
el repartidor existe, porque si no el código nos daría error.

CONTROL DE “TRAMPAS” DEL USUARIO


Para este ejemplo, el usuario podría intentar introducir una
fecha anterior a la del último registro. Para ello podríamos
introducir un control previo de comprobación y obligarle a
rectificar el dato.

En la BD de ejemplo que acompaña a este texo lo anterior está reflejado en el formulario


FEntregas3.

El código sería el siguiente:


Private Sub FechaEntrega_AfterUpdate()
Dim regAnterior As Variant 'Variant porque le haremos tomar o bien un valor
'numérico o un valor de fecha, según el caso

'Si no se ha escrito ninguna fecha salimos sin hacer nada


If IsNull(Me.FechaEntrega.Value) Then Exit Sub

'Si no hay repartidor avisamos y salimos


If IsNull(Me.Repartidor.Value) Then
MsgBox "Debe indicar un repartidor", vbInformation, "SIN DATOS"
Exit Sub
End If

'Buscamos la fecha del registro anterior; esto es, del registro


'que tiene el Id más alto excluyendo el del registro en el que estamos
'Aquí incluimos el efecto del transportista, en la parte del filtro
regAnterior = Nz(DMax("FechaEntrega", "TEntregas", "Repartidor='" & Me.Repartidor.Value _
& "' AND Id<" & Me.Id.Value), 0)

'Si es el primer registro de ese repartidor la función Nz() hace que regAnterior tome el
'valor 0. Eso significa que estamos en el primer registro
If regAnterior = 0 Then
'Escribimos el valor en el campo [DiasTranscurridos]
Me.DiasTranscurridos.Value = regAnterior
Else 'En caso contrario restamos fechas, pero antes controlamos que todo sea correcto
If Me.FechaEntrega.Value < regAnterior Then 'La fecha introducida es menor que la del registro
anterior
MsgBox "La fecha introducida no es correcta, dado que es inferior a la última registrada para" _
& " el repartidor " & Me.Repartidor.Value & ", que es " & regAnterior & vbCrLf & vbCrLf _
& "Debe cambiar la fecha", vbExclamation, "FECHA INCORRECTA"
Me.FechaEntrega.Value = Null
Exit Sub
Else
Me.DiasTranscurridos.Value = Me.FechaEntrega.Value - regAnterior
End If
End If
End Sub

UNOS APUNTES DE ÚLTIMA HORA


El ejemplo está desarrollado para obtener la fecha, pero imaginemos que queremos obtener
los datos del registro anterior en función del campo [X]. ¿Cómo lo hacemos?

Pues la sistemática general sería exactamente la misma que la que os he explicado. Sólo

5
Visítame en http://neckkito.siliconproject.com.ar
tendríamos que ajustar, básicamente:

 Que el valor retornado sea el del campo [X], y eso lo


hacemos llamándolo en la función DMax(), así:

regAnterior = Nz(DMax("X", "TEntregas", "Id<" & Me.Id.Value), 0)

 El ejemplo devuelve los días entre fechas. Deberíamos


sustituir ese bloque de código por los cálculos que nosotros
necesitemos.

Como la casuística en este caso es muy amplia sólo puedo


daros estas “recomendaciones generales”.

PARA FINALIZAR EL EJEMPLO


Bueno… Espero que se haya entendido bien la manera de “pillar” los datos que queramos del
último registro y que, si lo necesitáis para vuestra aplicación, sepáis adaptar los códigos sin
problemas.

Un saludo, y…

¡suerte!

6
Visítame en http://neckkito.siliconproject.com.ar

También podría gustarte