1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies. Weitere Informationen

[Access] Nachtstunden berechnen

Dieses Thema im Forum "Office-Anwendungen" wurde erstellt von DiddiGSB, 28. Januar 2012.

  1. DiddiGSB

    DiddiGSB Grünschnabel

    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
  2. Yaslaw

    Yaslaw n/a Moderator

    Mit einer reinen Formel wird es sehr schwer. Ein wenig VBA ist da hilfreich

    Ich habe dir mal etwas zusammengestellt

    Code (Visual Basic):
    1. Private Type periode
    2.     beginHour    As Integer
    3.     endHour     As Integer
    4. End Type
    5.  
    6. Public Function getNightHours(ByVal iBegin As Integer, ByVal iEnd As Integer) As Integer
    7.     'Nacht definieren
    8.    Const C_NIGHT_BEGIN As Integer = 0
    9.     Const C_NIGHT_END As Integer = 6
    10.    
    11.     Dim night  As periode
    12.     Dim shift  As periode
    13.    
    14.     night = createPerode(C_NIGHT_BEGIN, C_NIGHT_END)
    15.     shift = createPerode(iBegin, iEnd)
    16.    
    17.     getNightHours = min(night.endHour, shift.endHour) - max(night.beginHour, shift.beginHour)
    18.     If Sgn(getNightHours) = -1 Then getNightHours = 0
    19. End Function
    20.  
    21. '--Hilfsfunktionen
    22. Private Function createPerode(ByVal iBegin As Integer, ByVal iEnd As Integer) As periode
    23.    
    24.     With createPerode
    25.         If iBegin > iEnd Then
    26.             .beginHour = iBegin - 24
    27.             .endHour = iEnd
    28.         Else
    29.             .beginHour = iBegin
    30.             .endHour = iEnd
    31.         End If
    32.     End With
    33.  
    34. End Function
    35.  
    36. 'min() und max(): [url]http://wiki.yaslaw.info/wikka/VbVbaFunctions:[/url]
    37. '/**
    38. ' * Gibt den Höheren von 2 Werten zurück
    39. ' * @param  Variant     Wert 1
    40. ' * @param  Variant     Wert 2
    41. ' * @return Variant     der Grössere Wert
    42. ' */
    43. Public Function max(ByVal iValue1 As Variant, ByVal iValue2 As Variant) As Variant
    44.     If iValue1 > iValue2 Then
    45.         max = iValue1
    46.     Else
    47.         max = iValue2
    48.     End If
    49. End Function
    50.  
    51. '/**
    52. ' * Gibt den Tieferen von 2 Werten zurück
    53. ' * @param  Variant     Wert 1
    54. ' * @param  Variant     Wert 2
    55. ' * @return Variant     der Kleinere Wert
    56. ' */
    57. Public Function min(ByVal iValue1 As Variant, ByVal iValue2 As Variant) As Variant
    58.     If iValue1 < iValue2 Then
    59.         min = iValue1
    60.     Else
    61.         min = iValue2
    62.     End If
    63. End Function

    Das kannst du jetzt aus dem Formular so aufrufen
    Code (Text):
    1. =getNightHours(Hour([begin]);Hour([ende]))
    2. Beziehungsweise so im Header für die gesammtsumme
    3. =Sum(getNightHours(Hour([begin]);Hour([ende])))
  3. DiddiGSB

    DiddiGSB Grünschnabel

    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.
  4. Yaslaw

    Yaslaw n/a Moderator

    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 (Text):
    1. //Aufurf in einem Feld im Detail-bereich:
    2. =getNightHours([begin];[ende])
    3.  
    4. //Aufurf im Header-Bereich (also die Summe)
    5. =convertSecoundsToTimeString(Sum(getNightHoursInSec([begin];[ende])))
    und hier das Module
    Code (Visual Basic):
    1. Option Compare Database
    2.  
    3. Private Type periode
    4.     begin   As Variant
    5.     end     As Variant
    6. End Type
    7.  
    8. Private Const C_DAY_IN_SEC As Long = 86400
    9. '
    10. Public Function getNightHours(ByVal iBegin As Date, ByVal iEnd As Date) As String
    11.     getNightHours = convertSecoundsToTimeString(getNightHoursInSec(iBegin, iEnd))
    12. End Function
    13. Public Function getNightHoursInSec(ByVal iBegin As Date, ByVal iEnd As Date) As Variant
    14.     'Nacht definieren
    15.    Const C_NIGHT_BEGIN = "00:00:00"
    16.     Const C_NIGHT_END = "06:00:00"
    17.    
    18.     Dim night  As periode
    19.     Dim shift  As periode
    20.     Dim secounds As Long
    21.    
    22.     night = createPerode(C_NIGHT_BEGIN, C_NIGHT_END)
    23.     shift = createPerode(iBegin, iEnd)
    24.    
    25.     getNightHoursInSec = min(night.end, shift.end) - max(night.begin, shift.begin)
    26.     If Sgn(getNightHoursInSec) = -1 Then getNightHoursInSec = 0
    27. End Function
    28.  
    29. '/**
    30. ' * Erstellt eine Zeit-Periode
    31. ' * @param  Date    Startzeit Time(hh:nn:ss)
    32. ' * @param  Date    Endzeit Time(hh:nn:ss)
    33. ' * @return periode
    34. ' */
    35. Private Function createPerode(ByVal iBegin As Date, ByVal iEnd As Date) As periode
    36.    
    37.     With createPerode
    38.         .begin = convertTimeToSecounds(iBegin)
    39.         .end = convertTimeToSecounds(iEnd)
    40.         'Falls die Startzeit hinter der Endzeit liegt, den Wert degieren (Periode geht über Mitternacht)
    41.        If iBegin > iEnd Then .begin = .begin - C_DAY_IN_SEC
    42.     End With
    43.  
    44. End Function
    45.  
    46. '/**
    47. ' * Konvertiert Time (hh:nn:ss) in Sekunden
    48. ' * @param  Date    Time(hh:nn:ss)
    49. ' * @return Long    Anzahl Sekunden
    50. ' */
    51. Public Function convertTimeToSecounds(ByVal iTime As Date) As Variant
    52.     convertTimeToSecounds = DateDiff("s", CDate("00:00:00"), iTime)
    53. End Function
    54.  
    55. '/**
    56. ' * Konvertiert Sekunden in Time (hh:nn:ss)
    57. ' * @param  Date    Anzahl Sekunden
    58. ' * @return Long    Time(hh:nn:ss)
    59. ' */
    60. Public Function convertSecoundsToTimeString(ByVal iSecounds As Variant) As String
    61.     Dim time As Date
    62.     Dim dateInHours As Variant
    63.    
    64.     time = Format(iSecounds / C_DAY_IN_SEC, "dd.mm.yyyy hh:nn:ss")
    65.     dateInHours = Fix(iSecounds / C_DAY_IN_SEC)
    66.     convertSecoundsToTimeString = dateInHours + Hour(time) & ":" & Format(time, "nn:ss")
    67. End Function
    68.  
    69. '/**
    70. ' * Gibt den Höheren von 2 Werten zurück
    71. ' * @param  Variant     Wert 1
    72. ' * @param  Variant     Wert 2
    73. ' * @return Variant     der Grössere Wert
    74. ' */
    75. Private Function max(ByVal iValue1 As Variant, ByVal iValue2 As Variant) As Variant
    76.     If iValue1 > iValue2 Then
    77.         max = iValue1
    78.     Else
    79.         max = iValue2
    80.     End If
    81. End Function
    82.  
    83. '/**
    84. ' * Gibt den Tieferen von 2 Werten zurück
    85. ' * @param  Variant     Wert 1
    86. ' * @param  Variant     Wert 2
    87. ' * @return Variant     der Kleinere Wert
    88. ' */
    89. Private Function min(ByVal iValue1 As Variant, ByVal iValue2 As Variant) As Variant
    90.     If iValue1 < iValue2 Then
    91.         min = iValue1
    92.     Else
    93.         min = iValue2
    94.     End If
    95. End Function
  5. DiddiGSB

    DiddiGSB Grünschnabel

    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
  6. Yaslaw

    Yaslaw n/a Moderator

    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
  7. Zvoni

    Zvoni Erfahrenes Mitglied

    Ummm, denke ich jetzt mit meinem VBA-Ansatz zu sehr um die Ecke?

    Code (Visual Basic):
    1.  
    2.  
    3.     Zeits = DateDiff("s", "30.01.2012 00:00:00", "30.01.2012 05:35:20")
    4.    
    5.     Zeith = Zeits \ 3600
    6.    
    7.     Zeitm = Zeits - Zeith * 3600
    8.        
    9.     Zeitm = Zeitm \ 60
    10.    
    11.     Zeitsec = Zeits - Zeith * 3600 - Zeitm * 60
    12.  
    13.     Debug.Print Zeits
    14.  
    15.     Debug.Print "Stunden: " & Zeith
    16.  
    17.     Debug.Print "Minuten: " & Zeitm
    18.    
    19.     Debug.Print "Sekunden: " & Zeitsec
    20.  
    ergibt
    Stunden: 5
    Minuten: 35
    Sekunden: 20
  8. Yaslaw

    Yaslaw n/a Moderator

    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
  9. Zvoni

    Zvoni Erfahrenes Mitglied

    Wie kommst du denn da drauf?

    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.
  10. Yaslaw

    Yaslaw n/a Moderator

    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.
  11. Zvoni

    Zvoni Erfahrenes Mitglied

    Uh ja, willkommen im Club. Hab gerade sowas an der Backe.

    Stichwort: CTI-Software an Telefonanlage *GROLL*
  12. DiddiGSB

    DiddiGSB Grünschnabel

    Hi Yaslaw

    Sorry das ich erst jetzt antworte, Stress auf der Arbeit gehabt.

    Der Fehler lag bei mir, sorry. Hatte es als Modul gespeichert. :(



    Danke noch mal. ;-)

Diese Seite empfehlen