Ceci est une page optimisée pour les mobiles. Cliquez sur ce texte pour afficher la vraie page.

Date et heure EcartDate

mapomme

XLDnaute Barbatruc
Supporter XLD
Bonjour à tous,

Beaucoup de question sur comment calculer l'âge d'une personne à partir de sa date de naissance ou bien le nombre d'année, de mois et de jour entre deux dates.

J'ai repris une fonction de @ROGER2327 qui l'avait lui-même reprise de JP Mesters et j'ai ajouté quelques options.

La fonction : EcartDate(Debut As Date, Fin As Date, Optional Quoi As String = "", Optional Langue As String = ".fr")

Debut est la date de début de la période (c'est une vraie date au sens d'Excel pas du texte)
Fin est la date de début de la période (c'est une vraie date au sens d'Excel pas du texte)
Quoi est ce qu'on désire en sortie :
  • ce paramètre est facultatif
  • si quoi = 1 ou "a" ou "y" alors on retourne un nombre qui est le nombre d'année entre le Debut et la Fin
  • si quoi = 2 ou "m" alors on retourne un nombre qui est le nombre de mois entre le Debut et la Fin
  • si quoi = 3 ou "j" ou "d" alors on retourne un nombre qui est le nombre de jour entre le Debut et la Fin
  • si quoi est omis ou différent des valeurs ci-dessus alors on retourne la durée (âge) en texte sous la forme texte : n an m mois j jour
  • on adapte le texte de sortie avec les singuliers ou pluriels requis.
Langue est un texte indiquant la langue à utiliser :
  • ce paramètre est facultatif
  • cet argument sera égal un court texte commençant par un point et suivi du suffixe internet (pour site du pays de la langue désirée)
  • exemple de texte : .fr (français), .gb (anglais), .uk (anglais), .usa (américain), .de (allemand), .es (espagnol), .it (italien), .pt (portugais), .cor (corse)
  • si Langue est omis ou bien ne correspond pas à une des traductions alors la langue sera le français
Pour ajouter une langue dans le code :
  • dupliquer la dernière ligne de type texte = texte & "," & ".cor,annu,anni,m...
  • remplacer cor par le code du pays parlant la langue désirée
  • puis, séparées par des virgules, indiquer les traductions de an (au singulier puis au pluriel), de mois (au singulier puis au pluriel) et enfin de jour (au singulier puis au pluriel).

Vos avis, critiques et suggestions sont les bienvenues. Il faudrait aboutir à une fonction personnalisée avec un consensus "presque général".
Si c'est une mauvaise idée ou bien redondant alors je retirerai la fonction sans en être marri en aucune manière.

Le code est dans module1:
VB:
Function EcartDate(Debut As Date, Fin As Date, Optional Quoi As String = "", Optional Langue As String = ".fr")
' adapté d'un code de -> JP Mesters
Const defaut = ".fr"

Dim texte$, Nba&, Nbm&, Nbj&, Retenue&, s$, t, i&
   If Debut > Fin Then EcartDate = "#CHRONOLOGIE!": Exit Function
   texte = ".fr,an,ans,mois,mois,jour,jours"                         'français (.fr)
   texte = texte & "," & ".gb,year,years,month,months,day,days"      'anglais (.gb)
   texte = texte & "," & ".uk,year,years,month,months,day,days"      'anglais (.uk)
   texte = texte & "," & ".usa,year,years,month,months,day,days"     'américain (.usa)
   texte = texte & "," & ".de,Jahr,Jahre,Monat,Monate,Tag,Tage"      'allemand (.de)
   texte = texte & "," & ".es,año,años,mes,meses,día,días"           'espagnol (.es)
   texte = texte & "," & ".it,anno,anni,mese,mesi,giorno,giorni"     'italien (.it)
   texte = texte & "," & ".pt,ano,anos,mês,meses,dia,dias"           'portugais (.pt)
   texte = texte & "," & ".cor,annu,anni,mese,mesi,ghjornu,ghjorni"  'corse (.cor)
 
   Nba = Year(Fin) - Year(Debut)
   Nbm = Month(Fin) - Month(Debut)
   Nbj = Day(Fin) - Day(Debut)
   Retenue = Day(DateSerial(Year(Fin), Month(Fin), 0))
   If Nbj < 0 Then Nbm = Nbm - 1: Nbj = Nbj + Retenue
   If Nbm < 0 Then Nba = Nba - 1: Nbm = Nbm + 12

   Select Case Left(LCase(Quoi), 1)
      Case "a", "y", "1"
         EcartDate = Nba: Exit Function
      Case "m", "2"
         EcartDate = Nbm: Exit Function
      Case "j", "d", "3"
         EcartDate = Nbj: Exit Function
      Case Else
         Quoi = LCase(Quoi): Langue = LCase(Langue): t = Split(LCase(texte), ",")
         If Left(Langue, 1) <> "." Then Langue = defaut
         For i = 0 To UBound(t)
            If Langue = t(i) Then Exit For
         Next i
         If i > UBound(t) Then i = 1
         s = IIf(Nba = 0, "", IIf(Nba = 1, "1 " & t(i + 1), Nba & " " & t(i + 2)))
         s = Trim(s & " " & IIf(Nbm = 0, "", IIf(Nbm = 1, "1 " & t(i + 3), Nbm & " " & t(i + 4))))
         s = Trim(s & " " & IIf(Nbj = 0, "", IIf(Nbj = 1, "1 " & t(i + 5), Nbj & " " & t(i + 6))))
   End Select
   EcartDate = s
