Imprimir página | Cerrar ventana

Validar registro

Impreso de: Foro de Access y VBA
Categoría: Access y VBA
Nombre del foro: Access y VBA
Descripción del foro: Foro de programacion en Access (Con código y sin código)
URL: http://www.mvp-access.com/foro/forum_posts.asp?TID=84859
Fecha de impresión: 20/Abril/2024 a las 05:26


Tema: Validar registro
Publicado por: maserrano
Asunto: Validar registro
Fecha de publicación: 27/Noviembre/2019 a las 13:00
Buenos días.
Sé, de antemano, que sobre el tema propuesto hay mucha literatura y muchos ejemplos, pero, no obstante planteo la siguiente duda.

Se trata de validar un campo y que muestre un aviso de que existe, de existir, y no haga el registro, o bien que te lleve a ese registro existente.

El problema lo planteo al ser un campo calculado el que se tiene que comprobar. Este campo se forma con los dos campos anteriores (de tipo texto corto) y no se forma lógicamente hasta que no se ha salido del segundo campo. No sé cómo se puede hacer esa comprobación para que diga que existe y vuelva al segundo de los campos para que introduzca una secuencia diferente.

La segunda posibilidad es renunciar al campo calculado y hacer un campo de texto (tipo texto corto) que venga calculado mediante un evento tipo AfterUpdate, con un Recordset que me coja los valores del campo 1 y 2 de una forma determinada. Hasta ese punto lo puedo hacer, pero después no puedo hacer que me verifique si ese registro ya existe y que entonces vuelva a preguntar por el campo 2.  

Más o menos sería algo así:

Private Sub valor2_AfterUpdate()

Dim Rst As Recordset, _
    Marcador As Variant
Set Rst = Me.RecordsetClone

Rst.FindFirst "Id= '" & Me.Id & "'"
If Not Rst.NoMatch Then
Me.Bookmark = Rst.Bookmark
Else
    Me!Id = Left(Me!valor1, 2) & "/" & Mid(Me!valor1, 3, 2) & "." & Mid(Me!valor1, 5, 3) & "-" & Right(Me!valor2, 3)
    DoCmd.RunCommand acCmdSelectRecord
End If

Rst.Close

End Sub

Pues se trata de eso, de si el campo Id existe, que no lo grabe y vuelva a pedir un nuevo valor del campo valor2.
Muchas gracias por adelantado.




Respuestas:
Publicado por: VIMIPAS
Fecha de publicación: 27/Noviembre/2019 a las 23:20
Hola buenas noches.

Tal vez con el evento de "Antes de actualizar" puedes comprobarlo:

Private Sub Texto5_BeforeUpdate(Cancel As Integer)

End Sub

En caso de que no corresponda, le dices Cancel=True y actúas en consecuencia, por ejemplo que no siga haciendo lo que debería hacer en el caso contrario.

Saludos.


-------------
Gracias


Publicado por: maserrano
Fecha de publicación: 28/Noviembre/2019 a las 00:31
Buenas VIMIPAS.
Lo he probado y me da error.
Error 3022 en tiempo de ejecución. Los cambios solicitados en la tabla no se realizaron... valores duplicados...
Explico lo que hasta ahora tengo:

Una tabla (T1) con 4 campos:
Id (autonumérico) contador
V1 (texto corto) un valor alfanumeico
V2 (texto corto) otro valor alfanumeico
V3 (texto corto) Valor formado a partir de los otros dos. Propiedad sin duplicados

