Η Ελληνίδα NETWORKDAYS

Για τη μέτρηση των εργάσιμων ημερών σε ένα χρονικό διάστημα, το excel διαθέτει την συνάρτηση NETWORKDAYS. Η συνάρτηση είναι μόνιμο μέλος της συλλογής συναρτήσεων του excel από την έκδοση 2007 και μετά. Στις παλιότερες εκδόσεις θα τη βρείτε αν έχετε ενεργοποιημένο το πρόσθετο ‘Πακέτο Εργαλείο Ανάλυσης’. Μια βελτιωμένη έκδοση της συνάρτησης, η NETWORKDAYS.INTL εμφανίστηκε στην έκδοση 2010. Περιγραφή για τη σύνταξή και τον τρόπο χρήσης των συναρτήσεων αυτών, μπορείτε να βρείτε στην επίσημη βοήθεια για το excel, εδώ για την NETWORKDAYS και εδώ για την NETWORKDAYS.INTL

.
Η συνάρτηση WorkingDays
Επειδή εδώ είμαστε ένα ιστολόγιο για τον έλληνα χρήστη του excel, θα ντύσουμε τη συνάρτηση NETWORKDAYS με ελληνική φορεσιά, ή καλλίτερα θα ράψουμε μια εξ ολοκλήρου καινούργια φορεσιά, με τα πιο απλά υλικά της vba, ώστε η συνάρτηση να είναι συμβατή με όλες τις εκδόσεις του excel και όσο γίνεται απλή στη χρήση. Η συνάρτησή έχει το… ελληνικότατο όνομα WorkingDays και θεώρει εξ ορισμού αργίες, όλα τα Σάββατα, όλες τις Κυριακές και τις παρακάτω 13 ημερομηνίες:
— Πρωτοχρονιά (1 Ιανουαρίου)
— Θεοφάνεια (6 Ιανουαρίου)
— Καθαρή Δευτέρα (κινητή)
— Εθνική Γιορτή (25 Μαρτίου)
— Μεγάλη Παρασκευή (κινητή)
— Άγιο Πάσχα (κινητή)
— Δευτέρα Διακαινησίμου (2η του Πάσχα, κινητή)
— Πρωτομαγιά (1 Μαΐου)
— Αγίου Πνεύματος (κινητή)
— Κοίμηση Θεοτόκου (15 Αυγούστου)
— Εθνική Γιορτή (28 Οκτωβρίου)
— Χριστούγεννα (25 Δεκεμβρίου)
— Σύναξη Θεοτόκου (26 Δεκεμβρίου)
Η πλήρης σύνταξη τη συνάρτησης είναι:
=WorkingDays(start_date;end_date;extra_holidays)
δηλαδή, δέχεται τρία ορίσματα: start_date, end_date είναι αντίστοιχα η πρώτη και ή τελευταία ημερομηνία του χρονικού διαστήματος του οποίου ζητάτε το πλήθος των εργάσιμων ημερών, και το προαιρετικό όρισμα extra_holidays με το οποίο μπορείτε να χαρακτηρίσετε σαν αργίες, όσες και όποιες άλλες ημερομηνίες επί πλέον των παραπάνω θέλετε.
Παράδειγμα: Αν στο κελί Α1 είναι η ημερομηνία 1/10/2015, και στο κελί Β1 η 31/10/2015, τότε η συνάρτηση =WorkingDays(A1;B1) θα επιστρέψει 21. Δηλαδή από το σύνολο των 31 ημερών του Οκτωβρίου αφαίρεσε τα Σαββατοκύριακα και την 28η Οκτωβρίου. Αν όμως ζείτε στη Θεσσαλονίκη και για σας είναι αργία και η 26η Οκτωβρίου, γιορτή του Αγίου Δημητρίου, θα γράψετε σε ένα κελί έστω το C1: 26/10/2015 και θα συντάξετε τη συνάρτηση έτσι: =WorkingDays(A1;B1;C1), η οποία θα επιστρέψει σωστά 20.
Οι ημερομηνίες start_date, end_date και extra_holidays μπορούν να δοθούν:
— από κελιά στα οποία είναι γραμμένες σαν κανονικές ημερομηνίες του excel
— από κελιά στα οποία είναι γραμμένες σαν κείμενο
— απ ευθείας μέσα στην συνάρτηση (απαραίτητα κλεισμένες σε εισαγωγικά)
— με την βοήθεια της συνάρτηση DATE
— σαν σειριακοί αριθμοί που αντιπροσωπεύουν τις ημερομηνίες
— σαν συναρτήσεις που επιστρέφουν ημερομηνίες
— με οποιοδήποτε συνδυασμό των παραπάνω
Ειδικά στο όρισμα end_date μπορεί να μη του δοθεί τιμή ή να του δοθεί τιμή μηδέν. Τότε η συνάρτηση επιστρέφει το πλήθος των εργασίμων ημερών από την ημέρα start_date έως το τέλος του μήνα.
Αν οι extra_holidays ημερομηνίες είναι περισσότερες από μία, γράψτε τις σε διαδοχικά κελιά, οριζόντια ή κάθετα ή γράψετε τις κατευθείαν στην συνάρτηση περικλείοντας σε αγκύλες { }

