OVH Cloud OVH Cloud

Jours ouvrables

6 réponses
Avatar
S. PERREAUT
Bonsoir tout le monde,

Voilà bien longtemps que je n'étais venu chercher quelques précieux
conseils.
Je suis à la recherche d'une fonction ou macro afin de calculer le nombre de
jours ouvrables entre 2 dates. Excel (2002) propose une fonction pour les
jours ouvrés mais pas de jours ouvrables.

Merci d'avance pour votre aide.

Sylvain

PS : serait il possible d'avoir une copie de réponse sur mon mail ? Le
firewall du bureau ne laisse pas l'accès au port 119 des newsgroups.

6 réponses

Avatar
Daniel.M
Salut Sylvain,

Tu as à choisir entre 2 stratégies/solutions.

1. Une fonction NbOuvrés() incrémente de DtDébut à DtFin et vérifie pour chacune
d'elle, si elle correspond à un jour férié. C'est la solution de Frédéric
Sigonneau qui utilise la fonction TYPEJOUR() de Laurent Longre.
=NbOuvrés(DtDébut;DtFin)

2. La fonction NB.JOURS.OUVRES() des macros complémentaires Excel avec, comme 3e
argument, une fonction FetesFR() qui retourne les jours fériés français entre
DtDébut et DtFin.
=NB.JOURS.OUVRES(DtDébut;DtFin;FetesFR(DtDébut;DtFin))

Tu choisis celle que tu veux mais je te dirais que la deuxième est un peu plus
rapide (pas de construction de liste de fêtes pour chaque jour) mais j'ai un
biais certain ;-)

'Solution 1:
'=========== 'Une solution VBA, avec l'aide de la fonction TYPEJOUR de Laurent Longre, pour
'trouver le nombre de jours ouvrés entre deux dates de ton choix.
'Après avoir recopié le code dans un module standard du classeur où tu veux
'l 'utiliser, tu peux écrire dans une feuille de calcul, pour trouver, par
'exemple, le nombre de jours ouvrés en janvier 2003 :
'
'=NbOuvrés("1/1/2003"*1;"31/1/2003"*1)
'
'FS
'--
'Frédéric Sigonneau [né un sans-culottide]

'======================= 'comment compter un nbre de jours entre 2 dates saisies ds 2 cellules en
'otant les samedi,dimanche et jours feries

Function NbOuvrés&(D1, D2)
Dim Prem As Date, Der As Date, i As Date
If D1 = D2 Then
Prem = D1
If TYPEJOUR(Prem) = 0 Then NbOuvrés = 1
Exit Function
End If
Select Case D1 < D2
Case True: Prem = D1: Der = D2
Case False: Prem = D2: Der = D1
End Select
For i = Prem To Der
NbOuvrés = NbOuvrés + (TYPEJOUR(i) = 0) * -1
Next i
End Function


'Cette fonction renvoie 0 si le jour passé en paramètre est un jour de semaine,
'1 s'il s'agit d'un samedi ou d'un dimanche et 2 s'il s'agit d'un jour férié.
'Valide jusqu'en 2099 et pour les jours fériés français
Function TYPEJOUR(D As Date)
'L. Longre
Dim A As Integer, T As Integer
Dim LP As Date, LD As Long
Dim Toto As Long

A = Year(D)
If A > 2099 Then
TYPEJOUR = CVErr(xlErrValue)
Exit Function
End If
LD = Int(D)
If LD <= 2 Then
If LD = 1 Then TYPEJOUR = 2
Exit Function
End If
T = (((255 - 11 * (A Mod 19)) - 21) Mod 30) + 21
LP = DateSerial(A, 3, 2) + T + (T > 48) _
+ 6 - ((A + A 4 + T + (T > 48) + 1) Mod 7)
Select Case D
' Jours fériés mobiles
Case Is = LP, Is = LP + 38, Is = LP + 49
TYPEJOUR = 2
' Jours fériés fixes
Case Is = DateSerial(A, 1, 1), Is = DateSerial(A, 5, 1), _
Is = DateSerial(A, 5, 8), Is = DateSerial(A, 7, 14), _
Is = DateSerial(A, 8, 15), Is = DateSerial(A, 11, 1), _
Is = DateSerial(A, 11, 11), Is = DateSerial(A, 12, 25)
TYPEJOUR = 2
Case Else
' Samedi ou dimanche
If Weekday(D, vbMonday) >= 6 Then TYPEJOUR = 1
End Select

