Nachtstunden berechnen

DiddiGSB

Mitglied
Ich bräuchte für ein Formular eine Berechnung der Nachtstunden. (Zeiten zwischen 00:00 und 06:00 Uhr.)

Arbeite mit 2 Tabellen

tblTag

TagID
Tag (Datum)
SchichtID_F, (Fremdschlüssel aus tblSchicht)
Bemerkung (Text)

tblSchicht

SchichtID
Schicht (gibt 25 Stck)
Beginn (Uhrzeit 24St Format)
Ende (Uhrzeit 24St Format)

Die Daten werden im Formular frmArbeiten zusammen gefasst.
Dort werden auch die Anzahl der Std in einem ungebundenen Textfeld berechnet.
Nun hätte ich gerne noch das oben genannte Feld, welches mir die Summe der Nachtstunden in einem weiteren ungebunden Textfeld anzeigt.

Hat da jemand eine Idee ?

Danke im vor raus.

P.S. Arbeite mit Office 2010
 
Mit einer reinen Formel wird es sehr schwer. Ein wenig VBA ist da hilfreich

Ich habe dir mal etwas zusammengestellt

Visual Basic:
Private Type periode
    beginHour    As Integer
    endHour     As Integer
End Type

Public Function getNightHours(ByVal iBegin As Integer, ByVal iEnd As Integer) As Integer
    'Nacht definieren
    Const C_NIGHT_BEGIN As Integer = 0
    Const C_NIGHT_END As Integer = 6
    
    Dim night  As periode
    Dim shift  As periode
    
    night = createPerode(C_NIGHT_BEGIN, C_NIGHT_END)
    shift = createPerode(iBegin, iEnd)
    
    getNightHours = min(night.endHour, shift.endHour) - max(night.beginHour, shift.beginHour)
    If Sgn(getNightHours) = -1 Then getNightHours = 0
End Function

'--Hilfsfunktionen
Private Function createPerode(ByVal iBegin As Integer, ByVal iEnd As Integer) As periode
    
    With createPerode
        If iBegin > iEnd Then
            .beginHour = iBegin - 24
            .endHour = iEnd
        Else
            .beginHour = iBegin
            .endHour = iEnd
        End If
    End With

End Function

'min() und max(): http://wiki.yaslaw.info/wikka/VbVbaFunctions:
'/**
' * Gibt den Höheren von 2 Werten zurück
' * @param  Variant     Wert 1
' * @param  Variant     Wert 2
' * @return Variant     der Grössere Wert
' */
Public Function max(ByVal iValue1 As Variant, ByVal iValue2 As Variant) As Variant
    If iValue1 > iValue2 Then
        max = iValue1
    Else
        max = iValue2
    End If
End Function

'/**
' * Gibt den Tieferen von 2 Werten zurück
' * @param  Variant     Wert 1
' * @param  Variant     Wert 2
' * @return Variant     der Kleinere Wert
' */
Public Function min(ByVal iValue1 As Variant, ByVal iValue2 As Variant) As Variant
    If iValue1 < iValue2 Then
        min = iValue1
    Else
        min = iValue2
    End If
End Function


Das kannst du jetzt aus dem Formular so aufrufen
Code:
=getNightHours(Hour([begin]);Hour([ende]))
Beziehungsweise so im Header für die gesammtsumme
=Sum(getNightHours(Hour([begin]);Hour([ende])))
 
Hi Yaslaw

danke für deine Antwort und die Hilfe.
Habe deinen Vorschlag mal eingepflegt und klappt fast.
Ich bekomme wenn ich mein ungebundenes Feld nicht formatiere, den Wert als einfache Zahl wieder.

Beispiel.

Beginn 17:33
Ende 01:39
Wert = 1

Normalerweise wären das 1 Std und 39 Min.

Formatiere ich das Feld nun als Zeit 24 Std, bekomme ich den Wert 00:00 zurück.

P.S.

Ich kann kein VB, habe da Null Plan von.
 
oh, du arbeitest mit Minuten. Dann muss man meine Formeln anpassen. Die folgende Formeln arbeitet nicht mehr mit Stunden sondern mit Sekunden

Du kannst leider in Access nicht mehr als 24 Stunden als Time rechnen Ich habe darum das ganze so umgeschrieben, dass das Resultat als String zurückgegeben wird
zb: 37:30:05

Code:
//Aufurf in einem Feld im Detail-bereich:
=getNightHours([begin];[ende])

//Aufurf im Header-Bereich (also die Summe)
=convertSecoundsToTimeString(Sum(getNightHoursInSec([begin];[ende])))

und hier das Module
Visual Basic:
Option Compare Database

Private Type periode
    begin   As Variant
    end     As Variant
End Type

Private Const C_DAY_IN_SEC As Long = 86400
'
Public Function getNightHours(ByVal iBegin As Date, ByVal iEnd As Date) As String
    getNightHours = convertSecoundsToTimeString(getNightHoursInSec(iBegin, iEnd))
End Function
Public Function getNightHoursInSec(ByVal iBegin As Date, ByVal iEnd As Date) As Variant
    'Nacht definieren
    Const C_NIGHT_BEGIN = "00:00:00"
    Const C_NIGHT_END = "06:00:00"
    
    Dim night  As periode
    Dim shift  As periode
    Dim secounds As Long
    
    night = createPerode(C_NIGHT_BEGIN, C_NIGHT_END)
    shift = createPerode(iBegin, iEnd)
    
    getNightHoursInSec = min(night.end, shift.end) - max(night.begin, shift.begin)
    If Sgn(getNightHoursInSec) = -1 Then getNightHoursInSec = 0