End Function
 

Pièces jointes

  • calcul âge-v1.xlsm
    25.7 KB · Affichages: 24
Dernière édition:

mapomme

XLDnaute Barbatruc
Supporter XLD
comment renvoyer le nombre de jours ou le nombre de mois réels entre les deux dates
En général, je préfère rester avec un nombre très limité d'options possibles pour permettre à l'utilisateur de s'en souvenir sans recours à une recherche d'aide ou relecture du code pour connaitre les options.
Bien souvent, on peut avec une formule retrouver d'autres résultats.

renvoyer le nombre de jours:
Il suffit de soustraire les deux dates : =Fin - Debut point besoin d'une fonction personnalisée

renvoyer le nombre de mois réels :
Si j'ai bien compris "=12 * ECARTDATE(Debut ; Fin ; 1) + ECARTDATE(Debut ; Fin ; 2)" devrait le faire.
 
Dernière édition:

mapomme

XLDnaute Barbatruc
Supporter XLD
par la même occasion j'aurais mis la détection de langue automatique
Salut @patricktoulon ,

  • J'aime quand d'autres propositions sont faites. L'idée de la détection de la langue est très intéressante.. .
  • Le Case est bien aussi. J'avoue ne pas m'être posé la question de l'optimisation de l'exécution.

On stocke tout ça pour la fonction finale vers laquelle on pourra créer un lien pour des réponses rapides aux questions relatives à ce problème de durée.
 

patricktoulon

XLDnaute Barbatruc
re
voila ma vision
changer les "100" pour les bons code dans les cases( si je les retrouve je vous les donnerais )
en ajouter autant que vous voulez
  1. plus de split de texte et tout le tointoin
  2. détection automatique de la langue si argument omis
  3. n’empêche pas l'utilisation d'une langue différente du system
  4. l'argument langue peu etre le code country ou l'initiale
VB:
Option Explicit

Function EcartDate(Debut As Date, Fin As Date, Optional Quoi As String = "", Optional Langue As String = "")
' adapté d'un code de -> JP Mesters

    If Debut > Fin Then EcartDate = "#CHRONOLOGIE!": Exit Function
    Dim Nba&, Nbm&, Nbj&, Retenue&, s$, t, i&
    If Langue = "" Then Langue = Application.International(xlCountrySetting)

    Select Case LCase(Langue)
    Case 33, ".fr": t = Array("an", "ans", "mois", "mois", "jour", "jours")    'french
    Case 49, ".de": t = Array("Jahr", "Jahre", "Monat", "Monate", "Tag", "Tage")    'dusch
    Case 34, ".es": t = Array("año", "años", "mes", "meses", "día", "días")    'spanich
    Case 1, 44, 100, ".uk", ".gb", ".usa": t = Array("year", "years", "month", "months", "day", "days")    'english
    Case ".it", 100: t = Array("anno", "anni", "mese", "mesi", "giorno", "giorni")    'italian
    Case ".pt", 100: t = Array("ano", "anos", "mês", "meses", "dia", "dias")    'portugesh
    Case ".cor": t = Array("annu", "anni", "mese", "mesi", "ghjornu", "ghjorni")    'corse
        'etc...etc...
    Case Else: t = Array("year", "years", "month", "months", "day", "days")   ' on le met par defaut en anglaais (langue universelle) au cas ou la langue n'est pas retrouvée
    End Select

    Nba = Year(Fin) - Year(Debut)
    Nbm = Month(Fin) - Month(Debut)
    Nbj = Day(Fin) - Day(Debut)
    Retenue = Day(DateSerial(Year(Fin), Month(Fin), 0))
    If Nbj < 0 Then Nbm = Nbm - 1: Nbj = Nbj + Retenue
    If Nbm < 0 Then Nba = Nba - 1: Nbm = Nbm + 12

    Select Case Left(LCase(Quoi), 1)
    Case "a", "y", "1"
        EcartDate = Nba: Exit Function
    Case "m", "2"
        EcartDate = Nbm: Exit Function
    Case "j", "d", "3"
        EcartDate = Nbj: Exit Function
    Case Else
        s = IIf(Nba = 0, "", IIf(Nba = 1, "1 " & t(0), Nba & " " & t(1)))
        s = Trim(s & " " & IIf(Nbm = 0, "", IIf(Nbm = 1, "1 " & t(2), Nbm & " " & t(3))))
        s = Trim(s & " " & IIf(Nbj = 0, "", IIf(Nbj = 1, "1 " & t(4), Nbj & " " & t(5))))
    End Select
    EcartDate = s
End Function
Sub test()
    Dim date1 As Date, date2 As Date
    date2 = CDate("20/06/2021")
    date1 = CDate("12/03/2019")
    MsgBox EcartDate(date1, date2)    'langue par defaut du system WINDOWS(et non celui de excel)
    MsgBox EcartDate(date1, date2, , 33)    'langue francais forcée
    MsgBox EcartDate(date1, date2, , ".fr")    'langue francais forcée
    MsgBox EcartDate(date1, date2, , ".uk")    'langue valable pour  anglais uk/ us /gb  forcée
    MsgBox EcartDate(date1, date2, , 49)    'langue allemand forcée
    MsgBox EcartDate(date1, date2, , ".es")    'langue allemand forcée

End Sub
 

patricktoulon

XLDnaute Barbatruc
re
j'irais même plus loin pour nba/nbm/nbj
demande du numerique avec l'intitulé ou pas
  1. plus de split de texte et tout le tointoin
  2. détection automatique de la langue si argument omis
  3. n’empêche pas l'utilisation d'une langue différente du system
  4. l'argument langue peu etre le code country ou l'initiale
  5. nba/nbm/nbj avec intitulé ou pas
VB:
Option Explicit

Function EcartDate(Debut As Date, Fin As Date, Optional Quoi As String = "", Optional Langue As String = "")
' adapté d'un code de -> JP Mesters

    If Debut > Fin Then EcartDate = "#CHRONOLOGIE!": Exit Function
    Dim Nba&, Nbm&, Nbj&, Retenue&, s$, t, i&, withlang
    withlang = Langue <> ""
    If Langue = "" Then Langue = Application.International(xlCountrySetting)

    Select Case LCase(Langue)
    Case 33, ".fr": t = Array("an", "ans", "mois", "mois", "jour", "jours")    'french
    Case 49, ".de": t = Array("Jahr", "Jahre", "Monat", "Monate", "Tag", "Tage")    'dusch
    Case 34, ".es": t = Array("año", "años", "mes", "meses", "día", "días")    'spanich
    Case 1, 44, 100, ".uk", ".gb", ".usa": t = Array("year", "years", "month", "months", "day", "days")    'english
    Case ".it", 100: t = Array("anno", "anni", "mese", "mesi", "giorno", "giorni")    'italian
    Case ".pt", 100: t = Array("ano", "anos", "mês", "meses", "dia", "dias")    'portugesh
    Case ".cor": t = Array("annu", "anni", "mese", "mesi", "ghjornu", "ghjorni")    'corse
        'etc...etc...
    Case Else: t = Array("year", "years", "month", "months", "day", "days")   ' on le met par defaut en anglais (langue universelle) au cas ou la langue n'est pas retrouvée
    End Select

    Nba = Year(Fin) - Year(Debut)
    Nbm = Month(Fin) - Month(Debut)
    Nbj = Day(Fin) - Day(Debut)
    Retenue = Day(DateSerial(Year(Fin), Month(Fin), 0))
    If Nbj < 0 Then Nbm = Nbm - 1: Nbj = Nbj + Retenue
    If Nbm < 0 Then Nba = Nba - 1: Nbm = Nbm + 12

    Select Case Left(LCase(Quoi), 1)
    Case "a", "y", "1"
        EcartDate = Nba & IIf(Langue <> "" And withlang, IIf(Nba <= 1, " " & t(0), " " & t(1)), ""): Exit Function
    Case "m", "2"
        EcartDate = Nbm & IIf(Langue <> "" And withlang, IIf(Nbm <= 1, " " & t(2), " " & t(3)), ""): Exit Function
    Case "j", "d", "3"
        EcartDate = Nbj & IIf(Langue <> "" And withlang, IIf(Nbj <= 1, " " & t(4), " " & t(5)), ""): Exit Function
    Case Else
        s = IIf(Nba = 0, "", IIf(Nba = 1, "1 " & t(0), Nba & " " & t(1)))
        s = Trim(s & " " & IIf(Nbm = 0, "", IIf(Nbm = 1, "1 " & t(2), Nbm & " " & t(3))))
        s = Trim(s & " " & IIf(Nbj = 0, "", IIf(Nbj = 1, "1 " & t(4), Nbj & " " & t(5))))
    End Select
    EcartDate = s