Un formulario F1 con tres cuadros:
C1 (valor V1)
C2 (valor V2)
C3 (valor V3, a partir de los anteriores
En C2 tengo el evento:

Private Sub C2_AfterUpdate()

Dim Rst As Recordset, _
    Marcador As Variant
Set Rst = Me.RecordsetClone

Rst.FindFirst "C3= '" & Me.C3 & "'"
If Not Rst.NoMatch Then
   Me.Undo
   Me.Bookmark = Rst.Bookmark
Else
    Me!C3 = Left(Me!C1, 2) & "/" & Mid(Me!C1, 3, 2) & "." & Mid(Me!C1, 5, 3) & "-" & Right(Me!C2, 3)
    DoCmd.RunCommand acCmdSelectRecord
End If

Rst.Close

End Sub

Este código me genera el valor V3 en el campo C3.

Para que no me genere un registro que ya existe, en el campo C3 pongo el evento antes de actualizar (colaboración de VIMIPAS, no sé si he podido meter algo la pata):

Private Sub C3_BeforeUpdate(Cancel As Integer)
 If (Not IsNull(DLookup("[C3]", _
        "T1", "[V3] ='" _
        & Me!C3 & "'"))) Then
        MsgBox "El registro ya existe"
        Cancel = True
        Me!C3.Undo
    End If
End Sub

..., pues no me hace nada y me da el error anterior. 
En la depuración me marca la línea:

DoCmd.RunCommand acCmdSelectRecord

..., con lo que creo que intenta grabarlo y no puede por las propiedades  del campo de no permitir duplicados y no haciendo caso al evento de antes de actualizar.

Ahora ando perdido, por si alguien ve algo y me puede ayudar. 
Gracias ante todo.


Publicado por: guarracuco
Fecha de publicación: 28/Noviembre/2019 a las 05:40
Puedes controlar el error. Todo procedimiento debe llevar un tratamiento de errores

Private Sub C3_BeforeUpdate(Cancel As Integer)
On error goto lbl_error

 If (Not IsNull(DLookup("[C3]", _
        "T1", "[V3] ='" _
        & Me!C3 & "'"))) Then
        MsgBox "El registro ya existe"
        Cancel = True
        Me!C3.Undo
    End If

Lbl_exit:
Exit sub

lbl_error:
If err.number= 3022 then
   Cancel= true
Else
Msgbox err.description
End if
Resume lbl_exit
End Sub

Ojo:,escrito desde el dispositivo móvil




Publicado por: maserrano
Fecha de publicación: 28/Noviembre/2019 a las 08:03
Gracias guarracuco pero me sigue dando el mismo error.



Publicado por: pitxiku
Fecha de publicación: 28/Noviembre/2019 a las 14:58
Los eventos Antes y Después de Actualizar sólo se lanzan cuando es el usuario el que escribe en él control. Como al control C3 le asignas el valor mediante código VBA, nunca se lanzará su evento.

Tienes que usar él evento Antes de Actualizar de los otros controles.


Publicado por: maserrano
Fecha de publicación: 28/Noviembre/2019 a las 15:55
No lo entiendo muy bien pitxiku;
El valor V3 en el campo C3 sí se genera y asigna, con el evento "Después de actualizar".
Lo que no hace es comprobar si existe y, de existir, borrarlo y pasar al campo anterior C2 otra vez para asignarle un nuevo valor distinto.
Eso, creo, es lo que me genera el error.
Me lo puede explicar con un poco más de detalle?
Gracias.


Publicado por: pitxiku
Fecha de publicación: 28/Noviembre/2019 a las 20:22
En él Antes de Actualizar de C3 estás comprobando si ese dato esta guardado. Pero ese evento no se va a lanzar nunca, porque él valor de C3 lo estás componiendo mediante código en él evento Después de Actualizar de C2.

Pero este evento tampoco tiene mucha importancia, porque él error aparece en él otro, que se lanza antes: una de las primeras cosas que haces es buscar un registro en base a los que hay en C3, pero en C3 NO hay nada porque todavía no has generado él valor.

En él evento Después de actualizar de C2 tienes que:

1. Generar él código y guardarlo en una variable (todavía no en C3).

2. Buscar en los registros en base a lo que hayas guardado en la variable.

3. Si no encuentras, asignas a C3 él valor de la variable

4. Si lo encuentras, cancelas cambios y te posiciona en él registro.


Publicado por: maserrano
Fecha de publicación: 28/Noviembre/2019 a las 20:46
Me pongo a ello y luego comento.
Gracias


Publicado por: VIMIPAS
Fecha de publicación: 28/Noviembre/2019 a las 22:27
Hola de nuevo.

Tal cual dice Pitxiku, tu primero elaboras el C3 en base a c1&c2, pero con VBA.

De que sirve poner un evento que no se va usar.... si ya lo has puesto con VBA, no salta el evento. Tan solo saltan los eventos, habitualmente, cuando se pulsa dentro del control que estemos, una tecla o se actúe en dicho control con el ratón..... nunca salta directamente con VBA.

Yo te puse dicho evento, pensando que tu entrabas con tus "manos" a dicho control y hacías algo en el, tecleando o con el ratón.

Saludos.


-------------
Gracias


Publicado por: maserrano
Fecha de publicación: 28/Noviembre/2019 a las 23:44
Ok. Es perfecto. 
Gracias pitxiku; gracias VIMIPAS.
Realmente no sé si falta o sobra algo pero con el código que he puesto funciona de maravilla.

Private Sub C2_AfterUpdate()

Dim var As String
Dim Rst As Recordset, _
Marcador As Variant
Set Rst = Me.RecordsetClone

Me!C3 = Left(Me!C1, 2) & "/" & Mid(Me!C1, 3, 2) & "." & Mid(Me!C1, 5, 3) & "-" & Right(Me!C2, 3)
var = Me!C3
Rst.FindFirst "V3= '" & var & "'"

If Not Rst.NoMatch Then
   Me.Undo
   Me.Bookmark = Rst.Bookmark
   
End If

Rst.Close

If (Not IsNull(DLookup("[V3]", _
        "T1", "[V3] ='" _
        & var & "'"))) Then
        MsgBox "El registro ya existe"
        Cancel = True
        Me!C3.Undo

    Me.C3.Value = ""
    Me.C2.SetFocus
End If
    
End Sub


Muchas gracias de nuevo.


Publicado por: maserrano
Fecha de publicación: 29/Noviembre/2019 a las 11:33
Vaya!
No me he dado cuenta, pero el código comete un fallito...
Cuando encuentra un valor que ya existe en la tabla, me cambia de registro y va a ese registro y borra el campo C3.
Debe permanecer en el nuevo registro creado, borrar el campo C3 y pasar el foco a C2 para renombrar a C3.

No sé cómo hacer que permanezca en el nuevo registro creado; ahora lo único que puedo hacer es eliminar del código:

Me.C3.Value = ""

porque me quita ese valor que ya estaba creado en tabla.

Realmente, he seguido al completo el consejo de pitxiku:
4. Si lo encuentras, cancelas cambios y te posiciona en él registro.

..., realmente no quiero posicionarme en el registro; sólo saber que existe y que me permita renombrar el valor de C2 (y así crear un C3 que no exista). En fin...

Alguna sugerencia ??


Publicado por: pitxiku
Fecha de publicación: 29/Noviembre/2019 a las 15:06
Desde tu primer código tienes esto:

If Not Rst.NoMatch Then
     Me.Bookmark = Rst.Bookmark

So no quieres posicionarte en un registro ya existente, para qué lo tienes?

Toma lápiz y papel, escribe a mano qué quieres que haga tu código, y luego crea él código en access, es mucho más sencillo.


Publicado por: maserrano
Fecha de publicación: 30/Noviembre/2019 a las 01:09
Oído cocina.
Buen mensaje lo de pensar.
..., con quitarlo bastaba.
Salu2 y gracias.


Publicado por: maserrano
Fecha de publicación: 01/Diciembre/2019 a las 00:47
Perdón no me di cuenta de mencionar que el hilo se puede cerrar. 



Imprimir página | Cerrar ventana