Une boucle dans une "Array" qui aille au-delà de la limite supérieure de celle-ci

Magic_Doctor

XLDnaute Barbatruc
Bonjour,

Je voudrais connaître le nombre de jours entre un mois postérieur d'un mois donné (que j'ai appelé "MoisClôture") et celui-ci, dans une année de toujours 365 jours.
Je m'explique. Supposons que le mois dit "MoisClôture" soit le mois d'avril et que le mois postérieur soit le mois de septembre. Je voudrais alors connaître le nombre de jours entre le mois de septembre (inclu) et le mois d'avril de l'année suivante (inclu lui aussi).
Pour ce faire, j'ai rédigé la routine suivante qui fonctionne :
VB:
Sub NombreJours1() 'OK

    Dim x As Byte
    Dim i As Byte
    Dim nbjr1 As Integer, nbjr2 As Integer, totalnbjr As Integer
    
    mesmois = Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) 'année de 365 jours
    MoisClôture = 4 'avril
    x = 9 'septembre
            
    For i = x - 1 To UBound(mesmois) 'on va jusqu'à la fin de l'année civile
        nbjr1 = mesmois(i) + nbjr1 '1ère tranche du nombre de jours restant
    Next
    For i = 0 To MoisClôture - 1 'on va jusqu'au mois de clôture inclu
        nbjr2 = mesmois(i) + nbjr2 '2ème tranche du nombre de jours restant
    Next
    totalnbjr = nbjr1 + nbjr2
    
    [c15] = totalnbjr 'vérification sur la feuille
End Sub
Cependant, je suis obligé de faire 2 boucles. Je me demandais si l'on ne pouvait pas y arriver avec seulement un boucle. J'ai tenté de la manière suivante, mais ça plante :
VB:
Sub NombreJours2() 'Pas OK

    Dim x As Integer
    Dim i As Integer '"m" est déclaré "As Integer" dans la fonction "Multiple"
    Dim totalnbjr As Integer
    
    mesmois = Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) 'année de 365 jours
    MoisClôture = 4 'avril
    x = 9 'septembre
            
    For i = x - 1 To UBound(mesmois) + MoisClôture - 1
       totalnbjr = mesmois(MultipleMois(i, 12)) + totalnbjr
    Next
    
    [c15] = totalnbjr 'vérification sur la feuille
End Sub
------------------------------------------------------------------
Function Multiple(m As Integer, seuil As Byte) As Byte
'Fonction utilisée ailleurs dans l'application, alors j'en profite
'- m : variable
'- seuil : valeur seuil qui ne peut être dépassée par m
'Exemple : si seuil = 24, si m = 1 --> 1 / si m = 25 --> 1
'Dans ce cas, quel que soit m, le résultat sera toujours compris dans l'intervalle d'entiers [1 , 24]
'Si seuil = 12, l'intervalle d'entiers sera : [1 , 12]
'Magic_Doctor
    m = m - seuil * (m \ seuil)
    Multiple = IIf(m = 0, seuil, m)
End Function
Où me suis-je planté et est-ce possible ?
 
Dernière édition:

Dranreb

XLDnaute Barbatruc
Re : Une boucle dans une "Array" qui aille au-delà de la limite supérieure de celle-c

Bonjour.
Essayez comme ça :
VB:
Sub NombreJours1() 'OK

    Dim X As Byte, MoisClôture As Byte
    Dim NbJr As Integer
    Dim MesMois() As Variant
   
    MesMois = Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) 'année de 365 jours
    MoisClôture = 4 'avril
    X = 9 'septembre
   
    Do: NbJr = NbJr + MesMois(X - 1): If X = MoisClôture Then Exit Do
        X = X Mod 12 + 1: Loop
   
    [C15].Value = NbJr 'vérification sur la feuille
End Sub
 

job75

XLDnaute Barbatruc
Re : Une boucle dans une "Array" qui aille au-delà de la limite supérieure de celle-c

Bonjour Magic_Doctor, salut Dranreb,

Une seule boucle suffit en effet et voici la plus courte :

Code:
For i = moisclôture To x - 2
  totalnbjr = mesmois(i) + totalnbjr
