Molto tempo fa avevo elaborato una "funzione" per questi calcoli, che corrisponde al seguente codice:
- Codice: Seleziona tutto
Function Termine(ByVal Durata As Double, ByVal via As Double, ByRef tt As Range, Optional SabY = 0, Optional ByRef Holid As Range) As Double
'Data una "durata" in [hh]:mm:ss, una data/ora di inizio, e un orario di lavoro,
' calcola la data/ora di conclusione (di una attivita')
'L' orario deve essere su 4 celle adiacenti in verticale:
' orario di inizio
' orario di fine mattutino
' orario inizio pom
' orario di fine
' Il secondo turno NON si considera lavorato di sabato
Dim HGGstd As Double
Dim HSab As Double
Dim ElapTot As Double
Dim ElapD0 As Double
Dim Interv As Double
Dim HStart As Double
Dim hPom As Double
Dim DDay As Integer
Dim GSet As Integer
Dim Extra As Double
'Calcolo ore oggi
'Dura = Range("A1").Value
Interv = tt.Offset(2, 0) - tt.Offset(1, 0)
HGGstd = tt.Offset(3, 0).Value - tt - tt.Offset(2, 0).Value + tt.Offset(1, 0).Value
If SabY = 1 Then HSab = tt.Offset(1, 0).Value - tt Else HSab = 0
'HStart = Range("A2") - Int(Range("A2"))
HStart = via - Int(via)
If HStart < tt Then HStart = tt
If HStart > tt.Offset(3, 0) Then HStart = tt.Offset(3, 0)
If HStart > tt.Offset(1, 0) And Application.WorksheetFunction.Weekday(via, 2) = 6 Then HStart = tt.Offset(3, 0)
If HStart > tt.Offset(1, 0) And HStart < tt.Offset(2, 0) Then HStart = tt.Offset(2, 0)
If HStart > tt.Offset(3, 0) Then HStart = tt.offest(3, 0)
ElapD0 = tt.Offset(3, 0).Value - HStart
If HStart < tt.Offset(2, 0) Then ElapD0 = ElapD0 - Interv
If Application.WorksheetFunction.Weekday(via, 2) = 7 Then ElapTot = 0 Else ElapTot = ElapD0
DDay = 1
While Round(ElapTot * 1000000) < Round(Durata * 1000000)
If Application.WorksheetFunction.CountIf(Holid, Int(via) + DDay) > 0 Then GoTo SkipF
' If IsError(Application.WorksheetFunction.Lookup(Int(via) + DDay, Holid)) Then GoTo SkipF
GSet = Application.WorksheetFunction.Weekday(via + DDay, 2)
If GSet < 6 Then ElapTot = ElapTot + HGGstd
If GSet = 6 Then ElapTot = ElapTot + HSab
SkipF:
DDay = DDay + 1
If DDay > 1000 Then ElapTot = Durata
Wend
If GSet = 6 Then hPom = tt.Offset(1, 0) - tt Else hPom = tt.Offset(3, 0) - tt.Offset(2, 0)
Extra = Round(ElapTot * 1000000 - Durata * 1000000) / 1000000
If Extra > hPom Then Extra = ElapTot - Durata + Interv 'Else Extra = ElapTot - Durata
Termine = Int(via) + DDay - 1 + tt.Offset(3, 0) - Extra
If Application.WorksheetFunction.Weekday(via + DDay - 1, 2) = 6 Then Termine = Termine - (tt.Offset(3, 0) - tt.Offset(2, 0) + Interv)
'
End Function
E' gia' tradotto in brasilero
Uso:
-da Excel, Alt-F11 per aprire l' editor delle macro
-Menu /Inserisci /Modulo
-Copia il codice e incollalo nel frame vuoto di dx
Torna su excel, e in un' area libera segna in verticale in 4 celle contigue gli orari di lavoro, nel formato Ingresso/Uscita, Ingresso/Uscita (nel tuo caso quindi sara' 6:00/14:00, 14:00/22); il secondo turno NON si considera lavorativo nei sabato. Io ho usato L2:L5.
In un' altra area libera segna il calendario dei giorni festivi (data completa, es 15/08/2013, non basta il solo 15/08; quindi il calendario dei giorni festivi del 2013 va riscritto per il 2014); io ho usato M2:M20.
A questo punto userai una formula tipo
- Codice: Seleziona tutto
=Termine(OreDiDurata;DataOraAvvio;PrimaCellaOrarioLavorativo;SabatoSi/SabatoNo;AreaFestivi)
SabatoSi/SabatoNo corrisponde ai valori 1/0.
Quindi se la data/ora di inizio fosse in A2, le ore di durata in B2, e vuoi considerare il sabato lavorato (solo primo gruppo di timbrature) la formula sarebbe
- Codice: Seleziona tutto
=Termine(B2;A2;L2;1;M2:M20)
La cella va formattata come Data & Ora
Prova e fai sapere, ciao.
Edit 19-3-2013
Ho corretto la formula "tipo" (OreDiDurata /DataOraAvvio erano erroneamente invertite nella parentesi), mentre quella dell' esempio era invece corretta