Autotosumas Parciales en Formulario Access

Me he enganchado con esto que creo que es sencillo pero no lo consigo. Mi versión de Access es : Microsoft® Access® 2016 MSO (versión 2301 compilación 16.0.16026.20002) de 64 bits

Es una Tabla en la que quiero que conforme vaya introduciendo los datos de Importe, me vaya haciendo la suma del Saldo del campo anterior más el valor del nuevo importe.

La Tabla se llama "T Datos". Los campos serían [DESCRIPCION] [IMPORTE] [SALDO]

He utilizado en el campo [SALDO] "Valor Predeterminado"  la expresión: =Suma([IMPORTE])+2675,41

(Nota: 2675,41 es el valor inicial en el primer registro del campo [SALDO])

Y con esta expresión me devuelve la Suma de TODOS los valores de [IMPORTE] en cada registro. El mismo valor siempre. Y quisiera que en [SALDO] mantuviera el valor que se de en cada registro y que el siguiente fuera la suma de ese [SALDO] más el nuevo [IMPORTE].

EJ: [DESCRIPCION]    [IMPORTE]     [SALDO]

        Apunte Inicio                 0             2675,41

        Apunte 2                     100            2775,41

        Apunte 3                     200            2975,41

etc......

Esto me iría bien ponerlo en el Formulario como Procedimiento de Evento "al actualizar" o "al salir" del campo [IMPORTE]

3 Respuestas

Respuesta
1

En un informe se hace con mucha facilidad, pero en un formulario no es lo mas optimo, si acaso es ...¿imprescindible? Mejor en una consulta (que será el nuevo origen de datos del formulario, la tabla + el dato calculado).

Para que funcione de forma optima se necesita un dato que implique un orden creciente (no es imprescindible que sea correlativo solo que sea creciente).

Como saldo no se toma 'el campo anterior', se toma la suma del campo importe desde su inicio (cero o el saldo anterior) hasta el campo actual (la referencia creciente).

En la consulta se genera el nuevo campo así:
Saldo: DSum("Importe", "[aqui la tabla]", "[CampoCreciente] <= " & [CampoCreciente])

Solo un comentario: el saldo será real y si se modifica un valor se recalcula, la suma la hace 'registro a registro' para obtener el dato (se repetirá tantas veces como datos tenga la tabla).

¡Gracias! 

En un rato voy a probarlo.

Te comentaré.

Por alusiones:

La ventaja de hacer el calculo en una consulta, (el mismo calculo) es que el formulario 'pesa menos' y los datos se visualizaran en cuanto se guarde el registro.

Solo hay que verificar ambos métodos y quedarse con el que se considere mas idóneo (sobre todo al recorrer el formulario).

He probado esto y no funciona

Una tabla con estos campos:

Id (autonumérico)

Fecha (fecha/hora)

Descripción (texto)

Importe (moneda)

La consulta (en formato SQL)

SELECT Diario.Fecha, Diario.Descripcion, Diario.Importe, DSum("Importe","Diario","Id <=" & [id]) AS Saldo
FROM Diario;

Un formulario basado en esa consulta y el campo saldo se actualizará en cuanto se guarde el registro.

Como 'SALDO' es un campo calculado, no es manipulable ni en la consulta ni el formulario (se le puede desactivar su propiedad 'punto de tabulación' para facilitar la entrada de datos).

La consulta (en formato SQL)

SELECT Diario.Fecha, Diario.Descripcion, Diario.Importe, DSum("Importe","Diario","Id <=" & [id]) AS Saldo
FROM Diario;

En el mensaje anterior no disponía de la opción de formatear como código

Respuesta
1

En las tablas no puedes hacerlo, pero me parece descabellado que se diga que en los formularios no se debe. Los formularios se diseñaron como una forma cómoda de meter datos en las tablas. Para poder ver resultados en una consulta previamente tienes que haber metido datos en una tabla, y ¿por qué esperar si puedo verlos en el mismo momento que introduzco los datos?.

Por ejemplo, si tengo la tabla

Y con ella construyo un formulario, da igual único o continuo pero de esta forma se ve mejor