End Function
Sub test()
    Dim date1 As Date, date2 As Date
    date2 = CDate("20/06/2021")
    date1 = CDate("12/03/2019")
   
    MsgBox EcartDate(date1, date2, 1, ".es")    'nombre d'année +langue
    MsgBox EcartDate(date1, date2, 1)    'nombre d'année

    MsgBox EcartDate(date1, date2, 2, ".uk")    'nombre de mois  +langue
    MsgBox EcartDate(date1, date2, 2)    'nombre de mois

    MsgBox EcartDate(date1, date2, 3, ".es")    'nombre de jours  +langue
    MsgBox EcartDate(date1, date2, 3)    'nombre de jour

     MsgBox EcartDate(date1, date2)    'langue par defaut du system WINDOWS(et non celui de excel)
    MsgBox EcartDate(date1, date2, , 33)    'langue francais forcée
    MsgBox EcartDate(date1, date2, , ".fr")    'langue francais forcée
    MsgBox EcartDate(date1, date2, , ".uk")    'langue valable pour  anglais uk/ us /gb  forcée
    MsgBox EcartDate(date1, date2, , 49)    'langue allemand forcée
    MsgBox EcartDate(date1, date2, , ".es")    'langue allemand forcée

End Sub

elle est déconcertante de simplicité cette fonction j'adore je vote oui
 

mapomme

XLDnaute Barbatruc
Supporter XLD
Re @patricktoulon, @Yeahou,

J'étais arrivé au même code. Je le gardais sous le coude.

Pour moi, avec l'option 1, 2 ou 3, le retour doit être un nombre et pas un texte.

Comme toi, la fonction me semble juste. Je ne crois pas qu'il faille tergiverser.
Doit-on attendre les votes à foison ou bien les modo (dont @Yeahou ), peuvent-ils la juger et, le cas échéant, l'inclure dans le classeur des fonctions personnalisées ?

Il va falloir qu'on avance sur la mise à disposition de quelques fonctions personnalisées sinon ce forum va tourner à vide (et ça me chagrinerait).
 
Dernière édition:

patricktoulon

XLDnaute Barbatruc
re
a ben je ne sais pas quand ce dit classeur de fonction perso sera conçu
je suppose que David pourrait répondre a cette question
perso j'aime bien ce forum
il est quand même plus tranquille et certainement plus pointu (pour la plus part )que le forum excel
faut pas se presser
il y a déjà quelques fonctions intéressantes mais encore trop peu de valables pour en faire un complément
 

mapomme

XLDnaute Barbatruc
Supporter XLD
il y a déjà quelques fonctions intéressantes mais encore trop peu de valables pour en faire un complément
D'accord avec toi.

Ce n'est pas si facile de trouver des fonctions personnalisées utiles, assez générales, simples d'emploi et faciles à comprendre par quelqu'un qui les découvrent.

C'est pourquoi le classeur va être difficile à garnir.

Pour l'instant, je vois des fonctions dates et heures (à foison), des fonctions d'extraction de chaines (par exemple des nombres cachés dans du texte), quelques problèmes plus généraux (dont classement avec doublons).
Je manque sans doute d'imagination et d'expérience pour en dénicher d'autres qui soient intéressantes.

Une fois le classeur en route, il faudra le documenter et surtout il faudra le traduire en anglais pour inonder le marché mondial ; voyons en grand
 
Dernière édition:

patricktoulon

XLDnaute Barbatruc
ben pour certaines on fait aussi bien avec l'association de fonction existante
il est donc difficile de les prendre en compte
par exemple les doublons
on peut très bien faire une liste sans doublons en formule et la formule elle même est pas très compliqué
et dieu sait que les formules c'est pas mon fort
d'autre sont tout bonnement sans intérêt (selon moi) dans l'optique de ce classeur complément
en tout cas ta fonction je l'ai intégré dans ma biblio avec la mienne dans une version simplifiée
basé sur la tienne
VB:
Function Datediff_AMJ2$(ByVal Debut, Optional ByVal Fin = 0)
' adapté d'un code de -> @mapomme sur exceldownloads dans le forum des fonction personnalisées
    If Fin = 0 Then Fin = Date
    If Debut > Fin Then EcartDate = "#CHRONOLOGIE!": Exit Function


    Nba = Year(Fin) - Year(Debut): Nbm = Month(Fin) - Month(Debut)
    Nbj = Day(Fin) - Day(Debut): Retenue = Day(DateSerial(Year(Fin), Month(Fin), 0))
    If Nbj < 0 Then Nbm = Nbm - 1: Nbj = Nbj + Retenue
    If Nbm < 0 Then Nba = Nba - 1: Nbm = Nbm + 12

    s = IIf(Nba = 0, "", IIf(Nba = 1, "1 " & "an", Nba & " ans"))
    s = Trim(s & " " & IIf(Nbm = 0, "", IIf(Nbm = 1, "1 mois", Nbm & " mois")))
    s = Trim(s & " " & IIf(Nbj = 0, "", IIf(Nbj = 1, "1  jour", Nbj &  " jours")))

    Datediff_AMJ2$ = s
End Function

Sub test()
    Dim date1 As Date, date2 As Date
    date1 = CDate("20/06/2021")
    date2 = CDate("12/03/2019")
    MsgBox Datediff_AMJ2$(date2, date1)
    MsgBox Datediff_AMJ2$(CDate("04/03/1970"))

End Sub

la mienne
VB:
Function Datediff_AMJ$(ByVal dat1, Optional ByVal dat2 = 0)
    Dim a%, m%, j%, dtemp As Date, Erreur$
    If dat2 = 0 Then dat2 = Date
    Erreur = IIf(Not IsDate(dat1), "(1)", ""): Erreur = Erreur & IIf(Not IsDate(dat2), "(2)", ""): Erreur = IIf(Erreur <> "", "Invalid Argmt(" & Erreur & ")", "")
    If Erreur <> "" Then Datediff_AMJ = Erreur: Exit Function
    dat1 = CDate(dat1): dat2 = CDate(dat2)
    If dat1 > dat2 Then dtemp = dat1: dat1 = dat2: dat2 = dtemp
    a = Evaluate("DATEDIF(" & CDbl(dat1) & "," & CDbl(dat2) & ",""y"")")
    m = Evaluate("DATEDIF(" & CDbl(dat1) & "," & CDbl(dat2) & ",""ym"")")
    j = Abs(DateSerial(Year(dat1) + a, Month(dat1) + m, Day(dat1)) - dat2)
    Datediff_AMJ = RTrim(IIf(a, a & " an" & IIf(a = 1, " ", "s "), "") & IIf(m, m & " mois ", "") & IIf(j, j & " jour" & IIf(j = 1, "", "s"), ""))
End Function

Sub test()
    MsgBox Datediff_AMJ("02/02/2020", "25/01/2017")
    MsgBox Datediff_AMJ("25/01/2017", "02/02/2020")
    MsgBox Datediff_AMJ("04/03/1970")
    MsgBox Datediff_AMJ("toto", "titi")
    MsgBox Datediff_AMJ("25/04/2016", "titi")
End Sub
 

Magic_Doctor

XLDnaute Barbatruc
Re,

Manifestement, ce sont des codes internationaux pour le tel.
it --> 39
pt --> 351
uk = gb --> 44
usa --> 1
etc.
 

Etoto

XLDnaute Barbatruc
Bonjour à tous,

Savez-vous si dans le quoi on peux rajouter une option qui calcule en jour et en heure ? Si c'est trop complexe tant pis alors. Sinon merci déjà de cette super fonction et bravo du travail.

Cordialement.
 

Discussions similaires

  • Question
Microsoft 365 Excel VBA
Réponses
14
Affichages
790
Les cookies sont requis pour utiliser ce site. Vous devez les accepter pour continuer à utiliser le site. En savoir plus…