Next
totalnbjr  = 365 - totalnbjr
[c15] = totalnbjr 'vérification sur la feuille

A+
 
Dernière édition:

pierrejean

XLDnaute Barbatruc
Re : Une boucle dans une "Array" qui aille au-delà de la limite supérieure de celle-c

Bonjour Magic_Doctor

Une proposition:

Code:
Sub test()
 mesmois = Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
For n = CDate("15/09/2013") To CDate("15/4/2014") Step 30
 nbj = nbj + mesmois(Month(n) - 1)
Next
MsgBox (nbj)
End Sub

Ni 2013 ni 2014 ne sont bissextiles
En choisissant du 15 au 15 step 30 on est garanti d’être dans le mois suivant

Edit: Salut Gerard (et bravo !!!)
Arf !! Je ne t'avais pas vu Bernard !! Donc Salut également à toi
 
Dernière édition:

Dranreb

XLDnaute Barbatruc
Re : Une boucle dans une "Array" qui aille au-delà de la limite supérieure de celle-c

Bonjour Pierrejean.
J'avais vaguement pensé aussi à des dates construites sur des années à coup sûr non bissextiles. Mais à ce compte là on devrait pouvoir s'en sortir avec une simple soustraction de ces dates, non ? C'est d"ailleurs pour cela que je ne l'ai pas proposé: Magic Doctor semble avoir tendance à ne pas adopter ce qui s'écarte trop de son idée de départ, surtout en matière de dates.
 

job75

XLDnaute Barbatruc
Re : Une boucle dans une "Array" qui aille au-delà de la limite supérieure de celle-c

Re,

Magic_Doctor adore les tableaux, je suis sûr que ceci va lui plaire :

Code:
Sub NombreJours2()

    Dim mesmois, MoisClôture%, x%, i%, totalnbjr%
     
    mesmois = Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) 'année de 365 jours
    mesmois = Split(Join(mesmois) & " " & Join(mesmois))
    
    MoisClôture = 4 'avril
    x = 9 'septembre
            
    For i = x - 1 To MoisClôture + 11 'MoisClôture - 1 + 12
      totalnbjr = mesmois(i) + totalnbjr
    Next
     
    [c15] = totalnbjr 'vérification sur la feuille
    
End Sub
Et pour compléter la question de pierrejean, si x < MoisClôture, ça n'a aucune importance : MoisClôture est le mois de l'année suivant l'année de x.

A+
 
Dernière édition:

Magic_Doctor

XLDnaute Barbatruc
Re : Une boucle dans une "Array" qui aille au-delà de la limite supérieure de celle-c

Merci amigos,

Ça marche !
J'ai fini par retenir la solution de job, car, où je suis, "spliter" les "joins" est une excellente initiative, en attendant qu'ils soient vendus en pharmacie... C'est pas des blagues !
 

job75

XLDnaute Barbatruc
Re : Une boucle dans une "Array" qui aille au-delà de la limite supérieure de celle-c

Bonjour Magic_Doctor, le fil,

On peut préciser si les années sont bissextiles :

Code:
Sub NombreJours2()

     Dim mesmois, bissex1$, bissex2$, MoisClôture%, x%, i%, totalnbjr%
     
      
     mesmois = Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) 'année de 365 jours
     bissex1 = "non"
     bissex2 = "oui" '2ème année bissextile
     mesmois = Split(Replace(Join(mesmois), 28, IIf(bissex1 = "oui", 29, 28)) _
       & " " & Replace(Join(mesmois), 28, IIf(bissex2 = "oui", 29, 28)))
     
     MoisClôture = 4 'avril
     x = 9 'septembre
           
     For i = x - 1 To MoisClôture + 11 'MoisClôture - 1 + 12
       totalnbjr = mesmois(i) + totalnbjr
     Next
      
     [c15] = totalnbjr 'vérification sur la feuille
     
End Sub
A+
 

Dranreb

XLDnaute Barbatruc
Re : Une boucle dans une "Array" qui aille au-delà de la limite supérieure de celle-c

Bonjour.
Si on dispose des années en plus des mois ça devient tout simple, prendre l'explression
VB:
DateSerial(AFin, MFin + 1, 1) - DateSerial(ADéb, MDéb, 1)
 

Magic_Doctor

XLDnaute Barbatruc
Re : Une boucle dans une "Array" qui aille au-delà de la limite supérieure de celle-c

Bonjour job, Dranreb, pierrejean, le forum,

Merci encore pour l'intérêt que vous portez à ce sujet.
J'avais ouvert ce fil afin de voir s'il était possible de synthétiser 2 boucles en une seule. J'ai opté pour la solution de job.
À l'origine, il s'agit d'une partie d'une fonction qui permet, dans un "plan d'amortissement linéaire" (que m'avait demandé ma fille, et je suis tout sauf comptable !), de proratiser la 1ère année d'une immobilisation quand la mise en service de celle-ci ne commence pas exactement en début d'année fiscale (ce qui, bien sûr, doit être la plupart du temps le cas).
J'en suis arrivé à la constatation suivante (je découvre le monde cauchemardesque de la comptabilité...) :
- si l'année est dite comptable (360 jours) : on se moque des années bissextiles, puisque tous les mois de toutes les années ont par définition 30 jours
- si l'année a 365 jours (année fiscale normale) : la "bissexilité" n'intervient en fait que si la date de mise en service de l'actif est uniquement comprise dans un mois de février d'une année bissextile ; il faut bien qu'on commence à calculer le nombre de jours entre la date de mise en service (INCLUSE !) et la fin du mois de février, et, que l'administration fiscale le veuille ou pas, 29 ce n'est pas 28. En revanche, par la suite, pour les autres années, on "survolera" le mois de février en partant toujours du principe qu'il ne comporte que 28 jours. Bon, tout ça n'est pas bien grave, après tout il ne s'agit que d'un seul jour, mais quand on fait les choses, autant bien les faire dès le départ et après qu'on n'en parle plus jamais ! Enfin, j'essaie de raisonner logiquement.
La solution de Dranreb est simple et laconique mais trop précise, dans la mesure où elle tient compte fatalement des années bissextiles. Mais, même l'utilisant, je ne pense pas un instant que l'on puisse être emmerdé un tant soit peu par le fisc (l'essentiel, pour lui, est que l'amortissement se fasse totalement de manière cohérente en fonction du type d'amortissement choisi -ici linéaire- et ils ne vont pas pinailler pour un jour, d'autant plus qu'au départ on peut opter -suivant le logiciel dont on dispose, je suppose- pour une année de 360 jours ou de 365 jours : 5 jours d'écart !).
La solution de job est plus souple, dans la mesure où l'on peut décider si on tient compte ou pas des années bissextiles ; ce qui, dans d'autres circonstances que comptables, pourrait avoir un intérêt. Mais là, il faudra paramétrer la macro en stipulant si l'on tient compte ou pas des années bissextiles.
Je glisse ma fonction (que j'avais déjà mise dans un fil plus "ad hoc") :
VB:
Function PremièreAnnuité(fecha As Date, Optional TypeAnnée As Byte = 1, Optional MoisClôture As Byte = 12) As Integer
'Nombre de jours depuis une date donnée (INCLUSE) jusqu'à la fin de l'année fiscale
'- fecha : date de mise en service de l'actif
'- TypeAnnée = 1 : année comptable --> 12 mois de 30 jours <=> 360 jours
'- TypeAnnée = 2 : année fiscale normale de 365 jours
'si "TypeAnnée" est omis, par défaut ce sera une année dite comptable de 360 jours, de loin la plus fréquente
'- MoisClôture : mois de clôture
'si "MoisClôture" est omis, par défaut ce sera le mois de décembre (12), de loin le plus fréquent
'Éxemples:
'"=PremièreAnnuité(une_date;2;10)" --> nombre de jours, dans une année de 365 jours, entre la date (incluse) et le 31 octobre
'"=PremièreAnnuité(une_date;1;10)" ou "=PremièreAnnuité(une_date;;10)" --> nombre de jours, dans une année de 360 jours, entre la date (incluse) et le 30 octobre
'"=PremièreAnnuité(une_date;2)" --> nombre de jours, dans une année de 365 jours, entre la date (incluse) et le 31 décembre
'"=PremièreAnnuité(une_date)" --> nombre de jours, dans une année de 360 jours, entre la date (incluse) et le 30 décembre
'Magic_Doctor / job75
    Dim mesmois As Variant, nbjoursmois As Byte, i As Byte, nbjr As Integer
    nbjoursmois = IIf(TypeAnnée = 1, 30, NbJoursDuMois(Month(fecha), Year(fecha)))
    mesmois = Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) 'année de 365 jours
    mesmois = Split(Join(mesmois) & " " & Join(mesmois))
    
    If Month(fecha) <= MoisClôture Then
        If TypeAnnée = 1 Then 'année de 360 jours
            nbjr = 30 * (MoisClôture - Month(fecha))
        Else 'année de 365 jours
            For i = Month(fecha) To MoisClôture - 1
                nbjr = mesmois(i) + nbjr
            Next
        End If
    Else
        If TypeAnnée = 1 Then 'année de 360 jours
            nbjr = 30 * (12 + MoisClôture - Month(fecha))
        Else 'année de 365 jours
            For i = Month(fecha) To MoisClôture + 11
                nbjr = mesmois(i) + nbjr
            Next
        End If
    End If
    PremièreAnnuité = nbjoursmois - Day(fecha) + 1 + nbjr
End Function
------------------------------------------------------------------------------
Function NbJoursDuMois(m As Byte, Optional année As Integer = 0) As Byte
'Renvoie le nombre de jours d'un mois en fonction de son Nº
' m : un Nº de mois (janvier --> 1 ... décembre --> 12)
'- année : si omis, ne tiendra pas compte des années bissextiles (février -2- aura toujours 28 jours)
'Magic_Doctor
    Dim mesmois As Variant, x As Byte, nbjoursmois As Byte
    
    x = IIf(année = 0, 28, IIf(LeapYear(année), 29, 28))
    mesmois = Array(31, x, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
    
    NbJoursDuMois = mesmois(m - 1)
End Function
------------------------------------------------------------------------------
Function LeapYear(a%) As Boolean
'Vérifie si une année est bissextile ou pas (tient compte des années théoriquement bissextiles et qui ne le sont en fait pas, comme 1800/1900/2100...)
'- a : une année quelconque
'ROGER2327
    LeapYear = ((a Mod 4) = 0) * (1 + ((a Mod 100) = 0) * (1 + (((a \ 100) Mod 4) = 0)))
End Function
Bref, pas si simple que ça la proratisation.

Bonne journée à tous.
 
Dernière édition:

pierrejean

XLDnaute Barbatruc
Re : Une boucle dans une "Array" qui aille au-delà de la limite supérieure de celle-c

Re

Pour les allergiques aux split des join , une variante du job de Gerard

Code:
Sub NombreJours2()
    Dim mesmois, MoisClôture%, x%, i%, totalnbjr%
    mesmois = Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) 'année de 365 jours
    mesmois = Split(Join(mesmois) & " " & Join(mesmois))
    MoisClôture = 4 'avril
    x = 9 'septembre
    For i = x - 1 To MoisClôture + 11 'MoisClôture - 1 + 12
      totalnbjr = mesmois(i) + totalnbjr
    Next
    [c15] = totalnbjr 'vérification sur la feuille
End Sub
Sub NombreJours3()
    Dim mesmois, MoisClôture%, x%, i%, totalnbjr%
    mesmois = Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) 'année de 365 jours
    MoisClôture = 4 'avril
    x = 9 'septembre
    For i = x - 1 To MoisClôture + 11 'MoisClôture - 1 + 12
      totalnbjr = mesmois(i Mod 12) + totalnbjr
    Next
    [c15] = totalnbjr 'vérification sur la feuille
End Sub
 
Dernière édition:

Discussions similaires

Statistiques des forums

Discussions
312 305
Messages
2 087 070
Membres
103 453
dernier inscrit
Choupi