Anoto un valor en Valor1. Puedes ver que el cursor aún está en el control. Cuando pulso Enter

Me anota el primer saldo, y no tengo que tener en cuenta nada. Anoto otro valor y al pulsar Enter

Y así...

Y sólo con decirle, en el evento Después de actualizar del cuadro de texto Valor1

Private Sub Valor1_AfterUpdate()
DoCmd.RunCommand acCmdSaveRecord
Saldo = DSum("valor1", "tabla1")
End Sub

Y me va dejando la tabla como

¡Gracias! 
Pues eso es!
Esto es lo que quería.
Voy a probar.
Muchísimas gracias

Pues si que funciona, mira

Al pulsar Enter

Y el código es el que te dije

Private Sub Importe_AfterUpdate()
DoCmd.RunCommand acCmdSaveRecord
Grupo4 = DSum("importe", "T Datos")
End Sub

Lo que no sé si en las propiedades del cuadro de texto Importe-Eventos-Después de actualizar has puesto el cursor en el rectángulo blanco que hay a su derecha y al pulsado el botón de tres puntos(...) y en la ventana que se abre has seleccionado Generador de código.

No se. Algo hay que no cuadra. He repasado el código y he puesto lo mismo.

Y el resultado es que no da ningún valor. La celda queda en blanco.

El nombre del campo donde debe ir el Saldo parcial es "GRUPO4"

¿Alguna idea de por qué no me funciona?

Chico, tienes que perdonar el retraso, pero esta página no avisa de la petición de ampliación de respuestas.

Si tengo el formulario, al que sólo le he puesto dos campos de la tabla, y en vista diseño selecciono el control Importe y en sus propiedades-eventos pongo el cursor en el rectángulo de la derecha del evento Después de actualizar, me aparecen una punta de flecha y un botón de tres puntos. Si "despliego" la punta de flecha, me aparece Procedimiento de evento, lo selecciono y luego pulso el botón de los tres puntos(puedes ver que el cursor está a la derecha de Después de actualizar)

Entonces se abrirá el editor de VB, y entre Private Sub... y end sub es donde escribo

Con lo que a medida que voy metiendo datos en el formulario

Muchas gracias por la ayuda.
Esta opción de código que me dices es la que ya tengo puesta y, efectivamente, me va haciendo la suma conforme meto datos nuevos en el campo Importe.

Para que te hagas una idea, en el ejemplo que me has puesto arriba, si tu en el 2º campo que me has puesto, cambias el valor -333,00€ por otro distinto, ya no te mantiene el saldo bien.


Mi problema es que los datos me aparecen desordenados en el tiempo y si después de introducir el dato y que me haga la suma bien, procedo a reordenar la tabla por la Fecha del Valor, los resultados de la columna GRUPO4 (que en realidad es el SALDO) no quedan ordenados ni son correctos.

Para poder tenerlo bien tengo que borrar todos los valores desde el nuevo que quiero meter en su orden de fecha y volver a escribir todo.

Esta acción con Excel como ejemplo, sería: si tienes columnas A (Importe) y B (Saldo), la fórmula sería B2= B1+A2; B3=B2+A3; B4=B3+A4; etc. de forma que no sumara los valores del campo "IMPORTE" sino que tomara el último valor de la columna "GRUPO4" y le sumara el siguiente de la columna "IMPORTE". Así, cada vez que introduzca un nuevo valor, cuando se muestre en el Formulario ordenado por fecha del dato, me haga siempre la suma del saldo en ese Registro a esa fecha.

Tú dirás ¿y por qué no lo haces en Excel?  Pues porque en Excel, meter los datos y hacer las operaciones es fácil, pero extraer diferentes consultas por fechas, conceptos, suma de conceptos, etc es más complicado o muy difícil. 
Gracias por tu atención.

Te pongo a continuación tres capturas del Formulario para intentar explicar mejor lo que digo.

Tener en cuenta que el Formulario está basado en una Consulta que ORDENA los datos por el campo FECHA, así que cada vez que se cierra y se vuelve a abrir se reordenan todos los registros.


