Bloquear formulario antes de guardar

Necesito de su ayuda. Tengo un formulario llamado ContabilidadCDiario y un sub formulario llamado ComprobanteContabilidad . El subformulario tiene un campo llamado Debe y otro Haber en donde se registran montos. Al pie del subformulario hice unos cuadros de control para que muestre las sumas de cada columna.
En el formulario he colocado Casillas ( Total Debe-Total haber) independientes y visibles que muestran los totales del subformulario y otra casilla que se llama Saldo la cual resta las casilla antes mencionadas a fin de que muestren el valor 0 (es decir debe cuadrar) Hasta aca todo bien.
Lo que necesito es que a los usuarios no los deje grabar los registros o les de un mensaje de error si las sumas de ambas columnas Debe y Haber no están iguales. ( Es decir la casilla Saldo nunca de debe ser <> a cero).
¿Cómo puedo hacer eso?
He pasado todo el dia quebrandome la cabeza y nada.
Ayuda estimados

1 Respuesta

Respuesta
1

En principio no necesitas los cuadros de texto del formulario, pero si es tu deseo luego te lo explico.

Vamos a suponer que formulario y subformulario están relacionados por un campo IdMovimiento( no tiene porqué ser un Id, pero para el ejemplo vale), y supongamos que en el subformulario tienes los cuadros de texto Debe, Haber, Saldo( que están en la tabla ComprobanteContabilidad).

En las propiedades del cuadro de texto Debe, en Eventos-Después de actualizar puedes crear un procedimiento de evento y entre Private sub y end sub poner

docmd.runcommand accmdsaverecord

Saldo=dsum("nz([debe])","comprobantecontabilidad","idmovimiento<=" & me.idmovimiento & ""))-dsum("nz([haber])","comprobantecontabilidad","idmovimiento<=" & me.idmovimiento & "")

Lo mismo en el cuadro de texto Haber. Y asi, cuando anotes una cantidad en Debe, te "guardara" el registro y en saldo te pondrá la suma acumulada de la diferencia entre Debe y Haber. Lo mismo sucederá en Haber. Con lo que en Saldo tendrás siempre su valor actualizado.

¿Que quieres mantener los cuadro de texto en el formulario, bastaría con sustituir, en los eventos citados antes

Docmd. Runcommand accmdsaverecord

me.parent!totalDebe=dsum("nz([debe])","comprobantecontabilidad")

Y en Haber

Docmd. Runcommand accmdsaverecord

me.parent!totalhaber=dsum("nz([haber]","comprobantecontabilidad")

Aquí no sé si querrías poner criterios, así que lo dejo así.

Para que no puedan escribir, en las propiedades del formulario, en el evento Al abrir o Al cargar o al activar registro, depende como sea el formulario, puedes crear un procedimiento de evento y poner

me.allowedits=false

O sea, no puedes escribir en ninguno. ¿Que no quieres que elimine ninguno

me.allowdeletions=false

En fin, que puedes hacerlo de muchas formas

Gracias Estimado Julián

Creo que no me di a entender.

Mi situación es la siguiente:

Mi formulario con el subformulario esta en uso. Hay una casilla en el formulario que se llama Saldo, Que recibe los totales de las casillas del subformulario (SumaDebe-Sumahaber), si todo se dígito bien da como resultado 0 (cero). Hasta acá todo bien. Resulta que a alguno se le ocurre digitar sin revisar que este valor debe quedar a cero. Y entonces a fin de mes demoramos mucho tiempo en encontrar ese registro descuadrado. Por lo que quiero colocar algo que no permita que esta casilla quede con otro valor que no sea cero y no permita seguir adelante hasta que sea corregido el error y luego proseguir.

He colocado este código buscando una lógica a que el usuario no siga si el saldo me da algo diferente a cero y nada

Private Sub Form_BeforeUpdate(Cancel As Integer)
Cancel = Me!Saldo
If Me!Saldo = 0 Then
Me!Saldo = True
End If
If Me!Saldo <> 0 Then
Me!Saldo = False
End If
End Sub

Vamos a ver. Quiero dejar claro que no sé como hacéis las anotaciones, pero según mi opinión, en principio, el saldo, lo pongas en el formulario como en el subformulario nunca será cero a menos que fijes una fecha, una situación, etc. Mira si tengo el formulario Usuarios con el subformulario Movimientos, si en éste anoto algo en Debe

Cuando pulse Enter

Y me irá "arrastrando" el saldo según vaya haciendo anotaciones. El cuadro de texto Saldo está bloqueado para que nadie pueda tocarlo, ya que su valor lo da el cálculo.

Y como puedes ver nunca será cero, a menos que a un Debe le corresponda un Haber igual, o que digas "El último día de cada mes tiene que estar a cero" o algo parecido.

Y en el caso que dices de encontrar el registro descuadrado es muy sencillo, usando, por ejemplo

Docmd. Gotorecord,, acfirst

dim i as integer

for i=1 to me.recordset.recordcount

if saldo<>dsum(...lo que te puse en código) then

msgbox"Este es el registro equivocado",vbokonly,"Localizado"

exit sub

end if

next

Lo que hace es ir recorriendo los registros de forma que cuando localice el registro erróneo, te muestra el mensaje y se para ahí.

¿Puedes poner una imagen del formulario?

Gracias Julián por tu apoyo.

Como veras en el sub formulario no utilizo el saldo en cada línea, nada más los totales. Los cuales paso al formulario. La casilla Saldo hace la resta de los totales y debe quedar a cero. Caso contrario descuadra y no debería pasar a registrar otro formulario hasta que sea enmendado el error. (Es decir debe quedar con valor cero).

Estoy muy agradecido por tu atención.

Prueba a poner la imagen con ese botón. Así, cuando la reciba puedo ampliarla sin perder resolución. Ahora al haberla pegado, si la guardo para poder aumentarla pierdo nitidez y no soy capaz de leer los nombres de los controles.

Gracias y disculpa las molestias

No sé como "llegáis" a esa forma, pero debo suponer que en el combinado Fecha eliges un día y en sus propiedades-eventos-Después de actualizar tienes algo como

me.movimientos.form.recordsource="select * from movimientos where fecha=#" & me.nombredelcombinado & "#"

Si es algo así, que repito que no lo sé, podrías añadir algo como

If saldo<>0 then

me.movimientos.enabled=false

else

me.movimientos.enabled=true

end if

Suponiendo que el subformulario se llame Movimientos

De forma que si saldo distinto de cero el subformulario queda bloqueado. Lo acompañaría con el evento al activar el registro del formulario donde pondría algo como

if not me.newrecord and saldo<>0 then

me.movimientos.enabled=false

elseif not me.newrecord and saldo=0 then

me.movimientos.enabled=true

end if

Pero ya te digo, que no sé como llegáis a la pantalla que has puesto, que sería lo importante.

Gracias Julián

He colocado en mi proyecto lo que me enviaste, por cierto te agradezco mucho tu molestia en apoyarme. Pero tengo una quebradera de cabeza con esto. Anexo lo ingresado... me da error en el formulario

SUBFORMULARIO

Private Sub Form_AfterUpdate()

If Saldo <> 0 Then

Me.ComprobanteContabilidadSub.Enabled = False

Else

Me.ComprobanteContabilidadSub.Enabled = True

End If

End Sub

FORMULARIO

Private Sub Form_Current()

If Me!ComprobanteContabilidadSub!Saldo2 <> 0 Then

Me!ContabilidadCDiario.Enabled = False

ElseIf Not Me!ComprobanteContabilidadSub And Saldo2 = 0 Then

Me!ContabilidadCDiario.Enabled = True

End If

End Sub

Chico, lo siento, no entiendo absolutamente nada.

1º ¿Este formulario que muestras, lo "rellena" alguien?. Porque en este caso no puedes decirle que bloquee nada, porque tendrá que rellenar el segundo registro. ¿Es un formulario de búsqueda?

2º El formulario y el subformulario ¿son independientes?. Si son dependientes ¿cuál es el campo comun?

3º El número de registro del subformulario ¿es un autonumérico?

4º Si lo rellena alguien, supongo que será como en la imagen

Y cuando pulso Enter

Pero, lógicamente el saldo no puede ser cero, hasta que no rellene el(los) siguiente(s) registro(s)

Por lo que no tiene sentido bloquear nada.

5º Si lo va a rellenar alguien, es más importante evitar que cometa errores que luego tratar de arreglarlo. Por eso, si se equivoca en el Abono

Cuando pulso Enter

Cuando pulso Aceptar el cursor se queda en el control Abono para que cambie el valor y al ponerlo bien

Pero como te decía todo esto es suponer por suponer

El código global del subformulario(que está relacionado con el formulario por un campo IdContabilidad) es

Private Sub Abono_AfterUpdate()
DoCmd.RunCommand acCmdSaveRecord
Me.Parent!totalabono = DSum("nz([abono])", "detalleMov", "idcontabilidad=" & Me.IdContabilidad & "")
Me.Parent!Saldo = DSum("cargo", "detalleMov", "idcontabilidad=" & Me.IdContabilidad & "") - DSum("nz([abono])", "detallemov", "idcontabilidad=" & Me.IdContabilidad & "")
End Sub
Private Sub Abono_BeforeUpdate(Cancel As Integer)
If Abono <> Me.Parent!Saldo Then
MsgBox "El abono tiene que ser igual al Saldo, que es de " & Me.Parent!Saldo, vbOKOnly + vbInformation, "¡¡ No te enteras!!"
DoCmd.CancelEvent
End If
End Sub
Private Sub Cargo_AfterUpdate()
DoCmd.RunCommand acCmdSaveRecord
Me.Parent!totalcargo = DSum("nz([cargo])", "detalleMov", "idcontabilidad=" & Me.IdContabilidad & "")
Me.Parent!Saldo = DSum("nz([cargo])", "detalleMov", "idcontabilidad=" & Me.IdContabilidad & "") - DSum("nz([abono])", "detallemov", "idcontabilidad=" & Me.IdContabilidad & "")
End Sub

Lo de Form_AfterUpdate(), no veo para que sirve, ni tampoco lo de bloquear.

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas