Hello,
J'aimerai ajouter 7 jours ouvrables à une date, sans compter les samedi et dimanche, comment faire ?
Merci pour votre aide
Philippe
Code:
1
2
3
4
5
6 Sub test() Dim madate As Variant madate = DateAdd("w", 7, Now) End Sub
Version imprimable
Hello,
J'aimerai ajouter 7 jours ouvrables à une date, sans compter les samedi et dimanche, comment faire ?
Merci pour votre aide
Philippe
Code:
1
2
3
4
5
6 Sub test() Dim madate As Variant madate = DateAdd("w", 7, Now) End Sub
Bonjour,
edit: réponse inutile donc supprimée
merci Zekraoui_Jakani j'avais oublié l'existence de cette fonction, il faut dire aussi que sa traduction n'est pas très explicite: SERIE.JOUR.OUVRE.INTL
La fonctionfera l'affaire, mais il faudra également y tenir compte des congés légaux (à spécifier)Code:=WORKDAY(A3;7)
Excel dispose de fonctions spécifiques pour cela. Tu peux ainsi tenir compte des jours fériés spécifiés dans une table, et le régime hebdomadaire peut être spécifié lui aussi.
Pièce jointe 495779
si besoin de l'utiliser en VBA, ça ne pose pas de problème particulier. Tu peux utiliser EVALUATE et lui passer la formule (syntaxe internationale => =WORKDAY.INTL(A2,B2,"0000011",t_Fériés[Jours fériés]) ou utiliser application.WorksheetFunction.WorkDay_Intl
Hello,
Désolé pourriez-vous me transmettre plus d'infos, car les 2 solutions en vba ne fonctionne pas chez moi.
J'ai absolument besoin en vba car je vais travailler avec une textbox
Le but et d'ajouter 7 jours à une date en éliminant les samedi dimanche et les jours fériés listés dans une colonne
Je fixe une date de début de la misssion, la mission dure 7 jours et je veux connaître la date de fin de la mission en ne tenant compte que des jours travaillés
Encore merci pour votre aide
Philippe
Voici un exemple VBA de l'utilisation de la fonction Excel SERIE.JOUR.OUVRE.INTL. Cette fonction permet de spécifier les jours de la semaine qui sont ouvrés (0) et ceux qui sont fériés (1) dans une chaine de 7 digits dans laquelle lundi est en première position. Elle permet également d'utiliser une plage de jours réputés fériés, matérialisée ici dans une table de données nommée t_Fériés. Si la table des jours fériés contient plusieurs colonnes, il convient de spécifier la colonne qui contient les dates.
Pièce jointe 495989
Code:
1
2
3
4
5
6
7
8
9 Sub Test() Dim StartDate As Date, Days As Long, Week As String, Holydays As Range StartDate = DateSerial(2019, 7, 25) Days = 7 Week = "0000011" Set Holydays = Range("t_Fériés[Férié]") MsgBox CDate(Application.WorkDay_Intl(StartDate, Days, Week, Holydays)) End Sub
Bonjour Pierre,
Magnifique j'ai pu adapter le code.
J'ai encore un problème, lorsque je lache les données dans les cellules dateDébut et DateFin au format jj.mm.aaaa, avec les LabelDateDebut et le LabelDateFin via le bouton OK, les données ne prennent pas les mises en formes des cellules repectives.
Je dois double-cliquer sur les cellules pour que la mise en forme des cellules soit prise en compte, par exemple jjj jj.mm.aaaa ou autre ...
Comment supprimer ce problème ?
Merci
Philippe
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97 Option Explicit Private Sub TextBoxDuree_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger) 'Autorise la saisie de certains caractères Select Case KeyAscii Case 48 To 57 'Accepte de 0 à 9 Case Else KeyAscii = 0 End Select End Sub Private Sub LabelDateDebut_Click() USF_Calendar_Travaux_Debut.Show End Sub Private Sub LabelDateFin_Click() USF_Calendar_Travaux_Fin.Show End Sub Private Sub TextBoxDuree_Change() Dim Start_Date As Date, DateDebut As Date, DateFin As Date, Days As Long, Week As String, Holydays As Range, Date_debut As Variant 'Calcul de la date de fin si la date de début existe On Error GoTo Fin 'Si les dates sont vides Start_Date = LabelDateDebut If TextBoxDuree = "" Then LabelDateFin = LabelDateDebut LabelJourSemDebut = Format(LabelDateDebut, "ddd") 'Afficher le jour de la semaine devant la date LabelJourSemFin = Format(LabelDateFin, "ddd") 'Afficher le jour de la semaine devant la date Else Days = TextBoxDuree 'nombre de jour Week = "0000011" Set Holydays = Range("Tableau_Fériés[Jours fériés et ponts]") 'Vérifier les dates dans le tableau de la feuille DATA DateFin = CDate(Application.WorkDay_Intl(Start_Date, Days, Week, Holydays)) LabelDateFin = DateFin LabelJourSemDebut = Format(LabelDateDebut, "ddd") 'Afficher le jour de la semaine devant la date LabelJourSemFin = Format(LabelDateFin, "ddd") 'Afficher le jour de la semaine devant la date End If 'Fin du calcul de la date de fin si la date de début existe Fin: End Sub Private Sub UserForm_Initialize() Me.TextBoxPVchantier.SetFocus 'Place le curseur dans la textbox TextBoxPVchantier = ActiveCell.Value LabelDateDebut = ActiveCell.Offset(rowOffset:=0, columnOffset:=2) 'Charger avant la TextBoxDuree sinon la macro plante car la date et vide LabelDateFin = ActiveCell.Offset(rowOffset:=0, columnOffset:=3) 'Charger avant la TextBoxDuree sinon la macro plante car la date et vide TextBoxDuree = ActiveCell.Offset(rowOffset:=0, columnOffset:=1) Label_Num_CFC = ActiveCell.Offset(rowOffset:=0, columnOffset:=-3) LabelJourSemDebut = Format(LabelDateDebut, "ddd") 'Afficher le jour de la semaine devant la date LabelJourSemFin = Format(LabelDateFin, "ddd") 'Afficher le jour de la semaine devant la date If ActiveCell.Offset(rowOffset:=0, columnOffset:=4) = "Impératif" Then Option_Imperatif = True End If If ActiveCell.Offset(rowOffset:=0, columnOffset:=4) = "En cours" Then Option_En_cours = True End If If ActiveCell.Offset(rowOffset:=0, columnOffset:=4) = "En retard" Then Option_En_retard = True End If If ActiveCell.Offset(rowOffset:=0, columnOffset:=4) = "Urgent" Then Option_Urgent = True End If If ActiveCell.Offset(rowOffset:=0, columnOffset:=4) = "Terminé" Then Option_Terminé = True End If If ActiveCell.Offset(rowOffset:=0, columnOffset:=4) = "" Then Option_blanc = True End If End Sub Private Sub BT_Annuler_Click() Unload Me End Sub Private Sub BT_OK_Click() Dim Date_debut As String Unload Me ActiveCell = TextBoxPVchantier ActiveCell.Offset(rowOffset:=0, columnOffset:=1) = TextBoxDuree.Value ActiveCell.Offset(rowOffset:=0, columnOffset:=2) = LabelDateDebut ActiveCell.Offset(rowOffset:=0, columnOffset:=3) = LabelDateFin ActiveCell.Offset(rowOffset:=0, columnOffset:=5) = Now 'Avancement du chantier If Option_Imperatif.Value = True Then 'Si coché ... ActiveCell.Offset(rowOffset:=0, columnOffset:=4) = "Impératif" End If If Option_En_cours.Value = True Then 'Si coché ... ActiveCell.Offset(rowOffset:=0, columnOffset:=4) = "En cours" End If If Option_En_retard.Value = True Then 'Si coché ... ActiveCell.Offset(rowOffset:=0, columnOffset:=4) = "En retard" End If If Option_Urgent.Value = True Then 'Si coché ... ActiveCell.Offset(rowOffset:=0, columnOffset:=4) = "Urgent" End If If Option_Terminé.Value = True Then 'Si coché ... ActiveCell.Offset(rowOffset:=0, columnOffset:=4) = "Terminé" End If If Option_blanc.Value = True Then 'Si coché ... ActiveCell.Offset(rowOffset:=0, columnOffset:=4) = "" End If ActiveCell.Cells.CheckSpelling SpellLang:=1036 'Lancer le correcteur orthographique End Sub Private Sub CommandButton1_Click() Unload Me End Sub
Hell,
En fait il ne faut surtout pas formater les textbox date avec du texte, sinon les calculs ne fonctionnent plus et les cellules des feuilles ne reconnaisent pas les valeurs dates.
Voici le code corrigé et tout fonctionne.
Pour afficher les jours de la semaine lun. mar. ... sur le Userform, j'ai ajouté des labels devant les textbox des dates pour ne pas avoir de lettres dans les textbox des dates.
Merci pour votre aide
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136 Option Explicit Private Sub Btn_Feries_Click() Liaisons_Dossier_Onglet_Divers.Bouton_Data_Feries End Sub Private Sub TextBoxDuree_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger) 'Autorise la saisie de certains caractères Select Case KeyAscii Case 48 To 57 'Accepte de 0 à 9 Case Else KeyAscii = 0 End Select End Sub Private Sub LabelDateDebut_Click() USF_Calendar_Travaux_Debut.Show End Sub Private Sub LabelJourSemDebut_Click() USF_Calendar_Travaux_Debut.Show End Sub Private Sub LabelDateFin_Click() USF_Calendar_Travaux_Fin.Show End Sub Private Sub LabelJourSemFin_Click() USF_Calendar_Travaux_Fin.Show End Sub Private Sub TextBoxDuree_Change() Dim Start_Date As Date, DateDebut As Date, DateFin As Date, Days As Long, Week As String, Holydays As Range, Date_debut As Variant 'Calcul de la date de fin si la date de début existe On Error GoTo Fin 'Si les dates sont vides Start_Date = LabelDateDebut If TextBoxDuree = "" Then LabelDateFin = LabelDateDebut LabelJourSemDebut = Format(LabelDateDebut, "ddd") 'Afficher le jour de la semaine devant la date LabelJourSemFin = Format(LabelDateFin, "ddd") 'Afficher le jour de la semaine devant la date Else Days = TextBoxDuree 'nombre de jour Week = "0000011" Set Holydays = Range("Tableau_Fériés[Jours fériés et ponts]") 'Vérifier les dates dans le tableau de la feuille DATA DateFin = CDate(Application.WorkDay_Intl(Start_Date, Days, Week, Holydays)) LabelDateFin = DateFin LabelJourSemDebut = Format(LabelDateDebut, "ddd") 'Afficher le jour de la semaine devant la date LabelJourSemFin = Format(LabelDateFin, "ddd") 'Afficher le jour de la semaine devant la date End If 'Fin du calcul de la date de fin si la date de début existe Fin: End Sub Private Sub UserForm_Initialize() Dim ID_CFC As Variant Dim Trouve As Range Dim PlageDeRecherche As Range Dim Valeur_Cherchee As String Dim AdresseTrouvee As String Application.ScreenUpdating = False ID_CFC = ActiveCell.Offset(rowOffset:=0, columnOffset:=-2).Value & "-10001" 'Rechercher et sélectionner la cellule contenant ID_ Set PlageDeRecherche = ActiveSheet.Columns(1) Set Trouve = PlageDeRecherche.Cells.Find(what:=ID_CFC, LookAt:=xlWhole) 'méthode find, ici on cherche la valeur exacte (LookAt:=xlWhole) 'traitement de l'erreur possible : Si on ne trouve rien : If Trouve Is Nothing Then 'ici, traitement pour le cas où la valeur n'est pas trouvée AdresseTrouvee = Valeur_Cherchee & " n'est pas présent dans " & PlageDeRecherche.Address Else 'ici, traitement pour le cas où la valeur est trouvée AdresseTrouvee = Trouve.Address LabelCFC.Caption = Range(AdresseTrouvee).Offset(rowOffset:=0, columnOffset:=12) End If Me.TextBoxPVchantier.SetFocus 'Place le curseur dans la textbox FrameDate.Caption = "Nous sommes le " & Format(Now, "dddd dd.mm.yyyy") TextBoxPVchantier = ActiveCell.Value LabelDateDebut = ActiveCell.Offset(rowOffset:=0, columnOffset:=2) 'Charger avant la TextBoxDuree sinon la macro plante car la date et vide LabelDateFin = ActiveCell.Offset(rowOffset:=0, columnOffset:=3) 'Charger avant la TextBoxDuree sinon la macro plante car la date et vide TextBoxDuree = ActiveCell.Offset(rowOffset:=0, columnOffset:=1) LabelJourSemDebut = Format(LabelDateDebut, "ddd") 'Afficher le jour de la semaine devant la date LabelJourSemFin = Format(LabelDateFin, "ddd") 'Afficher le jour de la semaine devant la date If ActiveCell.Offset(rowOffset:=0, columnOffset:=4) = "Impératif" Then Option_Imperatif = True End If If ActiveCell.Offset(rowOffset:=0, columnOffset:=4) = "En cours" Then Option_En_cours = True End If If ActiveCell.Offset(rowOffset:=0, columnOffset:=4) = "En retard" Then Option_En_retard = True End If If ActiveCell.Offset(rowOffset:=0, columnOffset:=4) = "Urgent" Then Option_Urgent = True End If If ActiveCell.Offset(rowOffset:=0, columnOffset:=4) = "Terminé" Then Option_Terminé = True End If If ActiveCell.Offset(rowOffset:=0, columnOffset:=4) = "" Then Option_blanc = True End If End Sub Private Sub BT_Annuler_Click() Unload Me End Sub Private Sub BT_OK_Click() Dim Date_début As Date Dim Date_Fin As Date ActiveCell = TextBoxPVchantier ActiveCell.Offset(rowOffset:=0, columnOffset:=1) = TextBoxDuree.Value ActiveCell.Offset(rowOffset:=0, columnOffset:=6) = Now If LabelDateDebut = "" Then 'Pas de date Else Date_début = LabelDateDebut ActiveCell.Offset(rowOffset:=0, columnOffset:=2) = Date_début 'Variable obligatoire pour avoir la date au format date dans excel End If If LabelDateFin = "" Then 'Pas de date Else Date_Fin = LabelDateFin ActiveCell.Offset(rowOffset:=0, columnOffset:=3) = Date_Fin 'Variable obligatoire pour avoir la date au format date dans excel End If 'Avancement du chantier If Option_Imperatif.Value = True Then 'Si coché ... ActiveCell.Offset(rowOffset:=0, columnOffset:=4) = "Impératif" End If If Option_En_cours.Value = True Then 'Si coché ... ActiveCell.Offset(rowOffset:=0, columnOffset:=4) = "En cours" End If If Option_En_retard.Value = True Then 'Si coché ... ActiveCell.Offset(rowOffset:=0, columnOffset:=4) = "En retard" End If If Option_Urgent.Value = True Then 'Si coché ... ActiveCell.Offset(rowOffset:=0, columnOffset:=4) = "Urgent" End If If Option_Terminé.Value = True Then 'Si coché ... ActiveCell.Offset(rowOffset:=0, columnOffset:=4) = "Terminé" End If If Option_blanc.Value = True Then 'Si coché ... ActiveCell.Offset(rowOffset:=0, columnOffset:=4) = "" End If ActiveCell.Cells.CheckSpelling SpellLang:=1036 'Lancer le correcteur orthographique Unload Me End Sub Private Sub CommandButton1_Click() Unload Me End Sub
Hello,
Cette macro calcul automatiquement la date de fin en prenant en compte une durée donnée, les jours fériés d'une table et les wekend.
Comment modifier cette macro pour calculer le nombre de jour entre la date de début et la date de fin qui sont renseignées manuellement par l'utilisateur ?
Merci pour votre aide et meilleures salutations
Philippe
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 Private Sub Btn_Calculer_Date_de_fin_Click() Dim Start_Date As Date, DateDebut As Date, DateFin As Date, Days As Long, Week As String, Holydays As Range, Date_debut As Variant If MsgBox("Remplacer la date de fin ?", vbYesNo + vbQuestion, "Calculer la date de fin") = vbYes Then 'Calcul de la date de fin si la date de début existe On Error GoTo Fin 'Si les dates sont vides Start_Date = LabelDateDebut If TextBoxDuree = "" Then LabelDateFin = LabelDateDebut LabelJourSemDebut = Format(LabelDateDebut, "ddd") 'Afficher le jour de la semaine devant la date LabelJourSemFin = Format(LabelDateFin, "ddd") 'Afficher le jour de la semaine devant la date Else Days = TextBoxDuree 'nombre de jour Week = "0000011" Set Holydays = Range("Tableau_Fériés[Jours fériés et ponts]") 'Vérifier les dates dans le tableau de la feuille DATA DateFin = CDate(Application.WorkDay_Intl(Start_Date, Days, Week, Holydays)) LabelDateFin = DateFin LabelJourSemDebut = Format(LabelDateDebut, "ddd") 'Afficher le jour de la semaine devant la date LabelJourSemFin = Format(LabelDateFin, "ddd") 'Afficher le jour de la semaine devant la date End If 'Fin du calcul de la date de fin si la date de début existe End If Fin: End Sub
Comment seront-elles renseignées par l'utilisateur? Dans des textbox, des inputbox, des cellules?
Le principe consiste en fait à remplacer Start_Date et DateFin (attention que, sauf erreur, tu as un DateDebut qui traine et qui semble ne servir à rien), par la valeur des cellules correspondantes qui doivent contenir des dates, ou par la transformation des saisies textuelles (textbox et inputbox) en date.
Dans le code que tu as donné précédemment, elles sont effectivement dans des label. Donc je ne comprends pas bien ta réponse ni ton besoin.
Ok. Tu as deux fonctions qui "jouent" avec les jours fériés:
la fonction WorkDay_Intl, déjà utilisée, qui donne une date à x jours ouvrés (dans le futur ou le passé) par rapport à une date pivot;
la fonction NETWORKDAYS.INTL qui requiert deux dates (début et fin), puis optionnellement le régime hebdomadaire et le tableau des jours fériés.
Avec ces infos, tu devrais pouvoir t'en sortir pour adapter ta formule. Ces fonctions utilisées en VBA sont les correspondantes de Serie.jour.ouvre.intl et nb.jours.ouvres.intl.
Bonjour Pierre,
Voilà a fonctionne presque, mais sans les jours fériés.
J'ai également découvert que la macro se référe aux titres du tableau, ce qui est très risqué si l'on change le titre : Jours fériés et ponts, comment sécuriser la référence ?
Merci
Philippe
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14 Private Sub Label_Ecart_Date_en_jrs_Click() Dim Start_Date As Date, DateFin As Date, Days As Long, Week As String, Holydays As Range, Duree As Variant ' If MsgBox("Remplacer la date de fin ?", vbYesNo + vbQuestion, "Calculer la date de fin") = vbYes Then ' 'Calcul de la date de fin si la date de début existe ' On Error GoTo Fin 'Si les dates sont vides Start_Date = LabelDateDebut DateFin = LabelDateFin Week = "0000011" Set Holydays = Range("Tableau_Fériés[Jours fériés et ponts]") 'Vérifier les dates dans le tableau de la feuille DATA Duree = WorksheetFunction.NetworkDays_Intl(Start_Date, DateFin, Week, Holydays) Label_Ecart_Date_en_jrs.Caption = Duree ' End If Fin: End Sub
Je ne comprends pas ce que tu veux dire lorsque tu dis sans les jours fériés, puisque tu les reprends dans l'argument Holydays que tu passes à la fonction :koi:
Oui, bien sûr, il y a un risque. C'est certain que si tu renommes le tableau et/ou ses colonnes, tu casses ton outil. Mais c'est la façon la plus stable de travailler. Normalement, si tu as bien choisi les noms de tes tableaux et de tes colonnes, il n'y a pas de raison qu'ils changent par la suite.
Par contre, si tu travailles avec une plage de données (donc pas un tableau structuré):
- Si tu déplaces la plage, le code VBA ne suit pas derrière et ta macro plantera aussi;
- Si tu ajoutes des données, tu devras travailler soit avec une plage nommée soit avec Range("A1048576").End(xlUp);
- Si tu travailles avec range("a1048576").End(xlUp) et que tu déplaces ta colonne, ce ne sera plus Range("A...");
- Si du déplaces ta plage sur une autre feuille, tu risques d'avoir des soucis aussi;
- Si tu renommes ta feuille et que tu as travaillé avec son nom d'onglet et pas son codename VBA, tu vas aussi planter;
- ...
Avec les références structurées, Les écueils énoncés ci-dessus disparaissent. Tu peux déplacer, sur la même feuille ou sur une autre, ajouter ou retrancher des infos, ton tableau structuré garantit la stabilité et la pérennité de ton code. Seule obligation, ne renommer ni le tableau ni ses colonnes. Idéalement, on devrait encadrer cela par une une gestion d'erreur (au moins au niveau de la procédure événementielle déclenchée par l'utilisateur) si on ne veut pas entrer en débogage. Mais c'est bien peu d'obligations par rapport aux anciennes méthodes (jusque et y compris Xl2003) lorsque les tableaux structurés n'existaient pas.
En fait je doit enlever un jour pour que le résultat soit correct, voir la macro.
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 Private Sub Label_Ecart_Date_en_jrs_Click() Dim Start_Date As Date, DateFin As Date, Days As Long, Week As String, Holydays As Range, Duree As Variant If LabelDateDebut = "" Or LabelDateFin = "" Then MsgBox "Les dates de début et de fin doivent être complétées.", vbInformation, "! Oups ! Action interrompue" Else Start_Date = LabelDateDebut DateFin = LabelDateFin Week = "0000011" On Error GoTo Description_erreur 'Si problème avec jours fériés Set Holydays = Range("Tableau_Fériés[Jours fériés et ponts]") 'Vérifier les dates dans le tableau de la feuille DATA Duree = WorksheetFunction.NetworkDays_Intl(Start_Date, DateFin, Week, Holydays) - 1 Label_Ecart_Date_en_jrs.Caption = Duree End If Exit Sub Description_erreur: MsgBox _ vbCrLf & vbCrLf & _ "- Il y a un problème avec le tableau des jours fériés." & vbCrLf & vbCrLf & _ "- Erreur VBA : " & vbCrLf & " " & Err.Description & vbCrLf & vbCrLf & _ "", vbExclamation, "! Oups ! Action interrompue" End Sub
Bonjour,
Peut-être que oui, peut-être que non. Tout dépend de la conception que l'on a du nombre de jours. À la base, Excel respecte les normes (Nord-)américaines du calcul des jours. Cela veut donc dire que le premier jour du délai, c'est le lendemain du jour de l'entente, du contrat. de l'emprunt etc. Et le dernier jour est inclus dans le décompte. Donc, de par chez-nous, tu empruntes pour dix jours le 1er du mois, le dernier jour du délai c'est le 11. Et, c'est à adapter pour se conformer aux coutumes et règles locales.
Pièce jointe 498614