Procédure trop grande

Bonjour à tous,

Je fais une application pour des jardiniers avec un planning semestriel qui reprend les semaines de semis/récolte. La macro se trouve en module 2.

Je peux reculer d'un semestre à l'autre pour 5 choix de légumes (Si vous cliquez sur la flêche < , macro "semestPréc" çà passe).

J'ai rajouté 40 autres cultures sur a macro "semestriel suivant" , et j'arrive à presque 1000 lignes pour la macro, et çà passe plus, (flêche >, macro "semestSuiv") avec le message:

image

J'ai lu quelques réponses sur le sujet pour réduire le code et diviser la macro, mais je vois pas trop comment faire.

Merci de votre aide.

2jardins-allg.zip (1.27 Mo)

Bonjour,

Place les deux procédures longues sur deux modules différents et lance-les depuis la macro d'origine

Bonjour M12,

Merci pour ta réponse rapide.

J'ai 2 macros, suivant et précédent, dans lesquelles j'ai 4 blocs de code assez long, et j'ai donc fait 4 modules pour la 1ere macro, pour voir.

Cà passe, mais çà n'éxécute pas les 4 modules, et y'a plus rien dans le tableau. :

         drlig = 3
For i = 2 To drn2
    'semaine semis et semaine récolte dans le semestre
    If ((ws2.Range("E" & i).Value <= CSng(sema2) And Year(ws2.Range("D" & i).Value) = an) _
        Or (ws2.Range("H" & i).Value >= CSng(sema1) And Year(ws2.Range("G" & i).Value) = an)) Then
           For k = sema1 To sema2
                If sema1 = 1 And (ws2.Range("E" & i).Value <= CSng(sema2) Or ws2.Range("H" & i).Value >= CSng(sema1)) _
                    And Year(ws2.Range("D" & i).Value) = an Then
                    'couleurs semis et récoltes 1er semestre (semaines 1 à 26)
                        Module1.resume1
                    'couleurs récoltes 1er semestre (semaines 1 à 26) semées au semestre précédent
                        Module4.resume2
                    'couleurs semis et récoltes 2eme semestre (semaines 27 à 52)
                        Module5.resume3
                    'couleurs semis 2eme semestre et récolte l'année suivante
                        Module6.resume4
                End If
            Next k
            If ws1.Cells(drlig, 1).Value = "" Then GoTo there
        If (ws2.Range("E" & i + 1).Value <= sema2 And ws2.Range("E" & i + 1).Value >= sema1 And _
            Year(ws2.Range("D" & i + 1).Value) = an) Or (ws2.Range("H" & i + 1).Value >= sema1 _
            And ws2.Range("H" & i + 1).Value <= sema2 And Year(ws2.Range("G" & i + 1).Value) = an) Then drlig = drlig + 1
    End If
there:
Next i

Je vais essayer de voir comment çà fonctionne.
A+

1jardins-allg.zip (1.29 Mo)

re,

je pense que la macro "Sub Nouv_Semestre(bSem)" fait le nécessaire ...

2jardins-allg.zip (1.25 Mo)

Bonjour BsAlv,

Wouah, génial, j'avais pas essayé çà alors.

Merci, je vais voir si je peux le faire avec la même mise en page.

Magnifique

re,

bonne chance, s'il y a encore des problèmes, il faut le dire ...

Bonjour BsAlv,

J'ai réussi à comprendre à peu prés ton code, mais il y a juste une erreur que je ne suis pas arrivé à corriger, c'est de mettre "1er Sem." et 2ème Sem aux 2 semestres.

Si tu pouvais voir çà.

Merci

re,