CAPTURA 01: Los datos conforme los voy introduciendo. Los apuntes son correlativos conforme van apareciendo. Las fechas son de cada apunte, no tienen por qué ser correlativas. El saldo está correcto porque va calculando conforme se va introduciendo el dato en IMPORTE.

Aquí el SALDO final es 0. SALDO CORRECTO

CAPTURA 02: Esta es la vista del Formulario tras cerrarlo y volverlo a abrir. Los registros se han reordenado según el criterio de la Consulta por FECHA. Los valores de IMPORTE son correctos pero el SALDO es incorrecto. No ha hecho la suma del valor de IMPORTE más el último valor de SALDO y el resultado en el último registro no es correcto.

Aquí el SALDO final es 500. SALDO INCORRECTO

CAPTURA 03: Esta es una captura de datos "forzada" para que se vean cuál debería ser el comportamiento del Formulario tras cerrar y volver a abrir. En esta vista se ve que las fechas son correlativas independientemente del momento de introducción del Apunte y el SALDO es correcto en todos los Registros. 

Aquí el SALDO final es 0. SALDO CORRECTO

Esta última es la acción que necesito en la acción "Después de actualizar" del campo "IMPORTE" para que me ofrezca siempre el SALDO correcto en cada Registro y al Final.

Gracias de nuevo

Voy a tratar de ser lo más sencillo posible. Si tengo el formulario Tabla1 con

Voy a cambiarle el valor del registro de 100 euros

Puedes ver que el cursor aún está en 50,50. Si pulso el botón

En este caso, pero se podría hacer de otras formas, pero me gusta ver, si son muchos registros como se va desplazando por lo registros actualizando valores, el código del botón es

Private Sub Comando7_Click()
Dim i As Integer
DoCmd.GoToRecord , , acFirst
For i = 1 To Me.Recordset.RecordCount
Grupo4 = DSum("importe", "tabla1", "idmov <=" & Me.IdMov & "")
DoCmd.GoToRecord , , acNext
Next
End Sub

No sería necesario que se viera el Idmov, pero lo pongo para que dé una idea.

Y el código del evento Después de actualizar del cuadro de texto Importe lo dejo como

Private Sub Importe_AfterUpdate()
DoCmd.RunCommand acCmdSaveRecord
Grupo4 = DSum("importe", "tabla1", "idmov<=" & Me.IdMov & "")
End Sub

La instrucción del botón también te serviría en caso de que decidieras eliminar un registro.

Hola Julián. Gracias por la última información.
Esa solución estaría bien si no modificara el orden del "IdMov" o como lo quieras llamar. Pero es que el orden de ese valor va a cambiar cada vez que cierre y abra el formulario ya que está ordenado por FECHA DEL VALOR y ese valor no tiene por qué coincidir con el momento de la inserción del registro. Por lo tanto se va a volver loco buscando el IdMov anterior menor ya que estarán desordenados.

Pregunto: Esa misma función que me has puesto, ¿se puede usar aplicándosela al campo FECHA en vez de al campo IdMov?

Es que en tu ejemplo no figura el campo FECHA y es el que uso para ordenar los datos.

La cosa sería que el campo SALDO diera el resultado del Registro en el que está, independientemente de su orden de IdMov

Por lo que se ve en la imagen, la fecha contable es la misma para todos los registros, por tanto no la puedes usar como diferenciador de los registros. Pero el primer campo de la izquierda, si guarda un orden. Vamos a suponer que se llama NumOrden. En la instrucción, donde yo pongo IdMov tu puedes poner NumOrden.

No. Fíjate bien. No son la misma fecha.
Son fechas distintas, alguna se repite, pero son distintas.
Al reordenar por fecha todo el saldo se corrompe porque mantiene el valor a pesar de haber cambiado de orden.

Había mirado la primera imagen en la que todos tenían la misma fecha. Tal como la tienes, hay fechas que se repiten, por lo que no puedes usar

<= fecha

Para ello, si tengo tu tabla, le añado un campo auxiliar llamado Orden

Con ella construyo un formulario, donde no sería necesario que se viera el control Orden, pero lo dejo a la vista.