End Function

'/**
' * Erstellt eine Zeit-Periode
' * @param  Date    Startzeit Time(hh:nn:ss)
' * @param  Date    Endzeit Time(hh:nn:ss)
' * @return periode
' */
Private Function createPerode(ByVal iBegin As Date, ByVal iEnd As Date) As periode
    
    With createPerode
        .begin = convertTimeToSecounds(iBegin)
        .end = convertTimeToSecounds(iEnd)
        'Falls die Startzeit hinter der Endzeit liegt, den Wert degieren (Periode geht über Mitternacht)
        If iBegin > iEnd Then .begin = .begin - C_DAY_IN_SEC
    End With

End Function

'/**
' * Konvertiert Time (hh:nn:ss) in Sekunden
' * @param  Date    Time(hh:nn:ss)
' * @return Long    Anzahl Sekunden
' */
Public Function convertTimeToSecounds(ByVal iTime As Date) As Variant
    convertTimeToSecounds = DateDiff("s", CDate("00:00:00"), iTime)
End Function

'/**
' * Konvertiert Sekunden in Time (hh:nn:ss)
' * @param  Date    Anzahl Sekunden
' * @return Long    Time(hh:nn:ss)
' */
Public Function convertSecoundsToTimeString(ByVal iSecounds As Variant) As String
    Dim time As Date
    Dim dateInHours As Variant
    
    time = Format(iSecounds / C_DAY_IN_SEC, "dd.mm.yyyy hh:nn:ss")
    dateInHours = Fix(iSecounds / C_DAY_IN_SEC)
    convertSecoundsToTimeString = dateInHours + Hour(time) & ":" & Format(time, "nn:ss")
End Function

'/**
' * Gibt den Höheren von 2 Werten zurück
' * @param  Variant     Wert 1
' * @param  Variant     Wert 2
' * @return Variant     der Grössere Wert
' */
Private Function max(ByVal iValue1 As Variant, ByVal iValue2 As Variant) As Variant
    If iValue1 > iValue2 Then
        max = iValue1
    Else
        max = iValue2
    End If
End Function

'/**
' * Gibt den Tieferen von 2 Werten zurück
' * @param  Variant     Wert 1
' * @param  Variant     Wert 2
' * @return Variant     der Kleinere Wert
' */
Private Function min(ByVal iValue1 As Variant, ByVal iValue2 As Variant) As Variant
    If iValue1 < iValue2 Then
        min = iValue1
    Else
        min = iValue2
    End If
End Function
 
Hi,

ich weiß schon warum ich VB nicht mag.

Bekomme einen Syntaxfehler beim kompelieren.

Zitat:

In diesem Visual Basic Modul liegt ein Syntax-Fehler vor.

Mal schauen ob ich es selber finde

Nochmals Danke
 
Ist mit Access 2003 geschrieben und kompiliert.
Ich kanns am Montag im Büro noch mit Access 2007 kompilieren.

Nachtrag:
Auch mit Access 2007 gehts.
Access 2010 habe ich nicht zur Verfügung
 
Ummm, denke ich jetzt mit meinem VBA-Ansatz zu sehr um die Ecke?

Visual Basic:
    Zeits = DateDiff("s", "30.01.2012 00:00:00", "30.01.2012 05:35:20")
    
    Zeith = Zeits \ 3600
    
    Zeitm = Zeits - Zeith * 3600
        
    Zeitm = Zeitm \ 60
    
    Zeitsec = Zeits - Zeith * 3600 - Zeitm * 60

    Debug.Print Zeits

    Debug.Print "Stunden: " & Zeith

    Debug.Print "Minuten: " & Zeitm
    
    Debug.Print "Sekunden: " & Zeitsec

ergibt
Stunden: 5
Minuten: 35
Sekunden: 20
 
Nunja, ich versuchte in meiner Lösung auch die folgenden Fälle Abzudecken:
- Die Schicht beginnt um 22 Uhr und Endet um 4 Uhr Morgens
- Die Definition der Nacht startet im 23 Uhr und endet um 6 Uhr Morgens

Darum ist die Rechnung etwas komplexer geraten
 
- Die Schicht beginnt um 22 Uhr und Endet um 4 Uhr Morgens
- Die Definition der Nacht startet im 23 Uhr und endet um 6 Uhr Morgens

Darum ist die Rechnung etwas komplexer geraten

Wie kommst du denn da drauf?

Ich bräuchte für ein Formular eine Berechnung der Nachtstunden. (Zeiten zwischen 00:00 und 06:00 Uhr.)

Das einzige was er noch zur Abgrenzung bräuchte ist:
Schichtbeginn vor 24:00 Uhr wird auf 00:00 Uhr nächstes Tagesdatum verschoben, Schichtende falls grösser 06:00 auf 06:00 Uhr

Und dann die DateDiff oben in meinem Beispiel.
 
Jepp, ich weiss.
Das ist der Stand heute - Sorry, ich mache möglichst immer allgemeingültige Lösungen die nicht beim ersten Managerfurz (und solche gibts nach meinen Erfahrungen am mehr als man Zeit hat sie umzusetzen) gleich neu programmiert werden müssen.

Ob das mit dem Schichtende und Schichtanfang so ist, ist halt eine Frage wie es im System drin ist - aber der Ansatz ist nicht schlecht, dass man einfach aus einer Schicht 2 macht zum berechnen. Darauf könnte man aufbauen.
 
Zurück