je prends F1, le lundi de la 2ème semaine, parce que la première est souvent dans un autre mois/année. Si le mois de cette date >6 (normallement on n'a que des dates en janvier ou juillet), on est dans le 2ème semestre. Si on veut le semestre suivant, alors c'est le 1 janvier de l'année suivant, si on veut le semestre précédent, c'est le 1 janvier de la même année, etc. Le fin de ce semestre + 1 jour = 6 mois plus tard et c'est la date "Nouv_Date2". Celle-là a peut-être donné de la confusion !

Puis on donne la valeur de cette année à la cellule A1. Même chose avec le semestre, mais là, je vois que j'ai pris "Nouv_Dat2", donc 6 mois après (!) et si cette date est en juillet, on est dans le premier semestre. C'était mieux compréhensible, si j'avais pris Nouv_Date (voir dernière ligne ici dessous) et si le mois est <7 = premier semestre, autrement deuxième semestre.

(Si cette date n'est pas un lundi, on prend le lundi précédent pour le mettre dans E1.)

.Range("A1").Value = Year(Nouv_Date)

.Range("A2").Value = IIf(Month(Nouv_Date2) = 7, 1, 2) & "ème Sem."   '---> avec Nouv_Date2
.Range("A2").Value = IIf(Month(Nouv_Date) < 7, 1, 2) & "ème Sem." '---> même chose mais avec Nouv_Date
 

mais peut-être vous ne voulez pas cette explication, simplement ceci

.Range("A2").Value = IIf(Month(Nouv_Date) < 7, "1er", "2ème" ) & " Sem." '---> même chose mais avec Nouv_Date

Concernant les semaines, j'ai utilisé le système d' "ISO.SEMAINE" qu'on utilise en Europe et la majorité du monde et ne pas le système américain.

Ok çà marche maintenant 1er et 2éme Sem.

Ton travail pour recadrer correctement les dates sur les bonnes semaines est super .

Par contre, les flêches ne font plus apparaitre les nouvelles cultures enregistrées au 1er semestre 2023, les 2 1eres lignes.

3jardins-allg.zip (939.29 Ko)

Merci

re,

pour ces 2 lignes, 3 des 4 dates sont format "texte", donc ce ne sont pas vraiment des dates. Vous utilisez ces dates encore ailleurs ?

Pour moi, c'est facile pour adapter ma macro qu'elle fonctionne aussi avec de textes, mais si cela cause aussi d'autres problèmes, c'est peut-être plus facile à éviter ce type de données ?

re,

D2:D3 sont encore des dates sous forme de "texte" et la macro les transforme comme date. Ces colonnes ont une validation pour le moment.

1jardins-allg-1.zip (888.27 Ko)

Bonjour à tous,

Effectivement c'était de ma faute j'ai pas mis le bon format CDate(Format(Me.datA.Value, "dd/mm/yy")) en enregistrement/ modif.

Maintenant çà apparait dans le semestre.

Merci BsAlv

Par contre ce que tu as rajouté là ne permet pas de garder les couleurs de la police, qui a parfois besoin d'être en blanc (noir sur noir on voit rien).

 If B Then
                             R = Application.Match(ab(i, 2), Sheets("Listes").Range("G1:G100"), 0)
                             If IsNumeric(R) Then
                                  .Cells(ptr, 5).Resize(, UBound(aA)).SpecialCells(xlConstants).Interior.Color = Sheets("listes").Cells(R, "G").Interior.Color
                             End If
                        End If

Désolé

re,

Quelque lignes plus haut, en cas que la culture ou l'abrégé est inconnu, on a ceci (cela ne cause pas votre problème, je suppose)

  If ab(i, 4) <= Nouv_Date2 And Nouv_Date <= ab(i, 7) Then
                    If ab(i, 3) = "" Then ab(i, 3) = "???"     'abrégé inconnu
                    If ab(i, 2) = "" Then ab(i, 2) = "???"     'culture inconnu
                    .Cells(ptr, 1) = ab(i, 2)     'nom culture
        

Puis votre problème est que la culture de votre ligne est inconnue dans la colonne G de "Listes", parce que c'est là que je prend les couleurs. Si vous ne voulez pas ce "noir", alors supprimer ce "else" comme vous l'avez fait, mais mieux, c'est d'ajouter cette culture dans la colonne G. Ajouter une sorte de validation avec cette colonne G sur la colonne B de "Cultures" est malin.

      If B Then     'boolean = pour savoir s'il y a des cultures entre colonne E:AE de cette ligne
                         R = Application.Match(ab(i, 2), Sheets("Listes").Range("G1:G100"), 0)     'cherchez cette culture dans la colonne G de "liste"
                         If IsNumeric(R) Then     'culture connue
                              .Cells(ptr, 5).Resize(, UBound(aA)).SpecialCells(xlConstants).Interior.Color = Sheets("listes").Cells(R, "G").Interior.Color
                         Else     'culture inconnue
                              .Cells(ptr, 5).Resize(, UBound(aA)).SpecialCells(xlConstants).Interior.ColorIndex = 1
                         End If
                    End If

Puis votre problème est que la culture de votre ligne est inconnue dans la colonne G de "Listes"

C'est faux. Les cultures sont toutes en colonne G en "listes".

Les couleurs de fond sont reproduites mais pas la police en blanc, exemple pour l'aubergine ou la courgette, que j'ai mis en "Cultures" et apparait en "Semestriel".

image
3jardins-allg.zip (1.29 Mo)

Il faudrait CRG écrit en blanc.

j'ai ajouté le couleur de la police.

Bonjour Bsalv,

Je reviens vers toi aprés ton super boulot sur la macro rapide de l'onglet semestriel.

C'est la macro Sub Nouv_Semestre(bSem) dans le module9

Maintenant que je me penche dessus, je réalise l'exercice que je dois en faire.

     Sub Nouv_Semestre(bSem)
     '***********************************************************************************
     'résultat sera le semestre précédent ou prochain dépendant du variable bSem, True=prochain, False=précédent)
     '***********************************************************************************
     Dim MaDate, Nouv_Date, Nouv_Date2, iSem, aA
     Dim ws1 As Worksheet
     Set ws1 = Sheets("Semestriel")
     With Sheets("Semestriel")
     MsgBox Date
          With .Range("F1")     'date de la 2ème semaine du semestre actuel, premiere semaine n'est pas toujours dans le même mois/année
             If .Value = "" Then     'si vide = prenez semestre de maintenant
                  .Value = DateSerial(Year(Date), ((Month(Date) - 1) Mod 6) * 6 + 1, 1)
                  '1/01 => (Month(Date) - 1) Mod 6) * 6 + 1 donne (0 x 6) + 1 =1
                  '1/07 => ((Month(Date) - 1) Mod 6) * 6 + 1 donne (1 x 6) + 1= 7
             End If
             MaDate = .Value2 ' ?
          End With
        'prochain semestre
            If bSem Then
                   If Month(MaDate) > 6 Then
                        Nouv_Date = DateSerial(Year(MaDate) + 1, 1, 1)     '1ier janvier l'année prochaine
                   Else
                        Nouv_Date = DateSerial(Year(MaDate), 7, 1)     '1ier juillet de cette année
                   End If
            Else     'semestre précedent
                   If Month(MaDate) > 6 Then
                        Nouv_Date = DateSerial(Year(MaDate), 1, 1)     '1ier janvier de cette année
                   Else
                        Nouv_Date = DateSerial(Year(MaDate) - 1, 7, 1)     '1ier juillet de l'année précédent
                   End If
            End If   'dates 2eme semestre
              Nouv_Date2 = CDbl(WorksheetFunction.EDate(Nouv_Date, 6))  '+ 6 mois =EDATE (Start_date, Months) 6/07 apres 6/01 en avançant
              .Range("A1").Value = Year(Nouv_Date) 'année
              .Range("A2").Value = IIf(Month(Nouv_Date) < 7, "1er", "2ème") & " Sem."
            Nouv_Date = CDbl(Nouv_Date - Weekday(Nouv_Date, 2) + 1)     'le lundi précédent en cas que ce n'est pas un lundi
                                                                       'lundi le premier jour de la semaine Weekday(Nouv_Date, 2)
            iSem = (Nouv_Date2 - Nouv_Date - 1) \ 7 + 1   '(/7) + 1 revient au nombre de semaines
        'tous les lundis
              ReDim aA(1 To iSem)
              For i = 1 To iSem
                   aA(i) = Nouv_Date + (i - 1) * 7 'date + n° semaine (de 1 à 26) x 7
              Next
              With .Range("E1")
                   .Resize(2, 30).ClearContents 'marge de 3 apres S27
                   .Resize(, iSem).Value = aA
                   .Resize(, iSem).Offset(1).FormulaR1C1 = "=IF(R[-1]C<>"""",ISOWEEKNUM(R[-1]C),""-"")"     'iso-semaines
              End With
              .Range("A1").CurrentRegion.Offset(2).Clear 'efface à partir de la ligne 3
              .Range("C1").Resize(, 2).EntireColumn.NumberFormat = "ddd dd-mm"
        'tableau Cultures
              ab = Range("Tableau2").Value2
              ptr = 3
              For i = 1 To UBound(ab)
                   If ab(i, 4) <= Nouv_Date2 And Nouv_Date <= ab(i, 7) Then
                        .Cells(ptr, 1) = ab(i, 2) 'nom culture
                        .Cells(ptr, 2) = ab(i, 1) 'num parcelle
                        .Cells(ptr, 3) = ab(i, 4) 'date semis
                        .Cells(ptr, 4) = ab(i, 7) 'date récolte
                        B = False
                        For j = 1 To UBound(aA)
                             If ab(i, 4) <= aA(j) + 6 And aA(j) <= ab(i, 7) Then .Cells(ptr, j + 4).Value = ab(i, 3): B = True
                        Next
                    ''boolean = pour savoir s'il y a des cultures entre colonne E:AE de cette ligne
                        If B Then
                            R = Application.Match(ab(i, 2), Sheets("Listes").Range("G1:G100"), 0)
                            If IsNumeric(R) Then     'culture connue
                                 .Cells(ptr, 5).Resize(, UBound(aA)).SpecialCells(xlConstants).Interior.Color = Sheets("listes").Cells(R, "G").Interior.Color
                                 .Cells(ptr, 5).Resize(, UBound(aA)).SpecialCells(xlConstants).Font.Color = Sheets("listes").Cells(R, "G").Font.Color     'la police
                            Else
                                 .Cells(ptr, 5).Resize(, UBound(aA)).SpecialCells(xlConstants).Font.ColorIndex = 2     'police blanc
                            End If
                        End If
                        ptr = ptr + 1
                   End If
              Next

J'ai réussit à comprendre dans les grandes lignes, mais voici mes questions:

C'est quoi bsem et pkoi déclarer ici plutôt qu'en Dim, et sans%, $.. aprés

If bSem Then

Date en msgbox c'est la date du jour, elle est paramétrée ou ? et si on avance de 2 semestres, elle sert plus à rien.

 .Value = DateSerial(Year(Date), ((Month(Date) - 1) Mod 6) * 6 + 1, 1)
                  '1/01 => (Month(Date) - 1) Mod 6) * 6 + 1 donne (0 x 6) + 1 =1
                  '1/07 => ((Month(Date) - 1) Mod 6) * 6 + 1 donne (1 x 6) + 1= 7

.value2 c'est le format chiffre

isem c'est une variable en date ?

Resize c'est comme redim ?

Le controle numérique pour du texte, pkoi ?

R = Application.Match(ab(i, 2), Sheets("Listes").Range("G1:G100"), 0)
If IsNumeric(R) Then     'culture connue

Et pourquoi j + 4 pour mettre l'abrégé (ou réf) dans le planning.

For j = 1 To UBound(aA)
         If ab(i, 4) <= aA(j) + 6 And aA(j) <= ab(i, 7) Then .Cells(ptr, j + 4).Value = ab(i, 3): B = True
Next

Merci

bonjour,

Ces flèches de la cellule A1 de la feuille "semestre" sont assignés aux macros semestrPrec() et semestrSuiv() qui sont les mêmes sauf leur paramètre, il sautent vers la macro "Nouv_Semestre" avec le paramètre "True" ou "False", ce paramètre "bSem" dans l'entête. Plus d'explication : voir https://www.excel-pratique.com/fr/vba/procedures_fonctions. Déclarer les variables est une bonne habitude quand on débute en VBA, mais c'est un choix personnel, après autant d'années, moi, je ne le fais plus. Si vous voulez le faire, il faut modifier le début de la macro Nouv_Semestre comme ça Sub Nouv_Semestre(bSem as boolean), je ne trouve pas ce "pkol".

Dim MaDate, Nouv_Date, Nouv_Date2, iSem, aA : ils sont du type variant, parce que je n'avais rien ajouter = la même choice que faire rien, paresseux, .... %, $, ... sont des symboles anciens, que je n'utilise pas. La ligne des déclarations serait possible comme ca (ou en plusieurs lignes)

   Dim MaDate As Date, Nouv_Date As Date, Nouv_Date2 As Date, iSem As Integer, aA As Variant, i As Integer, aB As Variant, ptr As Integer, b As Boolean, j As Integer, r As Variant, DrLig As Long

Now et Date sont les mêmes valeurs en VBA que les formules MAINTENANT() et AUJOURDHUI() qu'on utilise dans ces feuilles

Sub Aujourdhui()
     MsgBox "Aujourd'hui : " & Format(Date, "dddd dd-mmm-yyyy")
     MsgBox "Maintenant : " & Format(Now, "dddd dd-mm-yyyy hh:mm:ss")
End Sub

la construction "((Month(Date) - 1) Mod 6) * 6 + 1", on est le 11 mai = 5ième mois alors (5-1) mod 6 = 4 mod 6 = 0 et puis 0*6+1 = 1 donc janvier. Si on était en septembre = 9ième mois ----> ((9-1) mod 6) *6 + 1 = (8 mod 6) * 6 + 1 = 1 * 6 + 1 = 7 = juillet

".value2", c'est pour lire des données sans fautes, sans arrondir pour des valeurs "currency" ou dates. Supposons qu'une cellule contient une valeur de "1234,56789" mais le format de la cellule est "0,00 €", on risque d'ajouter la valeur arrondi "1.234,57" au tableau, dépendant de la situation cela n'est pas préférable. La même chose avec les dates ou dates+heures, Excel est d'origine américain et utilise le format "MM/DD/YYYY". En utilisant ".value2", on lit toujours correct. Donc pour tous les autres situations, il n'y a pas de différence entre ".value" et ".value2", mais pour des valeurs "currency" et "dates", je préfère utiliser "Value2".

iSem est un integer = le nombre de semaines dans votre tremestre avec une correction pour le début du tremestre, si le premier n'est pas un lundi, on recule jusqu'au lundi précédent, pour avoir des semaines complèts. Par exemple 1/7/2023 est samedi, le lundi précédent = 26/6/23

Resize est pour définir une plage dans une feuille, voir https://learn.microsoft.com/fr-fr/office/vba/api/excel.range.resize, redim est pour redimensioner un array en mémoire, donc c'est semblable mais pas égal !!!

pkoi ???

R = Application.Match(ab(i, 2), Sheets("Listes").Range("G1:G100"), 0)

c'est important que R est du type variant et certainement pas integer ou long, alors VBA a le choix d'assigner une valeur "erreur" à R, si le match ne donne pas un résultat.

aA = un tableau avec tous les dates "lundi" du semestre, par exemple 2ieme semestre 2023 = 26/6/23, 3/7/2023,10/7/23, ...., 25/12/2023. Le premier élément de "aA" = première semaine = correspond à la 5ième colonne "E" de "Semestre" (les colonnes A:D sont culture, parcelle, date semis, date réculte), donc c'est pourquoi on ajoute 4.

Bonjour,

Merci pour les explications.

pkoi c'est du langage sms pour dire pourquoi.

donc le controle numérique pour du texte, pourquoi ?

R = Application.Match(ab(i, 2), Sheets("Listes").Range("G1:G100"), 0)
If IsNumeric(R) Then     'culture connue

Sinon, date est toujours 1 quand on passe au 2ème semestre avec

.Value = DateSerial(Year(Date), ((Month(Date) - 1) Mod 6) * 6 + 1, 1)

parce qu'on est toujours en mai.

Cdt

re,

aB = un tableau en mémoire et donc une copie virtuelle du tableau "Tableau2" de la feuille "Culture". La 2ième colonne de ce tableau sont les cultures.

Colonne G de la feuile "Liste" sont les mêmes noms de culture avec leur couleur correspondant.

Si on trouve un match exact, R représente la ligne du nom de culture dans "Liste", par exemple "pomme de terre" sera 35, (parce que G35=pomme de terre). Si le nom est inconnu dans la colonne G, R est type variant/error avec valeur "Fout 2042", en français "Erreur 2042", ce valeur n'est pas numérique, donc les couleurs Colorindex seront 1 et 2

image

Si F1 de la feuille "Semestriel" est vide, on prendra pour aujourd'hui le 01/01/2023, donc semestre 1 de 2023 pour date de début "MaDate",ce F1 n'est pas vide, MaDate sera la valeur de F1. Pourquoi la cellule F1 et pas E1, E1 est le lundi précédent, si le premier n'était pas un lundi, donc E1 n'est pas nécessairement dans le même semestre/année que G1. Donc F1 est le "vrai premier lundi" de ce semestre et ne pas nécessairement le premier du mois.

  With Sheets("Semestriel")
          With .Range("F1")     'date de la 2ème semaine du semestre actuel, premiere semaine n'est pas toujours dans le même mois/année
               If .Value = "" Then     'si vide = prenez semestre de maintenant
                    .Value = DateSerial(Year(Date), ((Month(Date) - 1) Mod 6) * 6 + 1, 1)
     '

Quand on appui la flèche gauche ou droite, ce fameux "bSem" avec valeur "Vrai" ou "Faux", on soustrait ou ajoute 6 mois et si le semestre actuel est 1 ou 2, on a les 4 possibilités ici dessous ... pour calculer "Nouv_date" et les règles suivants pour calculer le lundi précédent.

 If bSem Then
               If Month(MaDate) > 6 Then
                    Nouv_Date = DateSerial(Year(MaDate) + 1, 1, 1)     '1ier janvier l'année prochaine
               Else
                    Nouv_Date = DateSerial(Year(MaDate), 7, 1)     '1ier juillet de cette année
               End If
          Else     'semestre précedent
               If Month(MaDate) > 6 Then
                    Nouv_Date = DateSerial(Year(MaDate), 1, 1)     '1ier janvier de cette année
               Else
                    Nouv_Date = DateSerial(Year(MaDate) - 1, 7, 1)     '1ier juillet de l'année précédent
               End If
          End If
Rechercher des sujets similaires à "procedure trop grande"