.
Παραδείγματα:
Αν στο κελί Α1 είναι η ημερομηνία 1/10/2015 και στο κελί Β1 η 31/10/2015, όλες οι παρακάτω συναρτήσεις επιστρέφουν τις εργάσιμες ημέρες του Οκτωβρίου 2015

=WorkingDays(A1;B1)
=WorkingDays(A1;0)
=WorkingDays(A1)
=WorkingDays("1/10/2015";"31/10/2015")
=WorkingDays("1/10/2015")
=WorkingDays(DATE(2015;10;1);DATE(2015;10;31))
=WorkingDays(DATE(2015;10;1))
=WorkingDays(42278;42308) ‘Σειριακοί αριθμοί ημερομηνιών
=WorkingDays(42278)

Οι παρακάτω συναρτήσεις επιστρέφουν το πλήθος των εργάσιμων ημερών του Οκτωβρίου 2015, υπολογίζοντας σαν αργία και την γιορτή του Αγίου Δημητρίου που έχει γραφτεί στο κελί C1: 26/10/2015

=WorkingDays(A1;B1;C1)
=WorkingDays(A1;0;C1)
=WorkingDays("1/10/2015";"31/10/15";"26/10/2015")
=WorkingDays("1/10/2015";0;"26/10/2015")
=WorkingDays(DATE(2015;10;1);;DATE(2015;10;26))

Για να μετρήσετε τις εργάσιμες ημέρες του πρώτου εξαμήνου του 2015 θεωρώντας επί πλέον αργίες τις 3 πρώτες ημέρες του Φεβρουαρίου:

Κελί Α1: 1/1/2015
Κελί Β1: 30/6/2015
Κελιά C1, C2, C3: 1/2/15, 2/2/15, 3/2/15
=WorkingDays(A1;B1;C1:C3)

Ο ίδιος υπολογισμός, γράφοντας τις ημερομηνίες κατ ευθείαν μέσα στη συνάρτηση (Παρατηρήστε ότι οι τιμές του ορίσματος extra_holidays στην περίπτωση που είναι περισσότερες από μία εισάγονται σαν πίνακας, με αγκύλες { } ) :

=WorkingDays("1/1/15";"30/6/15";{"2/2/15";"3/2/15";"4/2/15"})

Πλήθος εργασίμων ημερών από την αρχή του τρέχοντος χρόνου έως σήμερα και από αύριο έως το τέλος του τρέχοντος έτους:

=WorkingDays(DATE(YEAR(TODAY());1;1);TODAY())
=WorkingDays(TODAY()+1;DATE(YEAR(TODAY());12;31))

Περισσότερα παραδείγματα θα βρείτε στο βιβλίο WorkingDaysΕxamples.xls το οποίο μπορείτε να κατεβάσετε από εδώ ή από εδώ.
Όλα τα παραδείγματα έχουν γραφτεί θεωρώντας ότι στα setting του υπολογιστή σας οι ημερομηνίες έχουν ρυθμιστεί να έχουν μορφή: ημέρα/μήνας/έτος. Διαφορετικά προσαρμόστε ανάλογα την γραφή των ημερομηνιών. Αν το βιβλίο σας που θα περιέχει την WorkingDays (ή την NETWORKDAYS) θα ανοίγει από διάφορους υπολογιστές για τους οποίους δεν γνωρίζετε τις ρυθμίσεις ημερομηνιών, τότε χρησιμοποιείστε τη συνάρτηση DATE για να εισάγετε τα ορίσματα. Αν χρησιμοποιήσετε τη συνάρτηση για ημερομηνίες παρελθόντων ετών, βεβαιωθείτε ότι ίσχυαν τότε οι αργίες που υπολογίζει. Η πιο παλιά ημερομηνία που επιτρέπει η συνάρτηση είναι η 1/1/1950.