End Function
'=======================

'=========== 'Solution 2:
'=========== Const VALABSENTE = -367
Const JRFer_FR_ANNEE = 11

Function FetesFR(Optional LimiteInf As Long = VALABSENTE, _
Optional LimiteSup As Long = VALABSENTE, _
Optional Glisse As Integer = 0) As Variant
' Daniel M. Feb 2003
' Retourne un tableau HORIZONTAL (très important!!!, utilisez
' Transpose() si besoin est) de fêtes Françaises comprises
' entre LimiteInf à LimiteSup
'
' Sans arguments, la fonction retourne les fêtes de l'année courante
' Précisément, LimiteInf et LimiteSup sont interprétés ainsi:
' LimiteInf:
' ========= ' Un nombre absent : le 1er jan de l'année courante
' Un nombre X plus petit que 1900 : la date courante + X jours
' X peut être négatif (-366 <= X < 1900)
' Un nombre X plus petit que 4100 (et >00) : 1er jan de l'année X
' Autre (>A00): il s'agit d'une vraie date et est prise comme tel.
'
' LimiteSup:
' ======= ' Un nombre absent : le départ calculé+1 an (-1 jour)
' Un nombre X plus petit que 1900 : Ce sera le delta ANNÉES
' (X années -1 jour) avec le départ calculé.
' Un nombre X plus petit que 4100 (et >00) : le 31 déc de l'année X
' Autre (>A00):il s'agit d'une vraie date et est prise comme tel.
'
' Exemples: (Supposons C1=Aujourdhui() )
'
'FetesFr(2004): fêtes du 1 jan 2004 au 31 déc 2004
'FetesFr(2004;6): fêtes du 1 janv 2004 au
' 31 déc 2009 (1er jan 2004 + 6 ans -1 jour)
'FetesFr(2004;2007): fêtes du 1 janv 2004 au 31 déc 2007
'FetesFr(2002;C1+200) : fêtes du 1 jan 2002 à date courante+200 jours
'
'FetesFr() : fêtes du 1er janv au 31 déc de l'année courante
'FetesFr(;2):fêtes du 1er janv de l'année courante
' jusqu'au 31 déc de l'année suivante
'FetesFr(;2005): fêtes du 1er jan de l'année courante au 31 déc 2005
'FetesFr(;C1): fêtes du 1er jan de l'année courante jusqu'à aujourd'hui
'
'FetesFr(23) : fêtes de la date courante + 23 jours
' jusqu'à 1 an (-1 jour) plus tard.
'FetesFr(0) : fêtes de la date courante jusqu'à 1 an (-1 jour) plus tard.
'FetesFr(0;1): Ibid
'FetesFr(5;8): fêtes de la date courante + 5 jours
'jusqu'à 8 ans (-1 jour) plus tard
'FetesFr(5;2007): fêtes de la date courante + 5 jours jusqu'au 31 déc 2007
'FetesFr(C1-1;C1+1) ou FetesFr(-1;C1+1) : fêtes d'hier à demain!
'
'FetesFr(C1): fêtes d'aujourd'hui jusqu'à dans 1 an (-1 jour)
'FetesFr(C1;6): fêtes d'aujourd'hui jusque dans exactement 6 ans (-1 jour)
'FetesFr(C1;ANNEE(C1)+6): fêtes d'aujourd'hui jusqu'au 31 déc dans 6 ans
'FetesFr(C1;2007): fêtes d'aujourd'hui jusqu'au 31 déc 2007
'FetesFr(C1;C1+200) : fêtes d'aujourd'hui jusqu'à dans 200 jours.
'
' Le traitement des 2 premiers args
' (décrits ci-dessus) fait en sorte qu'il est impossible
' d'obtenir les fêtes précises pour les 4099 premiers JOURS
' du calendrier (environ jusqu'en Mars 1911, pour calendrier 1900).
' Il faudra alors y aller avec FetesFr(1900;1911) Un moindre mal.
' Mon appréciation personnelle est que la fonction FetesFr()
' servira beaucoup plus pour la gestion actuelle
' (donc, avec des dates contemporaines) et que le gain
' de fonctionnalité/flexibilité vaut largement cette perte.
'
' Avec Glisse = -1, les fériés tombant un samedi sont ajustés au vendredi
' précédant, ceux tombant un dimanche sont ajustés au lundi suivant.
' Avec Glisse = 0, les jours fériés tombant durant une fin de semaine
' ne sont pas ajustés. Option par défaut
' Avec Glisse = 1, les jours fériés tombant durant une fin de semaine
' sont ajustés au lundi suivant.

