Suma total de horas en agrupación de informe

Imparto clases a alumnos y quisiera saber cómo conseguir que un informe de Access me sume el nº total de horas que realiza cada alumno por cada curso. Para ello tengo una tabla en la que recojo los siguientes datos:

DNI del alumno

FECHA de la jornada formativa

HORA ENTRADA

HORA SALIDA

Hora real inicio de la jornada

Hora real final de la jornada

Los campos HORA, todos tienen el formato Hora larga.

La hora de entrada hace referencia al fichaje de entrada/salida de los alumnos y la hora real es la hora de inicio/salida de la jornada formativa, evidentemente, los alumnos suelen fichar siempre antes del inicio de la jornada formativa, salvo los que llegan tarde, y lo mismo ocurre en la salida, ya que en ocasiones se van antes de la hora de salida.

Una vez recogidos los datos creo una consulta para la entrada y otra para la salida que luego uno en una nueva consulta con la información ya agrupada con los diferentes días que cada alumno asiste y sus respectivos horarios de entrada y salida, tanto los fichajes como el horario real de la jornada. En esta nueva consulta añado 2 nuevos campos de hora a los que se puede llamar HORA FINAL y que son los que generan la hora real de entrada y la hora real de salida ajustadas al horario real de inicio/fin de la jornada formativa. Posteriormente añado un nuevo campo al que llamo Diferencia y en el que lo que hago es restar la hora de entrada a la hora de salida con el fin de ver el tiempo total de asistencia a la jornada formativa:

Ejemplo:

La jornada formativa se inicia a las 9:00 y finaliza a las 14:00

Pepe ficha de entrada a las 9:05 y ficha de salida a las 14:01

El campo calculado Diferencia me dice que Pepe ha asistido 4 horas y 55 min. Ya que ha empezado 5 min. Tarde.

Con esta consulta, creo un informe que agrupo por DNI (encabezamiento). En este agrupamiento, incluyo el DNI, y en el detalle incluyo la fecha a la que asiste, la hora final de entrada, la hora final de salida y la diferencia.

Luego, incluyo una nueva agrupación del DNI (pie), con el objeto de sumar el campo Diferencia, y es aquí donde surge el problema ya que no hay forma de contabilizar este campo.

He intentado con dos opciones y ninguna me funciona:

Opción A: =Suma([Diferencia])

Opción B: =Suma([Horafinalsalida]-[Horafinalentrada])

2 Respuestas

Respuesta
1

Cualquiera de las opciones funciona bien, pero se limitaran a un periodo de 24 horas (un día) siguiendo las reglas consensuadas.

Access sumara con las reglas consensuadas en las que cada 60 segundos suman un minuto, cada 60 minutos una hora, cada 24 horas un día, cada xx días un mes y cada 12 meses un año.

Un remedio que se suele aplicar es convertir a un solo tipo de datos (en este caso lo adecuado serian minutos), sumar sin problemas los minutos (ya no hay el limite de 60 minutos) y obtenida la cifra final presentar el resultado como sea adecuado (por ejemplo200 horas y 22 minutos).

Para obtener los intervalos (duración de la clase) se puede aplicar la función DateDiff que devuelve la diferencia entre los dos datos (entrada/salida) en el tipo de intervalo que se le indique (segundos, minutos, horas ...).

Queda el problema de aquellos que no indican la hora de entrada (llegan tarde), se podría sustituir por el limite máximo permitido (digamos que la decima parte de la duración de la clase) esto es, si llega tarde solo 'se le admitiría' si el retardo no supera los seis minutos (o doce o ...), independiente del tiempo, se le aplicaría ese retraso, al que no 'anote ' su salida o bien se le aplica la hora oficial o la del que marco la mas alta (que seria el final de la clase).

Esta parte es la que se tiene que tener muy clara antes de generar las sumas (y es independiente de contabilizar faltas o retrasos).

Hola Enrique.

Como verás en el ejemplo que le he puesto a Eduardo, el problema está en la suma del grupo. En este caso, he utilizado la función Suma: =Suma([Diferencia]) y el resultado debería ser muy similar para los tres DNIs, y en cambio, el resultado que me sale es muy diferente y no entiendo por qué.