.
Η συνάρτηση WorkingDaysPlus
Επειδή ήδη μερικοί διαμαρτύρεστε ότι δεν έχουν όλοι οι εργαζόμενοι το σταθερό αυτό πακέτο αργιών, και η συνάρτηση δεν φροντίζει για αυτούς, το ιστολόγιο μαζί με τη γιορτινή φορεσιά, έραψε και μία φόρμα εργασίας, την συνάρτηση WorkingDaysPlus, που δεν θεωρεί καμία ημέρα αργία. Εξ ορισμού και τις 365 (ή 366) ημέρες του χρόνου τις θεώρει εργάσιμες. Η συνάρτηση WorkingDaysPlus εκτός των τριών ορισμάτων start_date, end_date και extra_holidays δέχεται 20 ακόμα (προαιρετικά) ορίσματα. Με τα 7 πρώτα από αυτά ορίζετε ποίες από τις ημέρες της εβδομάδας είναι αργίες . Δηλώστε τις αργίες με τον αριθμό 1 ή με TRUE και τις εργάσιμες με 0 (μηδέν) ή FALSE ή αφήστε το όρισμα κενό. Στην παρακάτω εικόνα έχει δηλωθεί αργία μόνο η Κυριακή:

WorkingDays11
Με τα υπόλοιπα 13 ορίσματα καθορίζετε ποιες είναι αργίες και ποιές όχι από τις γιορτές του παραπάνω πίνακα. Στην παρακάτω εικόνα οι Μεγάλη Παρασκευή και του Αγίου Πνεύματος έχουν δηλωθεί εργάσιμες και οι υπόλοιπες 11 αργίες:

WorkingDays22
Άλλες ημερομηνίες που θέλετε να ορίσετε σαν αργίες, θα τις γράψετε στο όρισμα extra_holidays. Για το όρισμα αυτό και για τα ορίσματα start_date και end_date, ισχύουν όσα είπαμε για την συνάρτηση WorkingDays. Η πιο παλιά ημερομηνία που επιτρέπει η συνάρτηση WorkingDaysPlus είναι η 1/1/1924.

.
Ο κώδικας για την WorkingDays:

Function WorkingDays(start_date As Date, Optional end_date As Date = 0, _
            Optional extra_holidays As Variant) As Long
'Από το Excel Λύσεις 2015
Application.Volatile
Dim pl As Long, i As Long
Dim etos As Integer, h As Integer
Dim V() As Date
Dim VH As Variant
Dim item  As Variant
Dim fd As Date, easter As Date
start_date = DateValue(start_date)
If end_date = 0 Then
    end_date = DateSerial(Year(start_date), Month(start_date) + 1, 1) - 1
Else
end_date = DateValue(end_date)
End If
If start_date < DateSerial(1949, 12, 31) Then _
    WorkingDays = CVErr(xlErrValue): GoTo telos
fd = DateSerial(1904, 1, 1)
pl = end_date - start_date
ReDim V(pl)
For i = 0 To pl
    V(i) = start_date + i
Next
For i = 0 To pl
    If DatePart("w", V(i), 1) = 1 Then V(i) = fd
    If DatePart("w", V(i), 1) = 7 Then V(i) = fd
Next
For etos = Year(start_date) To Year(end_date)
    easter = DateSerial(etos, 3, 31) + ((19 * (etos Mod 19) + 16) Mod 30) + ((2 * (etos Mod 4) + _
                        4 * (etos Mod 7) + 6 * ((19 * (etos Mod 19) + 16) Mod 30)) Mod 7) + 3
    VH = Array(DateSerial(etos, 1, 1), DateSerial(etos, 1, 6), DateSerial(etos, 3, 25), DateSerial(etos, 5, 1), _
                        DateSerial(etos, 8, 15), DateSerial(etos, 10, 28), DateSerial(etos, 12, 25), _
                        DateSerial(etos, 12, 26), easter - 48, easter - 2, easter + 1, easter + 50)
    For i = 0 To pl
        For h = 0 To 11
            If V(i) = VH(h) Then V(i) = fd
        Next h
    Next i
Next etos
If Not IsMissing(extra_holidays) Then
   If TypeName(extra_holidays) = "String" Or _
        TypeName(extra_holidays) = "Double" _
        Then extra_holidays = Array(extra_holidays)
    For Each item In extra_holidays
    For i = 0 To pl
    If V(i) = item Then V(i) = fd
    Next i
Next item
End If
For i = 0 To pl
If V(i) > fd Then WorkingDays = WorkingDays + 1
Next
telos:
End Function

.

Ο κώδικας για την WorkingDaysPlus:

Function WorkingDaysPlus(start_date As Date, Optional end_date As Date = 0, _
        Optional extra_holidays As Variant, _
        Optional DEYTERA As Boolean = False, _
        Optional TRITH As Boolean = False, _
        Optional TETARTH As Boolean = False, _
        Optional PEMPTH As Boolean = False, _
        Optional PARASKEYH As Boolean = False, _
        Optional SABBATO As Boolean = False, _
        Optional KYRIAKH As Boolean = False, _
        Optional IAN_01 As Boolean = False, _
        Optional IAN_06 As Boolean = False, _
        Optional KATHARH_DEYTERA As Boolean = False, _
        Optional MAR_25 As Boolean = False, _
        Optional MEGALH_PARASKEYH As Boolean = False, _
        Optional PASXA As Boolean = False, _
        Optional DEYTERA_PASXA As Boolean = False, _
        Optional MAI_01 As Boolean = False, _
        Optional AGIOY_PNEYMATOS As Boolean = False, _
        Optional AYG_15 As Boolean = False, _
        Optional OKT_28 As Boolean = False, _
        Optional DEK_25 As Boolean = False, _
        Optional DEK_26 As Boolean = False) As Long
'Από το Excel Λύσεις, 2015
Application.Volatile
Dim pl As Long, i As Long
Dim etos As Integer, h As Integer
Dim vday As Integer
Dim V() As Date
Dim VH As Variant
Dim item As Variant
Dim fd As Date, easter As Date
start_date = DateValue(start_date)
If end_date = 0 Then
    end_date = DateSerial(Year(start_date), Month(start_date) + 1, 1) - 1
Else
end_date = DateValue(end_date)
End If
If start_date < DateSerial(1924, 1, 1) Then _
    WorkingDaysPlus = CVErr(xlErrValue): GoTo telos
fd = DateSerial(1904, 1, 1)
pl = end_date - start_date
ReDim V(pl)
For i = 0 To pl
    V(i) = start_date + i
Next
For i = 0 To pl
vday = DatePart("w", V(i), 1)

    If DEYTERA = True Then
    If vday = 2 Then V(i) = fd
    End If

    If TRITH = True Then
    If vday = 3 Then V(i) = fd
    End If

    If TETARTH = True Then
    If vday = 4 Then V(i) = fd
    End If

    If PEMPTH = True Then
    If vday = 5 Then V(i) = fd
    End If

    If PARASKEYH = True Then
    If vday = 6 Then V(i) = fd
    End If

    If SABBATO = True Then
    If vday = 7 Then V(i) = fd
    End If

    If KYRIAKH = True Then
    If vday = 1 Then V(i) = fd
    End If
Next
For etos = Year(start_date) To Year(end_date)
    easter = DateSerial(etos, 3, 31) + ((19 * (etos Mod 19) + 16) Mod 30) + ((2 * (etos Mod 4) + _
                        4 * (etos Mod 7) + 6 * ((19 * (etos Mod 19) + 16) Mod 30)) Mod 7) + 3
    VH = Array(DateSerial(etos, 1, 1), DateSerial(etos, 1, 6), DateSerial(etos, 3, 25), DateSerial(etos, 5, 1), _
                        DateSerial(etos, 8, 15), DateSerial(etos, 10, 28), DateSerial(etos, 12, 25), _
                        DateSerial(etos, 12, 26), easter - 48, easter - 2, easter, easter + 1, easter + 50)
    If IAN_01 = False Then VH(0) = ""
    If IAN_06 = False Then VH(1) = ""
    If MAR_25 = False Then VH(2) = ""
    If MAI_01 = False Then VH(3) = ""
    If AYG_15 = False Then VH(4) = ""
    If OKT_28 = False Then VH(5) = ""
    If DEK_25 = False Then VH(6) = ""
    If DEK_26 = False Then VH(7) = ""
    If KATHARH_DEYTERA = False Then VH(8) = ""
    If MEGALH_PARASKEYH = False Then VH(9) = ""
    If PASXA = False Then VH(10) = ""
    If DEYTERA_PASXA = False Then VH(11) = ""
    If AGIOY_PNEYMATOS = False Then VH(12) = ""
    For i = 0 To pl
        For h = 0 To 12
            If V(i) = VH(h) Then V(i) = fd
        Next h
    Next i
Next etos
If Not IsMissing(extra_holidays) Then
    If TypeName(extra_holidays) = "String" Or _
        TypeName(extra_holidays) = "Double" _
        Then extra_holidays = Array(extra_holidays)
    For Each item In extra_holidays
    For i = 0 To pl
    If V(i) = item Then V(i) = fd
    Next i
Next item
End If
For i = 0 To pl
If V(i) > fd Then WorkingDaysPlus = WorkingDaysPlus + 1
Next
telos:
End Function
This entry was posted in excel, Συναρτήσεις Χρήστη, VBA and tagged , , , , , , , . Bookmark the permalink.