Dim j As Long, D As Long, WDay As Integer
Dim ret() As Variant, nRet As Integer
Dim Y As Integer, YStart As Integer, YEnd As Integer
Dim DtDeb As Date, DtFin As Date, PAQUES As Date

If LimiteInf <= VALABSENTE Then ' omis : donc, 1 janvier courant
DtDeb = DateSerial(Year(Date), 1, 1)
ElseIf LimiteInf < 1900 Then ' Date courante + ce delta en jours
DtDeb = Date + LimiteInf
ElseIf LimiteInf < 4100 Then ' on a mis une année
DtDeb = DateSerial(LimiteInf, 1, 1)
Else ' on a mis une date
DtDeb = LimiteInf
End If

If LimiteSup <= VALABSENTE Then ' omis : donc, DtDeb + 1 an
DtFin = DateSerial(Year(DtDeb) + 1, Month(DtDeb), _
Day(DtDeb) - 1)
ElseIf LimiteSup < 1900 Then
' DtFin = DtDeb + LimiteSup années
DtFin = DateSerial(Year(DtDeb) + LimiteSup, _
Month(DtDeb), Day(DtDeb) - 1)
ElseIf LimiteSup < 4100 Then ' on a mis une année
DtFin = DateSerial(LimiteSup, 12, 31)
Else ' on a mis une date
DtFin = LimiteSup
End If

If DtFin < DtDeb Then
FetesFR = CVErr(xlErrNum)
Exit Function
End If

YStart = Year(DtDeb)
YEnd = Year(DtFin)
nRet = 0

ReDim ret(1 To JRFer_FR_ANNEE * (1 + YEnd - YStart))
For Y = YStart To YEnd
For j = 1 To JRFer_FR_ANNEE
Select Case j
Case 1 ' Jour de l'An
D = DateSerial(Y, 1, 1)
Case 2 ' Lundi de Pâques
PAQUES = DateSerial(Y, 3, Int(29.56 + _
0.979 * ((204 - 11 * (Y Mod 19)) Mod 30)))
PAQUES = PAQUES - Weekday(PAQUES - 1)
D = PAQUES + 1
Case 3 ' Fête du Travail (1er mai)
D = DateSerial(Y, 5, 1)
Case 4 ' Journée de la victoire 1945
D = DateSerial(Y, 5, 8)
Case 5 ' Ascension
D = PAQUES + 39
Case 6 ' Lundi de la Pentecôte
D = PAQUES + 50
Case 7 ' Fête Nationale (14 juillet)
D = DateSerial(Y, 7, 14)
Case 8 ' Assomption (15 août)
D = DateSerial(Y, 8, 15)
Case 9 ' La Toussaint (1 nov)
D = DateSerial(Y, 11, 1)
Case 10 ' L'Armistice 1918
D = DateSerial(Y, 11, 11)
Case JRFer_FR_ANNEE ' Jour de Noël (25 décembre)
D = DateSerial(Y, 12, 25)
End Select

If Glisse = -1 Then
WDay = Weekday(D + 1)
If WDay = 1 Then ' Samedi? Retourne au vendredi
D = D - 1
ElseIf WDay = 2 Then ' Dimanche? Va au Lundi
D = D + 1
End If
ElseIf Glisse = 1 Then
WDay = Weekday(D + 1)
D = D + Application.Max(0, 3 - WDay)
End If

If D >= DtDeb Then
If D > DtFin Then Exit For ' Dates tardives, stop!
nRet = nRet + 1
ret(nRet) = D
End If

Next j
Next Y

If nRet = 0 Then
FetesFR = ""
Erase ret
Else
ReDim Preserve ret(1 To nRet) ' Ajuste le tableau
FetesFR = ret
' FetesFR = Application.Transpose(ret)' Pour tableau vertical
End If
End Function

'===========
Salutations,

Daniel M.


"S. PERREAUT" wrote in message
news:bpgjeq$j34$
Bonsoir tout le monde,

Voilà bien longtemps que je n'étais venu chercher quelques précieux
conseils.
Je suis à la recherche d'une fonction ou macro afin de calculer le nombre de
jours ouvrables entre 2 dates. Excel (2002) propose une fonction pour les
jours ouvrés mais pas de jours ouvrables.

Merci d'avance pour votre aide.

Sylvain

PS : serait il possible d'avoir une copie de réponse sur mon mail ? Le
firewall du bureau ne laisse pas l'accès au port 119 des newsgroups.




Avatar
Daniel.M
Hello,

Petite erreur dans la fonction FetesFR()

Au lieu de
FetesFR = ""
il faut mettre
FetesFR = 0

Ainsi, les fonctions qui appellent FetesFR et qui s'attendent à une matrice de
Dates/Nombres ne seront pas mises en échec.

Salutations,

Daniel M.
Avatar
AV
Tu choisis celle que tu veux mais je te dirais que la deuxième est un peu plus
rapide (pas de construction de liste de fêtes pour chaque jour) mais j'ai un
biais certain ;-)


Ce que j'aime bien dans la 2° (NB.JOURS.OUVRES) c'est que je peux très
facilement rajouter mes jours de vacances (au demeurant bien plus nombreux que
les jours fériés) !
;-)

AV

Avatar
Modeste
;-)))
Alors là AV tu va faire exploser Clément !!!!
déja que soit-disant on a trop de jours fériès,
si on plus tu rajoutes les vacances ?????
manquerai plus que tu lui dises que tu es
fonctionnaire !!!!
;-)))
@+
-----Message d'origine-----
mais j'ai un biais certain ;-)

Ce que j'aime bien dans la 2° (NB.JOURS.OUVRES) c'est que
je peux très

facilement rajouter mes jours de vacances (au demeurant
bien plus nombreux que

les jours fériés) !
;-)

AV


.



Avatar
S. PERREAUT
Un grand merci à vous pour votre aide. Je vais étudier ça.

Bonne journée.

Sylvain
-----Message d'origine-----
Bonsoir tout le monde,

Voilà bien longtemps que je n'étais venu chercher
quelques précieux

conseils.
Je suis à la recherche d'une fonction ou macro afin de
calculer le nombre de

jours ouvrables entre 2 dates. Excel (2002) propose une
fonction pour les

jours ouvrés mais pas de jours ouvrables.

Merci d'avance pour votre aide.

Sylvain

PS : serait il possible d'avoir une copie de réponse sur
mon mail ? Le

firewall du bureau ne laisse pas l'accès au port 119 des
newsgroups.



.



Avatar
AV
Alors là AV tu va faire exploser Clément !!!!
déja que soit-disant on a trop de jours fériès,
......


C'est justement pour éviter la dite-explosion que je me suis toujours abstenu de
publier en ce lieu la fonction qui m'a rendu célèbre sur tout le Plateau de
Millevaches :
NB.JOURS.VACANCES
......dont l'utilisation est semblable à NB.JOURS.OUVRES mais dont le 3°
argument fait référence à une (petite) plage contenant les jours travaillés

;-)

AV