He utilizado esta suma en muchas ocasiones con datos numéricos y nunca he tenido problemas por lo que entiendo que el problema está en la suma de las horas. 

Te adjunto una imagen del diseño del informe. Observarás que tengo puesto la suma continua "sobre todo", pero he probado las tres opciones que ofrece y con ninguna se soluciona el problema.

Acabo de ver lo que has posteado (siguiendo las indicaciones) y en nada niega mi exposición, es mas la consolida.

Dado que se utilizan los segundos (mas fidelidad), los datos del DNI1 son estos:
Horas ... Segundos
0:29:42 ... 1782
8:29:23 ... 30563
8:30:00 ... 30600
8:30:00 ... 30600
8:30:00 .........    30600

Lo que arroja un total de 124145 segundos y en formato 'natural'
1 día 10 horas 29 minutos y cinco segundos

Si a la suma le 'creamos' un formato utilizando la división entera (\) y el resto (Mod) queda así:

Para las horas: la división entera de los segundos por 3600 (60 segundos * 60 minutos)

124145 \ 3600 = 34

Para los minutos: se hace una división entera con el resto de las horas por 60 (segundos)

(124145 Mod 60) \60 = 29

Los segundos: simplemente el resto de los minutos 

124145 mod 60

En una línea: (los segundos en una variable TSegundos)

TSegundos\3600 & ":" & Format((TSegundos Mod 3600)\60,"00") & ":" & Format(TSegundos Mod 60,"00")
34:29:05

Hola Enrique.

En la consulta que alimenta el informe he convertido el horario en segundos y de esta manera ya me contabiliza el total que necesitaba en el informe ya que por la causa que sea, sí realiza la suma correcta en segundos.

Una vez en el informe intento volver a convertir los segundos en hh:mm:ss, siguiendo tus pasos pero aunque la conversión en horas y segundos es correcta, la conversión en minutos no me sale bien, ya que en lugar de salirme 29, me sale 0; aplico la siguiente función:

=Format(([Texto26] Mod 60)\60;"00"), Donde Texto26 es el campo ubicado en el pie del DNI y en el que se realiza la suma de los segundos: =Suma([Seg])

¿Cuál es el referente utilizado par el resto de los cálculos?, porque las matemáticas suelen ofrecer el mismo resultado con los mismos datos (el clásico 2 + 2 = 4).

Se parte del concepto de que una división tiene dividendo, divisor, cociente y resto.

La división puede ser entera (\) o la clásica con decimales (/).

La parte entera se obtiene así: Dividendo \ Divisor

EL resto así: Dividendo Mod Divisor

Una hora tiene 60 minutos * 60 segundos (3.600 unidades)

Un minuto tiene 60 segundos (60 unidades)

Se obtienen las horas en base a lo anterior : TSegundos \ (60 * 60) ==>> TSegundos \3600

EL resto de segundos (en el que están comprendidos los minutos y segundos sobrantes) así:
TSegundos Mod 3600

De esta cantidad (el sobrante) deseamos los minutos: (TSegundos mod 3600) \ 60

Verifica este calculo: estas aplicado obtener los minutos no las horas:
=Format(([Texto26] Mod 60)\60;"00"),

Para obtener los segundos se puede utilizar Mod con la formula anterior, pero nada impide utilizar el total (TSegundos) como dividendo y 60 como factor en para Mod.

En base a que los resultados se presentan individualmente, un formato especifico se lo aplicaría al cuadro de texto (no al calculo)

En el calculo se utiliza para presentar los datos en/como conjunto y que respete el formato clásico de dos cifras rellenando con ceros si no se alcanza la decena.

He revisado el hilo y reconozco que el error que delatas ha sido culpa mía al reconstruir los ejemplos traduciendo los datos que utilice.
Para dejarlo mas claro utilizare variables para los grupos

Se calcula en segundos, por lo que los segundos serán el resto final y a la vez la unidad

Para obtener las horas, la referencia es el numero de segundos que tiene una hora.

Para obtener los minutos, la referencia es el numero de segundos que tiene un minuto.

