Conflicto con Recordset

Tengo una duda sobre la forma en que Access ejecuta un código que contiene un recordset.
El tema es el siguiente: tengo un código que está formado por dos acciones y la primera de ellas es un recordset. La segunda acción tiene que esperar que el recordset termine para ejecutarse.
Yo pensaba que el escribir el código de forma
Private Sub Comando1_Click()
Primera Acción (Código de Recordset)
Segunda Acción (Depende de Primera)
End Sub
Ejecutaba el código de la primera acción y cuando llegaba a la línea de la segunda acción ya había terminado con todo lo anterior. Pero me di cuenta que no, que lo que hace es empezar a ejecutar el recordset y mientras lo ejecuta pasa a la segunda acción, lo cual me genera un inconveniente.
Un ejemplo simple de lo que me pasa (para tratar de aclarar algo) es:
- En un formulario que depende de la Tabla1 (que contiene una campo llamado CampoX) creo un botón que ejecute el siguiente código al hacer click
Private Sub Comando1_Click() Me.Refresh 'Para guardar cualquier cambio realizado sobre el formulario abierto
Dim dbs As Database
Dim rst As Recordset
Set dbs = CurrentDb
Set rst = dbs.OpenRecordset("Tabla1")
rst.MoveFirst
rst.Edit
rst!CampoX = "3"
rst.Update
rst.Close
dbs.Close
Me.CampoX = "2"
End Sub
Como podrán ver (si lo hacen) aparece un mensaje de error.
¿Alguien puede explicarme como es que funciona y como puedo solucionarlo?

1 respuesta

Respuesta
1
Veo dos, lo dos muy lógicos:
El primer mensaje de error que me aparece es cuando la tabla1 está vacía y por tanto falla el movefirst. Trivial, supongo. Se soluciona poniéndole un if not rst. Eof then lo que sea
El segundo, si el registro está en edición cuando le das al botónestando en el primer registro. Da un error de datos modificados en el ="2". El motivo es que el formulario detecta que los datos que está mostrando en pantalla ya no son los que hay en la tabla, y esto es correcto, pues los has tocado 'por debajo' con el recordset.
No sé realmente lo que pretendes hacer, así que tampoco puedo decirte cómo hacerlo...
Hola
Gracias por contestar.
Te comento: lo que trato de mostrar con este ejemplo sencillo es un problema que me ocurre al trabajar con mi base de datos.
Voy a tratar de detallarte mejor las cosas porque no se entendió mucho antes.
Primero que nada el primer error no es el problema al que hacia referencia porque mi tabla1 tenia datos. Entonces no me había dado cuenta de que me faltaba el código que me indicaste.
Si podes crea una nueva base de datos que va a ser bastante más fácil de entender (si me dejas un mail te envío el ejemplo). Realiza las siguientes cosas:
1-. Crea una tabla llamada tabla1 con un campo llamado campoX.
2-. Agrega un registro. Ejemplo: "Hola"
2-. Crea un formulario en donde el origen de registro sea precisamente la tabla1.
3-. En el formulario crea un cuadro de texto llamado campoX con el origen de control: campoX.
4-. Agrega 3 botones de comandos llamados Acción1, Acción2, Acción1y2.
5-. Agrega los siguientes procedimientos de evento al hacer click sobre los botones:
a-. Para el botón Acción1
Private Sub Acción1_Click()
Me.Refresh
Dim dbs As Database
Dim rst As Recordset
Set dbs = CurrentDb
Set rst = dbs.OpenRecordset("Tabla1")
If Not rst.EOF Then
rst.MoveFirst
rst.Edit
rst!campoX = "3"
rst.Update
rst.Close
dbs.Close
End If
End Sub
b-. para el botón Acción2
Private Sub Acción2_Click()
Me.campoX = "2"
End Sub
c-. para el botón Acción1y2
Private Sub Acción1y2_Click()
Me.Refresh
Dim dbs As Database
Dim rst As Recordset
Set dbs = CurrentDb
Set rst = dbs.OpenRecordset("Tabla1")
If Not rst.EOF Then
rst.MoveFirst
rst.Edit
rst!campoX = "3"
rst.Update
rst.Close
dbs.Close
Me.campoX = "2"
End If
End Sub
Bueno como verás haciendo click en el botón acción1 y a continuación en el botón acción2 debería ocurrir lo mismo que al hacer click en el botón acción1y2.
Pero sin embargo en el primer caso funciona correctamente mientras que en el segundo (acción1y2) ocurre un error.
La única diferencia que hay entre ambos es el tiempo que se tarda en hacer el click de Acción2.
Si estás de acuerdo conmigo, ¿tenés idea de como hacer para que acción1y2 funcione correctamente?
Disculpa por lo extenso del mensaje y espero haber sido algo más claro.
Pues tendrás que decirme qué error te da, porque a mí no me sale ninguno.
Funciona exactamente como se pretende que funcione.
Hola,
el mensaje de error que aparece es:
Se ha producido el error '7878' en tiempo de ejecución:
Los datos se han modificado.
Otro usuario modificó este registro y guardó los cambios antes de que usted intentara guardar los suyos.
Vuelva a modificar el registro.
Si me das tu dirección de mail te envío el ejemplo.
Te hago un comentario:
- Si no te aparece error al hacer click una vez en el botón Acción1y2 hazlo nuevamente. A mi me da error.
Gracias por tu tiempo
Pues si, ocurre si estás situado en el primer registro del formulario. Vuelvo a insistir en el 'tema 2' de mi respuesta anterior. El formulario tiene una información, que se queda obsoleta al modificar la tabla directamente con el recordset. Cuando se ejecuta lo de me. Campox=2, access detecta que lo que tiene el formulario ya no es lo que se había leído de la tabla y lanza un mensaje de error. De hecho, es el mismo que se lanzaría si este mismo problema apareciera por multiusuarios (dos accediendo al mismo tiempo al mismo registro).
Solución: justo antes del me.campox="2" que produce el error, ponle
Me. Recalc
Ésto fuerza a que se recalcule el formulario. Los campos de tablas se vuelven a leer, así el formulario se 'percata' de que ahora el campox debe valer 3, y cuando lo tocas ya no da el error.
Espero haber acertado... ¿era ésto?
Pues no había acertado, resulta que no es me. Recalc sino me. Requery Un Lapsus
Bien,
ahora funciona, pero por qué no produce un error cuando hago click en cada uno de los botones 1 y 2 por separado si en este caso tampoco utilizo me. ¿requery?
Access aprovecha los 'tiempos muertos' en que no está procesando visual basic para, entre otras cosas, comprobar si los datos de la tabla subyacente han variado. Entonces, si hay dos botones que se pulsan por separado, le da tiempo entre uno y otro a actualizar el formulario, y así no da el error.
Lo cual me ha dado una idea que he probado y efectivamente funciona. Si en lugar del me. Requery pones DoEvents el tercer botón también funciona. Esta función lo que hace es pasarle el control a Access para que procese esas tareas de fondo que normalmente ejecuta cuando no tiene nada mejor que hacer.

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas