No permitir repetición de un servicio dependiendo de la fecha y usuario
Bueno cuento con el siguiente formulario que esta enfocado en la carga de servicio a un restaurante el cual carga los registros por medio del dni insertado por pistola de código de barras. La cual carga los servicios de Desayuno, Almuerzo, Cena y Colación. Todos estos se van asociando automáticamente a un campo bolean correspondiente dependiendo de la hora que sea, excepto colación que se activa por intervención del usuario ya que es variable.
Bueno quiero lograr lo siguiente :
Que no se pueda repetir un mismo servicio 2 veces en un mismo día para el mismo usuario.
Por ejemplo:
Si Dni "5" con fecha "24/10/2019" y servicio "desayuno" esta solo una vez en la tabla seria ok pero si no que arroje un cuadro de mensaje en el evento antes de insertar del formulario que no esta permitida esta acción, todo esto con el fin de que una persona no se repita un servicio.
Bueno y esto aplicarlo a todos los servicios que están en esta tabla los cuales son desayuno, almuerzo, cena y colación.
1 respuesta
Puedes comprobar si ya está de alta ese servicio con este código (para el desayuno, para los otros servicios solo has de cambiar el servicio):
If DCount("*","AsignarServicios","Desayuno=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'")>0 Then
luego las lineas que sigan al Then dependerán de en qué evento lo pongas, algo que no tengo claro al no saber cómo funciona tu formulario.
Por ejemplo, si lo pones en algún evento "después de", podrías lanzar un mensaje y deshacer los cambios:
If DCount("*","AsignarServicios","Desayuno=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'")>0 Then Msgbox "El usuario ya usó ese servicio en el día seleccionado" Me.Undo End If
Si lo pones en un evento "antes de", podrías lanzar un mensaje y cancelar el evento:
If DCount("*","AsignarServicios","Desayuno=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'")>0 Then Msgbox "El usuario ya usó ese servicio en el día seleccionado" Cancel=True End If
Un saludo.
Hola gracias por tu respuesta, pero algo debo estar haciendo mal que no esta funcionando correctamente y he probado las dos opciones que me has dado.
Con la primera opción en el evento antes de insertar
Private Sub Form_AfterInsert() If DCount("*", "AsignarServicios", "Desayuno=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") > 0 Then MsgBox "El usuario ya usó ese servicio en el día seleccionado" Me.Undo End If End Sub
sucede que al momento de insertar el nuevo dni arroja de inmediatamente el mensaje "El usuario ya usó ese servicio en el día seleccionado" siendo que lo estoy probando con la tabla sin ningún registro, quizás lo que sucede es que considera el mismo registro que se esta insertando en el momento y de allí que pasa esto.
muestro captura
lo segundo que pasa con este código es que después de actualizar la tabla el registro si se lleva a cavo y no debería ser así, ya que, tu mencionaste : si lo pones en algún evento "después de", podrías lanzar un mensaje y deshacer los cambios
Hora con el segundo método que lo he puesto en el evento antes de insertar
Private Sub Form_BeforeInsert(Cancel As Integer) If DCount("*", "AsignarServicios", "Desayuno=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") > 0 Then MsgBox "El usuario ya usó ese servicio en el día seleccionado" Cancel = True End If End Sub
Sucede que me arroja un error de inmediato adjunto captura
Bueno esto es lo que me sucede en y lo otro es que me gustaría que el código revisara cada servicio simultáneamente.
Primero: el código funciona perfectamente, el problema está en que lo has puesto en los eventos equivocados...
El evento "Después de Insertar" del formulario se produce una vez que ya se han guardado los datos, por tanto, la validación siempre va a ser cierta porque el registro recién añadido cumple esa condición. Además, como los datos ya se han guardado, no hay nada que deshacer.
El evento "Antes de insertar" del formulario se ejecuta al escribir el primer carácter en un control de un nuevo registro, luego es lógico que te salte un error, porque haces una validación sin sentido.
Lo más sensato hubiera sido que usases los eventos "Después de actualizar" o "Antes de actualizar" del formulario, aunque si usas el primero vas a tener el mismo problema que te comentaba antes para "después de insertar", como ya has actualizado el registro, ya no tienes nada que deshacer.
Segundo: yo no te puedo indicar en qué evento lo has de colocar, porque no sé cómo funciona tu formulario... Si tienes casillas de verificación para marcar los servicios, el código te funcionará perfectamente en los eventos "antes de actualizar" o "después de actualizar" de cada casilla (si lo pones en el evento después, Me. Undo deshará el registro, Me. NombreCasilla. Undo deshará solo el cambio en la casilla). Si tienes botones para ejecutar una SQL de actualización (o inserción), puedes hacer la verificación en el código del propio botón y ejecutar la SQL o lanzar el mensaje según corresponda.
Te dejo un archivo con algunas opciones: http://www.filebig.net/files/SjwvWWt7fz
Muchas gracias, pero no se como hacer para que revise todos los servicios simultáneamente osea desayuno, almuerzo, cena y colación.
me ayudarías por favor
No sé a qué te refieres por "simultáneamente"...
¿Qué los tenga todos marcados? :
If DCount("*", "AsignarServicios", "Desayuno=-1 AND Cena=-1 AND Almuerzo=-1 AND Colacion=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") > 0 Then
¿o que mire uno a uno pero para los cuatro checks ?:
If DCount("*", "AsignarServicios", "Desayuno=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") > 0 Then MsgBox "El usuario ya usó el servicio de desayuno en el día seleccionado" ... End If If DCount("*", "AsignarServicios", "Almuerzo=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") > 0 Then MsgBox "El usuario ya usó el servicio de Almuerzo en el día seleccionado" ... End If If DCount("*", "AsignarServicios", "Cena=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") > 0 Then MsgBox "El usuario ya usó el servicio de Cena en el día seleccionado" ... End If If DCount("*", "AsignarServicios", "Colacion=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") > 0 Then MsgBox "El usuario ya usó el servicio de Colacion en el día seleccionado" ... End If
que mire uno a uno pero para los cuatro checks. Trate de poner ese código, pero no me resulta ,ya que, cambie la hora para que cargara otro servicio y me arroja el mensaje "El usuario ya usó el servicio de Almuerzo en el día seleccionado"
Private Sub Form_BeforeUpdate(Cancel As Integer) If DCount("*", "AsignarServicios", "Desayuno=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") > 0 Then MsgBox "El usuario ya usó el servicio de desayuno en el día seleccionado" Cancel = True End If If DCount("*", "AsignarServicios", "Almuerzo=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") > 0 Then MsgBox "El usuario ya usó el servicio de Almuerzo en el día seleccionado" Cancel = True End If If DCount("*", "AsignarServicios", "Cena=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") > 0 Then MsgBox "El usuario ya usó el servicio de Cena en el día seleccionado" Cancel = True End If If DCount("*", "AsignarServicios", "Colacion=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") > 0 Then MsgBox "El usuario ya usó el servicio de Colacion en el día seleccionado" Cancel = True End If End Sub
y bueno con respecto al formulario los únicos campos que manipula el usuario es dni (que se inserta con la pistola de codigo de barras) y el bolean de "colación" que se ve en la imagen que se utiliza cuando el usuario no quiere almuerzo y en cambio pide una colación.
Para que se ingresen los servicios utilizo el siguiente codigo.
Private Sub DNI_AfterUpdate() If Colacion = False Then If Hora >= DLookup("Desde", "Horarios", "Recurso=""Desayuno""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Desayuno""") Then Desayuno = True ElseIf Hora >= DLookup("Desde", "Horarios", "Recurso=""Almuerzo""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Almuerzo""") Then Almuerzo = True ElseIf Hora >= DLookup("Desde", "Horarios", "Recurso=""Cena""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Cena""") Then Cena = True End If End If End Sub
el cual funciona perfecto.
no se que hacer
Si hubieras empezado por ahí (por cómo funciona tu formulario) hubiéramos llegado a una solución mucho antes...
Haz esto, en el código que ya tienes:
Private Sub DNI_AfterUpdate() If Colacion = False Then If Hora >= DLookup("Desde", "Horarios", "Recurso=""Desayuno""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Desayuno""") Then If DCount("*", "AsignarServicios", "Desayuno=-1 AND Cena=-1 AND Almuerzo=-1 AND Colacion=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") = 0 Then Desayuno = True End IF ElseIf ...
Y así con los otros dos servicios.
quedaría así??
Private Sub DNI_AfterUpdate() If Colacion = False Then If Hora >= DLookup("Desde", "Horarios", "Recurso=""Desayuno""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Desayuno""") Then If DCount("*", "AsignarServicios", "Desayuno=-1 AND Cena=-1 AND Almuerzo=-1 AND Colacion=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") = 0 Then Desayuno = True End If ElseIf Hora >= DLookup("Desde", "Horarios", "Recurso=""Aluerzo""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Almuerzo""") Then If DCount("*", "AsignarServicios", "Desayuno=-1 AND Cena=-1 AND Almuerzo=-1 AND Colacion=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") = 0 Then Almuerzo = True ElseIf Hora >= DLookup("Desde", "Horarios", "Recurso=""Cena""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Cena""") Then If DCount("*", "AsignarServicios", "Desayuno=-1 AND Cena=-1 AND Almuerzo=-1 AND Colacion=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") = 0 Then Cena = True End If End Sub
Disculpa, que copie el If que no era...
Quedaría así:
Private Sub DNI_AfterUpdate() If Colacion = False Then If Hora >= DLookup("Desde", "Horarios", "Recurso=""Desayuno""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Desayuno""") Then If DCount("*", "AsignarServicios", "Desayuno=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") = 0 Then Desayuno = True End IF ElseIf ...
Y tendrías que cambiar Desayuno por Cena y Almuerzo en los ElseIfs correspondientes
lo ingresa de igual forma , pero sin check cuando se repite el servicio en cambio la colación permite el duplicado y con check cuando se ingresan
Private Sub DNI_AfterUpdate() If Colacion = False Then If Hora >= DLookup("Desde", "Horarios", "Recurso=""Desayuno""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Desayuno""") Then If DCount("*", "AsignarServicios", "Desayuno=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") = 0 Then Desayuno = True ElseIf Hora >= DLookup("Desde", "Horarios", "Recurso=""Almuerzo""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Almuerzo""") Then If DCount("*", "AsignarServicios", "Almuerzo=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") = 0 Then Almuerzo = True ElseIf Hora >= DLookup("Desde", "Horarios", "Recurso=""Cena""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Cena""") Then If DCount("*", "AsignarServicios", "Cena=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") = 0 Then Cena = True End If End If End Sub
ademas le quitaste el mensaje y que no lo ingrese si ya estaba en la tabla.
lo probé así también pero no funciono
Private Sub DNI_AfterUpdate() If Colacion = False Then If Hora >= DLookup("Desde", "Horarios", "Recurso=""Desayuno""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Desayuno""") Then If DCount("*", "AsignarServicios", "Desayuno=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") = 0 Then Desayuno = True MsgBox "El usuario ya usó el servicio de Colacion en el día seleccionado" Cancel = True ElseIf Hora >= DLookup("Desde", "Horarios", "Recurso=""Almuerzo""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Almuerzo""") Then If DCount("*", "AsignarServicios", "Almuerzo=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") = 0 Then Almuerzo = True MsgBox "El usuario ya usó el servicio de Colacion en el día seleccionado" Cancel = True ElseIf Hora >= DLookup("Desde", "Horarios", "Recurso=""Cena""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Cena""") Then If DCount("*", "AsignarServicios", "Cena=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") = 0 Then Cena = True MsgBox "El usuario ya usó el servicio de Colacion en el día seleccionado" Cancel = True End If End If End Sub
me estoy volviendo loco!!
Sin mensaje:
Private Sub DNI_AfterUpdate() If Colacion = False Then If Hora >= DLookup("Desde", "Horarios", "Recurso=""Desayuno""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Desayuno""") Then If DCount("*", "AsignarServicios", "Desayuno=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") = 0 Then Desayuno = True Else Me.Undo End If ElseIf
Con mensaje:
Private Sub DNI_AfterUpdate() If Colacion = False Then If Hora >= DLookup("Desde", "Horarios", "Recurso=""Desayuno""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Desayuno""") Then If DCount("*", "AsignarServicios", "Desayuno=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") = 0 Then Desayuno = True Else Msgbox "..." Me.Undo End If ElseIf
Lo que no puedes pretender es que copiando lo que te de la gana de las diferentes soluciones que te propongo te funcione (El Cancel=True es para eventos "antes de", no "despues de"...)
Hola amigo muchas gracias eres el mejor y. me quedo así el código.
Private Sub DNI_AfterUpdate() If Colacion = False Then If Hora >= DLookup("Desde", "Horarios", "Recurso=""Desayuno""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Desayuno""") Then If DCount("*", "AsignarServicios", "Desayuno=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") = 0 Then Desayuno = True Else MsgBox "El usuario ya usó el servicio de Desayuno en el día seleccionado" Me.Undo End If ElseIf Hora >= DLookup("Desde", "Horarios", "Recurso=""Almuerzo""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Almuerzo""") Then If DCount("*", "AsignarServicios", "Almuerzo=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") = 0 Then Almuerzo = True Else MsgBox "El usuario ya usó el servicio de Almuerzo en el día seleccionado" Me.Undo End If ElseIf Hora >= DLookup("Desde", "Horarios", "Recurso=""Cena""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Cena""") Then If DCount("*", "AsignarServicios", "Cena=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") = 0 Then Cena = True Else MsgBox "El usuario ya usó el servicio de Cena en el día seleccionado" Me.Undo End If End If End If End Sub
Pero sabes aun pasa por alto las colaciones y no podría utilizar el esa misma linea de código porque como dije en un comienzo la colación es variable , no tiene horario y de hecho no la tengo en la tabla de horarios de donde se toma la información para comparar que servicio se esta ingresando dependiendo de la hora.
muestro captura.
Hora esta comprobación seria diferente, ya que , colación puede reemplazar a los tres servicios (Desayuno, Almuerzo y Cena) por lo tanto debería ser algo así según lo que yo pienso:
si "DNI" dentro de la "fecha" tiene un total de tres servicios (desayuno, almuerzo y cena) entonces :
"El usuario no puede solicitar colaciones, ya que, adquirió todos los servicios de hoy"
de lo contrario si podría tomar el servicio. y el registro se carga en la tabla.
De ante mano de nuevo muchas gracias por tu valioso tiempo.
Todo el código que has puesto lo haces bajo la condición de que colación sea Falso, y nada más. Para contemplar la posibilidad de que colación sea verdadero, has de añadir, antes del último End If, un Else y ahí programar las validaciones que quieras si se marca la casilla Colacion.
En cuanto al código, viendo cómo son los códigos de validación anteriores, tendrías (con poco esfuerzo por tu parte) que ser capaz de hacerlo solo ( si no lo intentas, nunca aprenderás). Además, ya tienes una pista en los códigos que te he pasado en respuestas anteriores.
Hola, perdón por lo majadero pero no se que paso y ahora no funciona que impida registros duplicados, si asigna correctamente los servicios.
http://www.filebig.net/files/KT54mZ55nA
Te envío el archivo si me puedes ayudar ya que no consigo nada
Pues está bien claro, si en la tabla el campo se llama IdDni, en el código le tienes que llamar igual, no DNI (lo que te pongo en negrita) :
.... & "# AND IdDNI='" & Me.DNI & "'") = 0 Then
El Me. DNI que te pongo en cursiva, será el nombre que le tengas al cuadro de texto en el formulario, que no tiene por qué coincidir con el de la tabla. (Ahora no tengo acceso al archivo, pero lo compruebas tú)
Lo hice tal cual me dijiste pero no funciona además el campo en la tabLa si se llama DNI
Te explico el campo idni lo utilizo en el formulario para cargar la información con la pistola o manualmente, por lo tango debo tomar la información para comparar desde el dni que es un campo calculado que me extrae el dni ya con el formato que se utiliza.
Por lo mismo así debería esta bien, pero no
Private Sub DNI_AfterUpdate() If Colacion = False Then If Hora >= DLookup("Desde", "Horarios", "Recurso=""Desayuno""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Desayuno""") Then If DCount("*", "AsignarServicios", "Desayuno=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") = 0 Then Desayuno = True Else MsgBox "El usuario ya usó el servicio de Desayuno en el día seleccionado" Me.Undo End If ElseIf Hora >= DLookup("Desde", "Horarios", "Recurso=""Almuerzo""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Almuerzo""") Then If DCount("*", "AsignarServicios", "Almuerzo=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") = 0 Then Almuerzo = True Else MsgBox "El usuario ya usó el servicio de Almuerzo en el día seleccionado" Me.Undo End If ElseIf Hora >= DLookup("Desde", "Horarios", "Recurso=""Cena""") And Hora <= DLookup("Hasta", "Horarios", "Recurso=""Cena""") Then If DCount("*", "AsignarServicios", "Cena=-1 AND Fecha=#" & Me.Fecha & "# AND DNI='" & Me.DNI & "'") = 0 Then Cena = True Else MsgBox "El usuario ya usó el servicio de Cena en el día seleccionado" Me.Undo End If End If End If End Sub
Vale, el campo en la tabla sí se llama DNI, pero el cuadro de texto del formulario no (se llama idDNI), y en eso no me hiciste caso.
También es buena costumbre usar formatos americanos de fecha, para que al usarla en código no se "confunda".
Dicho esto, si lo pones así:
.... AND Fecha=#" & Format(Me.Fecha, "mm/dd/yyyy") & "# AND DNI='" & Me.idDNI & "'")=0 ...
A mi me funciona.
¡Gracias! ahora si funciona perfecto pero le hecho unos cambios ya que como te lo explicaba no puede comparar directamente del campo que esta en el tabla (DNI)con el campo del formulario(IdDNI) ,por que el dni se puede ingresar de dos formas una manual que es escribir directamente el dni Ejemplo:15813443-8
como te lo muestro en la imagen
Y la otra forma es con la pistola que envía la información con otro formato a este campo (IdDNI) del formulario por lo mismo la comparación de los mismo no resultaría.
Por lo tanto lo que hice fue agregar el campo que le daba el formato correcto al formulario y que el código comparece esos dos . Osea Campo dni de la tabla vs campo dni del formulario.
En fin funciona perfecto y el único cambio que realice fue el código que me has dado de la fecha , que al parecer eso era la causa , ya que había intentado esto mismo que hice ahora con el código antiguo y nada y ahora perfecto.
Ya lo probé con los distintos horarios y corre muy bien .
La verdad que muy agradecido con tu enorme paciencia y si se pudieran botar mas puntos claro que lo haría..
- Compartir respuesta