Tiempo = numero total de segundos

DVHora = 60 *60 = 3600

DVMinuto =60

Horas_Finales = Tiempo \ DVHora

El resto que no alcanza la hora será:
Tiempo Mod DVHora

Los minutos se obtienen al igual que las horas, pero con el resto de minutos que quedaron de la división entera:
Minutos_finales = (Tiempo Mod DVHora) \ DVMinuto

El calculo se los segundos podría utilizar el resto del calculo anterior, pero siendo la unidad de referencia se puede hacer el calculo directo sin importar si los minutos son 1, 59 o 2222, en cualquier caso seran segundos:

Segundos_finales = Tiempo Mod DvMinuto

Y siento que se me pasase desapercibido la trasferencia errónea del calculo de los minutos en el primer ejemplo (no en el calculo en una línea):

(124145 Mod 3600) \60 = 29

TSegundos =124145

?TSegundos\3600 & " Horas " & Format((TSegundos Mod 3600)\60,"00 \m\i\n\u\t\o\s") & Format(TSegundos Mod 60,"\ \y 00 \s\e\g\u\n\d\o\s")
34 Horas 29 minutos y 05 segundos
Respuesta
2

Juan Antonio le dejo este link de una respuesta que presenté anteriormente a Martha.

Determinar tiempo laborado agrupado con una consulta

Feliz año.

Ahora si quiere un ejemplo sencillo para liquidar horas, le dejo este ejemplo

Son 2 formas de liquidar horas, cuando se graban en formato decimal y otra, en formato hh:mm. Solo hay una diferencia porque tomo la hora de salida y en su caso debe ser 14:00, en este caso sería hacer el ajuste, algo como:

IF hora_salida>14:00 then

   hora_salida=14:00 

End If

Puede solicitar este ejemplo a [email protected] 

Hola Eduardo.

El problema no lo tengo a la hora de realizar la diferencia de horas entre la entrada y la salida, sino en el total que debo realizar en el agrupamiento por DNI. Igualmente, en ningún caso se me va a dar la circunstancia de que la formación termine más allá de las 12PM, por lo que no me veré afectado por el salto de las 24 horas.

Un saludo

Te adjunto una imagen del resultado que me sale a mi.

Creo que esto es lo que quiere.

Si quiere envíeme su base de datos con información ficticia y la reviso porque puede variar el uso de las funciones de acuerdo como haya definido los campos. Mi correo es [email protected] 

Sí, correcto, eso es lo que estoy buscando. Te envío la BBDD.

Un saludo

Esta es la solución

Le envíe el archivo editado a su correo.

Que pena parece que envíe la base de datos a un correo equivocado, me puede suministrar su correo para enviarle la base de datos.

Veo que no tiene claro la forma como hago la sumatoria del tiempo. Observe este reporte

En los totales NO necesita Suma continua. Para su caso con la función 1 es suficiente.

FUNCIONES

Function tiempoencadena(Interval As Double) As String
    tiempoencadena = DateDiff("h", 0, Interval) & _
                   Format$(Interval, ":nn:ss")
End Function
Public Function a_hora(fracc As Double)
 'Retorna una fracción de tiempo en fomato hh:mm:ss
 'En donde fracc puede ser la sumatoria de tiempos en decimal
a_hora = Format(Int(fracc / 3600), "00") & ":" & _
Format(Int((fracc - (Int(fracc / 3600) * 3600)) / 60), "00") & _
":" & Format(((fracc Mod 60)), "00")
End Function

Esta forma aplica igualmente para formularios. Lo más sencillo es utilizar la primera función, no obstante, la segunda es en caso de que se haya pasado el tiempo en decimales.

Hola Eduardo.

Te acabo de enviar mi correo e intentaré aplicar tu solución, pero la programación y yo no nos llevamos muy bien.

Ya le envíe la base de datos a su correo. No olvide valorar la respuesta.

Si utiliza la función tiempoencadena() no es necesario pasar el tiempo en segundos, para que se complica. Ahora si convierte el tiempo en segundos puede obtener el mismo resultado con la función a_hora(), por ejemplo

¿

? A_hora(124145) retorna 34:29:05

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas