Problema con el recordset al pulsar los botones buscar, siguiente y atrás

Tengo un problema al mover todo el recorset con los botones siguiente, buscar y atrás; es decir, que si estoy en un registro y por error o a propósito le cambio el texto al textbox y le doy a cualquiera de los botones mencionados lo que hace es grabar el registro con el error pese a que no es el botón guardar o modificar. Todos los textbox los tengo relacionados al origen del campo como se muestra en la imagen:

Anteriormente lo tenía sin origen del control pero me borraba todos los datos que le incluyera con los botones atrás adelante y buscar, además de que el botón buscar no trae todo el registro si no están relacionados al origen los textbox y los combobox. La función con la que se mueve el recorset hacia adelante y hacia atraas, es la siguiente:

'mueve registro por registro de la interfaz hacia adelante
Private Sub cmd_Siguiente_Click()

Recordset.MoveNext
If Recordset.EOF Then Recordset.MoveLast: MsgBox "Último Registro", vbInformation, "Clientes"
id_vdi = Recordset.Fields("id_vdi")
nivel_validacion = Recordset.Fields("nivel_validacion")
estatus = Recordset.Fields("estatus")
prefijo = Recordset.Fields("prefijo")
apellido_paterno = Recordset.Fields("apellido_paterno")
apellido_materno = Recordset.Fields("apellido_materno")
nombre_1 = Recordset.Fields("nombre_1")
nombre_2 = Recordset.Fields("nombre_2")
especialidad = Recordset.Fields("especialidad")
subespecialidad = Recordset.Fields("subespecialidad")
fecha_nacimiento = Recordset.Fields("fecha_nacimiento")
edad = Recordset.Fields("edad")
email_1 = Recordset.Fields("email_1")
email_2 = Recordset.Fields("email_2")
email_3 = Recordset.Fields("email_3")
telefono_movil = Recordset.Fields("telefono_movil")
hobbie = Recordset.Fields("hobbie")
publica_revistas = Recordset.Fields("publica_revistas")
ponente_congresos = Recordset.Fields("ponente_congresos")
Me.clave_vdi_1.Visible = True
Me.clave_vdi_fk.Visible = False
Me.cbo_estatus = ""
cmd_Guardar.Enabled = False
cmd_Modificar.Enabled = True
End Sub

Lo que necesito es que se pueda navegar en el formulario y que si borro o cambio un campo de texto por accidente no quede grabado moviendo los botones adelante y atras.

Necesito de su apoyo para este caso.

1 Respuesta

Respuesta
1

A mi modo de ver, estás mezclando conceptos. Verás: la idea de cargar los datos en un formulario por medio de un recordset solo tiene sentido si el formulario es independiente, es decir, si sus controles están desligados de la tabla. De esta forma, los datos los controlas con el recordset, avanzando y retrocediendo con códigos como el tuyo, y guardando los datos con las propiedades .Edit y .Update del recordset.

En tu caso, como el formulario está vinculado directamente a la tabla, cualquier cambio que hagas te queda registrado en ese mismo momento.

La solución a tu problema pasa por desvincular el formulario de la tabla.

Te dejo los enlaces a unos ejemplos que preparé para la web de Neckkito sobre manejo de formularios independientes (es una forma de las muchas que hay):

http://siliconproject.com.ar/neckkito/index.php/component/content/article/93-ejemplos-explicados/ejemplos-de-formularios/286-datos-en-formularios-independientes-1 

http://siliconproject.com.ar/neckkito/index.php/component/content/article/93-ejemplos-explicados/ejemplos-de-formularios/287-datos-en-formularios-independientes-2 

http://siliconproject.com.ar/neckkito/index.php/component/content/article/93-ejemplos-explicados/ejemplos-de-formularios/289-datos-en-formularios-independientes-3 

Un saludo.


Hola,

Gracias por tu respuesta y ... si me puedes apoyar con lo siguiente:

El motivo de ligar los componentes a la tabla es precisamente porque el buscador no realiza su función si no está ligado, entonces ligué los campos para efectos de que el buscador me traiga completo el registro que esté buscando. Ahora bien, hice un buscador que me traía todo a través del recordset, aunque sí me traía el registro que necesitaba no funcionaba como lo quiero ya que se posicionaba por ejemplo: si estoy en el registro 1 y requiero el registro 439 y al pulsar el botón de búsqueda (programado con sentencia SQL y recordset) me posicionaba en el registro 439, pero al dar siguiente o atrás simplemente me regresaba al 1 o 2 dependiendo del botón. Lo que hice fue ligar los campos para poner un command_1 con una macro de búsqueda y es aquí donde surge el nuevo problema que es: Ahora si me posiciona en el registro 439 y al dar siguiente y atrás me da el 438 o 440 pero si por error escribo algo en algún campo aunque no lo grabe se graba.

¿Me puedes apoyar con un buscador que traiga el registro completo y que se posicione correctamente en los registros consecutivamente? Tiene que ser con botón forzosamente porque así lo requiere mi usuario.

Como siempre, agradezco profundamente tu apoyo y consejos.

Saludos

¿Cómo es el código que usas para buscar?

Actualmente lo hago con una macro de access, te muestro la imagen:

Anteriormente lo hacía con el siguiente código:

'estructura de datos que permite la búsqueda de algún registro según su clave de vdi
Private Sub btn_buscar_vdi_Click()
'declaramos las variables de conexión a la base de datos con DAO y string
Dim mySql As String
Dim dbs As DAO.Database
Dim rst As DAO.Recordset
'este es un atrapador de errores
On Error GoTo Err_SinData

'realizamos la consulta sql
mySql = "SELECT * FROM Tabla1 WHERE id_vdi_master = '" + id_vdi_master.Value + "';"
'iniciamos la base de datos, el recordset y el snapshot
Set dbs = CurrentDb
Set rst = dbs.OpenRecordset(mySql, dbOpenSnapshot)
'Asignamos el valor al TextBox
id_vdi = rst.Fields("id_vdi").Value
id_vdi_master = rst.Fields("id_vdi_master").Value
clave_vdi_fk = id_vdi_master
nivel_validacion = rst.Fields("nivel_validacion").Value
estatus = rst.Fields("estatus").Value
prefijo = rst.Fields("prefijo").Value
apellido_paterno = rst.Fields("apellido_paterno").Value
apellido_materno = rst.Fields("apellido_materno").Value
nombre_1 = rst.Fields("nombre_1").Value
nombre_2 = rst.Fields("nombre_2").Value
especialidad = rst.Fields("especialidad").Value
subespecialidad = rst.Fields("subespecialidad").Value
fecha_nacimiento = rst.Fields("fecha_nacimiento").Value
edad = rst.Fields("edad").Value
email_1 = rst.Fields("email_1").Value
email_2 = rst.Fields("email_2").Value
email_3 = rst.Fields("email_3").Value
telefono_movil = rst.Fields("telefono_movil").Value
Me.clave_vdi_fk.Visible = True
Me.clave_vdi_1.Visible = False
Me.id_vdi_master = ""
'Cerramos el recordset y liberamos memoria
rst.Close
dbs.Close
Set rst = Nothing
Set dbs = Nothing
'salimos de la sub-rutina con el atrapador de errores
Exit_SinData:
Exit Sub
Err_SinData:
MsgBox "Registro inexistente o error en la captura, verifique la información"
'enviamos el id_vdi en blanco para nueva búsqueda
Me.id_vdi_master.Value = ""
Resume Exit_SinData
Los nombres que ves antes del signo = son los textbox, los que ves entre (" ") son los nombres del campo en la tabla de la base de datos. Claro que dejé este código del lado cuando vi que solo se posiciona para buscar pero no me permite hacer el recorrido consecutivo a partir de donde encontró el registro.

Saludos.
End Sub

El problema con tu código para buscar es que creas un nuevo recordset con los datos filtrados, por eso al pulsar los botones no te va al regsitro correspondiente del recordset original. Si en vez de hacerlo con un recordset nuevo son la SQL usas la propiedad FindFirst del recordset, te debería funcionar, ya que el recordset lo tienes cargado.

Algo así (sin control de errores):

Private Sub btn_buscar_vdi_Click()

rst.FindFirst "id_vdi_master = '" & id_vdi_master.Value & "'"

If rst.NoMatch Then

Msgbox "No se han encontrado registros para esa clave"

Else

'Aquí el código para cargar los datos en los cuadros

End If

End Sub

Si lo quieres "complicar" más, puedes jugar con FindNext, FindPrevious y Find Last para moverte por los registros "filtrados"

Estoy probando el código que me enviaste y seguramente lo tengo mal escrito por lo que me manda el error que te muestro en la imagen

me puedes ayudar un poco más con la estructura del código por favor?

Este es el código que estoy utilizando:

Private Sub btn_buscar_vdi_Click()
rst.FindFirst "id_vdi_master = '" & id_vdi_master.Value & "'"

If rst.NoMatch Then

MsgBox "No se han encontrado registros para esa clave"

Else
'este es un atrapador de errores
On Error GoTo Err_SinData
'Asignamos el valor al TextBox
id_vdi = rst.Fields("id_vdi").Value
id_vdi_master = rst.Fields("id_vdi_master").Value
clave_vdi_fk = id_vdi_master
nivel_validacion = rst.Fields("nivel_validacion").Value
estatus = rst.Fields("estatus").Value
prefijo = rst.Fields("prefijo").Value
apellido_paterno = rst.Fields("apellido_paterno").Value
apellido_materno = rst.Fields("apellido_materno").Value
nombre_1 = rst.Fields("nombre_1").Value
nombre_2 = rst.Fields("nombre_2").Value
especialidad = rst.Fields("especialidad").Value
subespecialidad = rst.Fields("subespecialidad").Value
fecha_nacimiento = rst.Fields("fecha_nacimiento").Value
edad = rst.Fields("edad").Value
email_1 = rst.Fields("email_1").Value
email_2 = rst.Fields("email_2").Value
email_3 = rst.Fields("email_3").Value
telefono_movil = rst.Fields("telefono_movil").Value
End If
Me.clave_vdi_fk.Visible = True
Me.clave_vdi_1.Visible = False
Me.id_vdi_master = ""
'Cerramos el recordset y liberamos memoria
rst.Close
dbs.Close
Set rst = Nothing
Set dbs = Nothing
'salimos de la sub-rutina con el atrapador de errores
Exit_SinData:
Exit Sub
Err_SinData:
MsgBox "Registro inexistente o error en la captura, verifique la información"
'enviamos el id_vdi en blanco para nueva búsqueda
Me.id_vdi_master.Value = ""
Resume Exit_SinData
'cmd_Siguiente_Click
End Sub

Gracias y saludos

Saludos

Cambia rst por Recordset, que es como llamas a tu objeto en el código de los botones. Me lié con el código que usabas antes para buscar... XD

Hola nuevamente,

Mira, tomé el código que me enviaste y ya lo estructuré correctamente y funciona perfecto, es decir; cuando ingreso el criterio de búsqueda, realiza la localización del registro correctamente. Sin embargo, me deja en el primer problema que había planteado en un inicio: Si estoy en el registro 1 y busco el 439, me trae todos los datos del registro 439, pero cuando pulso el botón siguiente y atrás, me pasa al 1 o al 2 respectivamente y necesito que se quede posicionado en el registro que busqué para continuar la búsqueda secuencial hacia adelante o hacia atrás con los botones navegadores.

Me puedes apoyar con esto?

Te envío el código como quedó:

Private Sub btn_buscar_vdi_Click()
Dim rst As Object
Set rst = Me.Recordset.Clone
rst.FindFirst "[id_vdi_master] = '" & Nz(Me![id_vdi_master], "") & "'"
If rst.NoMatch Then
Busca = id_vdi_master
Respuesta = MsgBox("Este registro no existe, verifique e inténtelo nuevamente", vbYesNo)
Else
id_vdi = rst.Fields("id_vdi").Value
id_vdi_master = rst.Fields("id_vdi_master").Value
clave_vdi_fk = id_vdi_master
nivel_validacion = rst.Fields("nivel_validacion").Value
estatus = rst.Fields("estatus").Value
prefijo = rst.Fields("prefijo").Value
apellido_paterno = rst.Fields("apellido_paterno").Value
apellido_materno = rst.Fields("apellido_materno").Value
nombre_1 = rst.Fields("nombre_1").Value
nombre_2 = rst.Fields("nombre_2").Value
especialidad = rst.Fields("especialidad").Value
End If
End Sub

Gracias por tu apoyo.

No me estás haciendo caso de lo que te digo: no puedes crear un nuevo recordset para buscar y pretender que pulsando los botones sobre el primer recordset te funcione todo como quieres.

Tal como tienes el sistema montado, tienes:

a) Un primer recordset (lo creas en algún sitio con Dim Recordset As ...) y sobre ese recordset actúas con los botones de navegación (en el código del botón siguiente de tu pregunta pones Recordset. MoveNext). Llamaré a este recordset A.

b)en tu botón buscar creas un nuevo objeto recordset (Dim rst As ... [aquí debería ser Recordset mejor que Object, pero bueno]) y le cargas el origen de datos del formulario (Set rst = Me. Recordset. Clone), lo que por otra parte es un "error", pues como te explicaba antes, el formulario debe ser independiente para que trabaje solo a través del recordset. Llamaré a este recordset B.

Hasta aquí lo que tienes programado.

Veamos ahora cómo funciona.

1º/ Abres el formulario y estarás en el registro 1. Se crea A y se posiciona en el registro 1.

2º/ Haces una búsqueda por medio del botón => Se crea B y se va al registro 450

3º/ Cuando pulsas el botón Siguiente (o Anterior), que trabaja sobre A, lógicamente se irá al registro 2 y no al 451 .

Conclusión: como te decía en mi respuesta anterior, el FindFirst lo tienes que aplicar al recordset que ya tienes creado y cargado, no a uno nuevo.

Hola,

Me queda claro que tengo dos recorset trabajando independientemente, que es precisamente lo que no estaba entendiendo. Me podrías apoyar para estructurar el código, te comento lo siguiente:

1) El Load Form se carga con lo siguiente: 

id_vdi = Recordset.Fields("id_vdi")
nivel_validacion = Recordset.Fields("nivel_validacion")
estatus = Recordset.Fields("estatus")

No tengo ninguna variable declarada, simplemente se cargan los campos al entrar con esto=>

Ahora bien, en el buscador tengo el siguiente código que ya te he mostrado:

Que en este último sí tengo la variable rst declarada como objeto, que se puede cambiar a Recordset.

2) Veo que cargo con rst o con Recordset según sea el caso, ¿Cómo podría homologar el recordset para que solamente trabaje uno y no los dos que están declarados? Te pregunto porque no tengo la menor idea de cómo declarar el FindFirst o como usarlo.

¿Me puedes apoyar con la estructura de cómo quedaría?

Gracias por tu apoyo y saludos.

Te comento lo que yo haría (y que me parece lo mejor para solucionar todos tus problemas):

1º/ Borrar el origen de datos del formulario, es decir, hacerlo independiente de la tabla

2º/ Construir un sistema como el que explico en el ejemplo "Formularios Independientes 1" que te enlacé anteriormente, en concreto el que explico para el formulario FDatos1

Así, en el Form_Load cargas los datos de la tabla en el recordset (rstDatos, en el ejemplo que te cito), y los tendrás disponibles para todos los botones y eventos del formulario (recuerda declarar la variable a nivel de módulo)

3º/ En el botón de buscar, el FindFirst lo aplicas ya sobre el recordset existente (rstDatos.FindFirst "[id_vdi_master] = '" & Nz(Me![id_vdi_master], "") & "'" ... y lo que sigue)

Así, en teoría (y debiera) al pulsar los botones anterior y siguiente te irá al registro adecuado.

¡Gracias! 

Amigo, quedó perfecto gracias a ti.

Saludos

Hola,

Una nueva pregunta:

El buscador funciona muy bien, pero necesito que haga las búsqueda siguiente, es decir: La búsqueda se genera a partir de un estatus que se le asigna al individuo, por ejemplo: POR CONFIRMAR, BUZON, NO CONTESTA.  Pero estos estatus se repiten en varios registros de los clientes, entonces cuando realizo la búsqueda me posiciona en el primero que encuentra y de ahí ya no se mueve al siguiente, ejemplo: 

Tengo 6 individuos con el mismo estatus POR CONFIRMAR, al buscar el estatus me lleva al primer individuo y cuando ingreso nuevamente la búsqueda POR CONFIRMAR para el siguiente registro me deja en el mismo en el que estoy posicionado, me queda claro que es porque no tiene una instrucción para salir de este y continuar al siguiente, me puedes apoyar con ello?

El código que me ayudaste a hacer es el siguiente:

Private Sub Buscar_Click()
'función que sirve para buscar a través del campo de texto
Set Recordset = Me.Recordset.Clone
Recordset.FindNext "[marcacion] = '" & Nz(Me![id_vdi_master], "") & "'"
If Recordset.NoMatch Then
Busca = marcacion
Respuesta = MsgBox("Este registro no existe, verifique e inténtelo nuevamente", vbYesNo)
Else
id_vdi = Recordset.Fields("id_vdi")
nivel_validacion = Recordset.Fields("nivel_validacion")
prefijo = Recordset.Fields("prefijo")
bendera = Recordset.Fields("bandera")
apellido_paterno = Recordset.Fields("apellido_paterno")
apellido_materno = Recordset.Fields("apellido_materno")
nombre_1 = Recordset.Fields("nombre_1")
nombre_2 = Recordset.Fields("nombre_2")

End If

Funciona perfecto, pero le falta que al dar buscar el mismo criterio, se brinque del que está o aunque lo contemple, se vaya al siguiente.

Saludos

Nos estamos desviando del tema original, lo mejor sería que abrieses una nueva pregunta.

A pesar de eso, te diré que la solución ya te la di antes:

Si lo quieres "complicar" más, puedes jugar con FindNext, FindPrevious y Find Last para moverte por los registros "filtrados"

A ver si lo consigues con esa pista, y si no, abre una nueva pregunta.

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas