Partendo da richiesta formulata in altra discussione (vedi
viewtopic.php?f=26&t=100803&p=582374#p582274) ho modificato totalmente la funzione Termine con nuove prestazioni:
-possibilita' di dichiarare orari di lavoro fino a 10 periodi Entr/Usc al giorno
-possibilita' di dichiarare orari di lavoro per ogni giorno della settimana
-possibilita' di dichiarare un elenco di festivita' e l' orario di lavoro per le festivita'
La nuova funzione si chiama termineXA e corrisponde al seguente codice:
- Codice: Seleziona tutto
Function TermineXA(ByVal Durata As Double, ByVal Via As Double, ByRef TT As Range, _
Optional ByRef Holid As Range, Optional ByRef AllTable As Range) As Variant
'V 3.0 B31221 by Anthony
'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 e' definito separatamente per i giorni settimanali: 1=Lun, 2= Mart,... 7=Dom
' la tabella orari e' organizzata come segue
' 1 6 7 10 '1="dal Lunedì in avanti"; 6="dal Sab in avanti"; ... 10=Festivi
' Entr Entr Entr Entr
' Usc Usc Usc Usc
' Entr Entr Entr Entr
' Usc Usc Usc Usc
' ... ... ... ...
'MAX 10 blocchi Entr/Usc; se blocco vuoto=non si lavora
'
'Esempio di Uso:
' =TermineXA(OreDurataTask;DataOraDiInizio;IntestazioneTabellaOrari;RangeFestivita'[;Opzionale:TabellaOrari])
' Ore e Date vanno indicate come Ore e Date nel formato Excel
'
Dim CDay As Long, mWTT, CDTT As Range, I As Long, MinMatch, RowSt As Long, MinTask As Long, MinScr As Long
Dim EndMin As Double, J As Long, CDTRec As Long, CDStart As Double
'
Const MaDay As Long = 24 * 60
MinTask = Durata * MaDay
If MinTask > (500 * 60) Then TermineXA = CVErr(xlErrNA): Exit Function
'
'Gestisci Holid opzionale:
If Holid Is Nothing Then
Set Holid = TT
End If
'
For J = 1 To 200
CDay = Application.WorksheetFunction.Weekday(Via, 2)
If Application.WorksheetFunction.CountIf(Holid, Int(Via)) > 0 Then CDay = 10 'caso festivo
mWTT = Application.Match(CDay, TT, True)
Set CDTT = Range(TT.Cells(1, mWTT).Offset(1, 0), TT.Cells(1, mWTT).End(xlDown)) 'current day timetable
If CDTT.Rows.Count <= 20 Then
CDTRec = Application.WorksheetFunction.CountA(CDTT)
CDStart = (CDTT.Cells(1, 1).Value * MaDay)
For I = (Via - Int(Via)) * MaDay To MaDay
If I >= CDStart Then
MinMatch = Application.Match(I / MaDay, CDTT, True)
If MinMatch Mod 2 = 1 Then
MinScr = MinScr + 1
Else
If MinMatch >= CDTRec Then Exit For
End If
If MinScr >= MinTask Then
EndMin = (I + 1) / MaDay
GoTo EndF
End If
End If
Next I
End If
Via = Int(Via) + 1
Next J
'
EndF:
TermineXA = Int(Via) + EndMin
'max circa 200 gg
If J >= 200 Then
TermineXA = CVErr(xlErrNA)
End If
End Function
La funzione va richiamata con una formula del tipo
- Codice: Seleziona tutto
=TermineXA(OreDurataTask;DataOraDiInizio;IntestazioneTabellaOrari[;RangeFestivita'[;Opzionale:TabellaOrari]])
Ad esempio
- Codice: Seleziona tutto
=TermineXA(B2;A2;E1:H1;K1:K12;E2:H9)
(in B3 nell' immagine):
![Immagine](https://i.postimg.cc/tC9Y9TL8/DENIEL69-01.jpg)
La formula e' inserita in B3; in B6:B12 e' riportato lo split di come le 24h30min sono posizionate nelle varie date tra inizio e termine.
La tabella che definisce gli orari di lavoro corrisponde all' area in giallo, quindi la "testata" (che va nella formula) corrisponde a E1:H1; la tabella delle festivita' e' in K1:K12 (costruitela in modo che dentro ci stiano tutte le festivita' che possono corrispondere al perido fino alle scadenze elaborate).
Tuttavia la tabella delle festivita' puo' essere omessa nella formula, e in questo caso tutti i gg saranno conteggiati secondo la tabella degli orari giornalieri.
Opzionale e' anche il riferimento, nella formula, all' intera tabella degli orari (E2:H9, nell' esempio di prima); questo serve solo a ricalcolare automaticamente il risultato se si modifica la tabella degli orari di lavoro.
Due parole sull' intestazione tabella:
-l' intestazione deve contenere il numero giorno della settimana (1=lun, 2=mar, ... 7=Dom) piu' una colonna intestata "10" per le festivita' infrasettimanali. L' orario impostato in una colonna "10" e' prevalente rispetto all' orario del giorno settimanale; quindi per assurdo se la domenica non si lavora ma nelle festivita' infrasettimanali si lavora, allora una festivita' dichiarata che capitasse di domenica verrebbe dichiarata lavorativa. Tenetene conto quando compilate l' elenco delle festivita'...
-non e' obbligatorio dichiarare tutti i giorni, perche' il giorno "dopo" (se non e' dichiarato) eredita l' orario del giorno "prima". Nella tabella dell' immagine pubblicata significa che dal Lun al Ven si fa sempre lo stesso orario, il Sab un altro orario, la Dom un altro ancora. La colonna "10" e' meglio che sia inserita sempre, anche se non usate una tabella festivita'.
-una colonna vuota corrisponde a una giornata non lavorativa
-gli orari vanno dichiarati a coppie di Entrata /Uscita; quando costruite la tabella suggerisco di inserire le intestazioni di riga (come ho fatto io in D2:D9)
-e' meglio se le colonne che contengono la tabella degli orari siano vuote sotto la tabella.
Superfluo dire che Ore e Date vanno indicate come Ore e Date nel formato Excel? Evitate di inserire Ore e Date come stringhe tra virgolette: "spesso" vengono tradotte bene, ma talvolta vengono tradotte a caso; quindi alla peggio appoggiatevi ad una cella formattata correttamente; oppure, per le ore, ricordatevi che dividendo un valore di ore in decimale (es 12,5 pari a 12h30min) per 24 (nell' esempio: 12,5/24) otterrete il corrispondente valore che in formato excel corrisponde a 12h30min (nell' esempio: 0,520833333).
L' algoritmo e' molto elementare, quindi il tempo di calcolo potrebbe risultare di parecchi secondi; per evitare rallentamenti sgraditi ho pertanto posto un limite di max 500 h di durata e 100 giorni di scadenza; oltre questi valori sara' restituito l' errore #N/A, che corrisponde a un tempo di calcolo inferiore a 1-2 sec.
Fatene buon uso.