Cuando abro el formulario

En el evento Al cargar del formulario le digo

Private Sub Form_Load()
Me.RecordSource = "select * from Ftabla1 order by fecha"
Dim i As Integer
DoCmd.GoToRecord , , acFirst
For i = 1 To Me.Recordset.RecordCount
Orden = Me.CurrentRecord
DoCmd.RunCommand acCmdSaveRecord
Saldo = DSum("importe", "ftabla1", "fecha<=#" & Me.Fecha & "# and orden <=" & Me.Orden & "")
DoCmd.GoToRecord , , acNext
Next
End Sub

Es decir, que el origen de registros del formulario sean aquellos de la tabla ordenados por fecha. Después le digo que se vaya al primer registro, y que al control Orden le asigne el valor del registro en que está en ese momento, y que a su vez me calcule el saldo. Que repita el proceso hasta el final del formulario.

Con lo que si modificas algún valor o eliminas algún registro, cada vez que abras el formulario te "recalculará" todo. El saldo correcto lo tendrás siempre en el formulario no en la tabla, ya que en ella están ordenado por entrada no por fecha.

No va.

Me da este error

y al darle a DEPURAR es esto lo que muestra:

Yo he puesto como nombre a la tabla el nombre que he visto en el formulario, pero si la tabla se llama de otra forma, por ejemplo, Alumnos tienes que escribirlo como

Me.recordsource="select * from alumnos order by fecha"

Bueno, pues parece que hemos acertado. He hecho varias pruebas y parece que responde bien. He creado una macro asignada a un botón "al hacer click" para que cierre y abra el formulario y así se actualice. .

Una duda, en el campo "ORDEN" donde pongo el numero correlativo de registro, ¿lo tengo que poner a mano o puede ser que se actualice automáticamente a un +1 sobre el último existente?

Ah! y MUCHÍSIMAS GRACIAS por todo el trabajo que has hecho y el tiempo que me has dedicado.

No tienes que hacer nada, observa que la instrucción está en el evento al cargar del formulario. Por tanto, cada vez que abras el formulario ejecuta la instrucción. Pero también, con la tabla abierta, puedes decirle que te ordene de menor a mayor el campo Orden, con lo cual también tendrás en la tabla el saldo correcto en el último registro.

No. Lo que pregunto es si el campo ORDEN puede ser auto numérico. 
Por no tener que escribir yo el número 

Autonumérico no debe ser, ya que cuando declaras un campo autonumérico pierdes el control sobre él y si eliminas un registro, el autonumérico te marcaría que hay, por ejemplo, 15 registros cuando en realidad hay 14.

Pero, si te has fijado en el código, no hay que escribir nada en Orden. El valor lo coge automáticamente a medida que vas rellenando registros en el formulario.

Respuesta
1

Estoy de acuerdo con Julián el indicado es un formulario y es la solución y TOTALMENTE descabellado el concepto de Enrique, este señor siempre repite una respuesta o copia parte de una respuesta de otro, si no da una respuesta con solo texto "cantinflesco"

¡Gracias! 

Pues he aplicado el Procedimiento de evento en "despues de actualizar" del campo "IMPORTE" .

Esto he escrito:
Private Sub IMPORTE_AfterUpdate()
DoCmd.RunCommand acCmdSaveRecord
GRUPO4 = DSum("IMPORTE", "T Datos")
End Sub

Y no me funciona. Como resultado me da el campo vacío.

Recuerdo:

Campo "IMPORTE" es donde está el apunte de la cantidad

Campo "GRUPO4" es donde debe aparecer la suma continua.
"T Datos" es el nombre de la Tabla.

¿He hecho algo mal?

¿Pudiera tener algo que ver en que no de resultados el que los "Tipos de Datos" en la Tabla están puestos como "Moneda" ?
¿Deberían ser "Número"?

He probado cambiando los datos de esos campos a "Número" y tampoco funciona

¿Alguna idea de por qué no me funciona?

Si puede envíeme la base de datos con información ficticia a [email protected] y trato de colaborarle.

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas