Tri de tableaux de longueurs variables sur différentes feuilles
#1
Débutant XLPages

Inscription: 20/07/2009

Messages: 9

Système d'exploitation:
PC
Version Excel utilisée:
2007
Posté le : 05-08-2009 13h50
 Bonjour à tous,

voilà donc mon problème qui ne semble pas être présent dans l'un des forums :
à partir d'une feuille (Finances), je veux lancer une macro qui, entre autres, trie par dates des tableaux qui sont présents sur les autres feuilles du classeur. Ces tableaux n'ont pas une longuer fixe et seront amener à évoluer. Après de nombreux essais avec "Sort" qui me renvoyaient des erreur d'application ou d'objet(voir premier code), j'ai trouvé un code qui semblait marcher (voir deuxième code). Le problème est qu'il me modifie aussi ma feuille de départ et que je ne voudrais pas passer par une fontion "Activate".

Premier code (juste la partie concernée):
For i = 3 To ActiveWorkbook.Sheets.Count
    For l = 4 To 69
        If ActiveWorkbook.Sheets(i).Range("B9").Value <> "" And ActiveWorkbook.Sheets(i).Range("B9").Value = ThisWorkbook.Sheets("Finances").Range("E" & l).Value Then
            'Recherche de la dernière cellule remplie pour les Factures
            DerniereFacture = ActiveWorkbook.Sheets(i).Columns(28).Find("*", , , , , xlPrevious).Row
            'Trier le tableau des factures par dates croissantes
            ActiveWorkbook.Sheets(i).Range(Cells(154, 27), Cells(DerniereFacture, 35)).Select
            Selection.Sort Key1:=Range("AA154"), Order1:=xlAscending

Deuxième code (juste la partie concernée) :
For i = 3 To ActiveWorkbook.Sheets.Count
    For l = 4 To 69
        If ActiveWorkbook.Sheets(i).Range("B9").Value <> "" And ActiveWorkbook.Sheets(i).Range("B9").Value = ThisWorkbook.Sheets("Finances").Range("E" & l).Value Then
            'Recherche de la dernière cellule remplie pour les Factures
            DerniereFacture = ActiveWorkbook.Sheets(i).Columns(28).Find("*", , , , , xlPrevious).Row
            'Trier le tableau des factures par dates croissantes
            ActiveWorkbook.Sheets(i).Activate
            Range(Cells(154, 27), Cells(DerniereFacture, 35)).Sort   Key1:=Range("AB154"), Order1:=xlAscending
            ActiveWorkbook.Sheets("Finances").Activate
J'espère que mon explication est compréhensible et que j'ai mis assez d'informations pour que vous puissiez me répondre.
Cordialement,
Gaël
Hors Ligne
Rapport   Haut 

Re: Tri de tableaux de longueurs variables sur différentes feuilles
#2
Webmestre

Inscription: 18/05/2006
De Saône-et-Loire (71)

Messages: 1539

Système d'exploitation:
PC
Version Excel utilisée:
97, 2000, 2002, 2003, 2007, 2010, 2013, 2016 et 365
Posté le : 06-08-2009 00h57
Bonsoir GGLyon et bienvenue

A priori, je te proposerais un code VBA comme suit :
Dim DerniereFacture As Long
Dim i As Integer
Dim L As Byte

'...
'...

For i = 3 To ActiveWorkbook.Sheets.Count
    For L = 4 To 69
        With ActiveWorkbook.Sheets(i)
            If .Range("B9").Value <> "" And .Range("B9").Value = ThisWorkbook.Sheets("Finances").Range("E" & L).Value Then
                'Recherche de la dernière cellule remplie pour les Factures
                DerniereFacture = .Cells(.Rows.Count, 28).End(xlUp).Row
                'Trier le tableau des factures par dates croissantes
                .Range(.Cells(154, 27), .Cells(DerniereFacture, 35)).Sort _
                    Key1:=.Range("AA154"), Order1:=xlAscending
                '... SUITE DE TON CODE
            End If
            '... SUITE DE TON CODE
        End With
Mais bien évidemment, impossible de tester la proposition sans ton classeur (ou un extrait épuré à l'essentiel du problème)...

Par ailleurs, j'ai un peu de mal à comprendre les points suivants :
- Pourquoi ActiveWorkbook puis ThisWorkbook ? Y a t'il 2 classeurs en jeu ?
- Pourquoi i commence à 3 ? A 2, j'aurai compris que tu exclus une feuille, celle se nommant "Finances", mais 2....
- J'ai aussi du mal à imaginer le pourquoi de cette boucle For L = 4 to 69. Le but est-il de comparer la valeur B9 de chaque feuille avec 65 cellules en colonne E de la feuille "Finances" ?

La seule chose dont je suis quasi sûr, c'est que tes plantages proviennent des Activates et autres Select que tu utilises à tort dans tes codes. A part de très très rares exceptions, il est toujours inutiles d'activer ou sélectionner un objet pour agir dessus en VBA. C'est même la première source de plantages que rencontrent la plupart des débutants...

Je me permets également d'attirer ton attention sur l'importance et l'intérêt de la Déclaration des Variables en VBA.

Cordialement,

Didier_mDF
Image redimensionnée
Le Webmaster

La réponse vous satisfait ? Merci de revenir solder le sujet en [résolu], voir ce lien
Hors Ligne
Rapport   Haut 

Re: Tri de tableaux de longueurs variables sur différentes feuilles
#3
Débutant XLPages

Inscription: 20/07/2009

Messages: 9

Système d'exploitation:
PC
Version Excel utilisée:
2007
Posté le : 06-08-2009 09h55
Bonjour le forum, Bonjour mDF,

merci beaucoup pour avoir jeté un oeil sur mon problème.
Pour le moment, j'ai une erreur de compilation qui apparaît sur la ligne Key1:=.Range... dans ce que tu m'as proposé. Comme mes notions en VBA sont très limitées, je ne sais pas si ça provient de ce que j'ai pu écrire avant ou pas !
C'est aussi pour cette raison que tu trouves des ActiveWorkbook et ThisWorkbook partout et que qu'il y a des boucles qui parcourent beaucoup de cellules peut-être inutilement ! Je fais vraiment du bidouillage et je pense que tu passerais pas loin de la syncope en voyant le reste des lignes !
Pour répondre un peu plus à tes interrogations :
- i commence à 3 car j'ai une 2 feuilles (dont Finances) qui récupère des données sur le reste du classeur,
- en ce qui concerne les Activate, c'était juste un essai, y en a pas ailleurs :)
- la prochaine fois, j'incluerai ma déclaration de variables dans le code que je poste.
J'aurai bien mis mon classeur mais il s'agit de données confidentielles et j'ai peur de passer beaucoup de temps à l'épurer. Je vais voir quand même aujourd'hui si c'est possible car tes conseils et ceux du forum me seront précieux.

MAJ : voilà le fichier, qui était trop gros, donc il faut copier les feuilles du fichier 2 dans le 1 !

Cordialement,
Gaël 






Pièce jointe:
zip GGlyon1.zip   [ Taille: 67.00 Ko - Téléchargements: 419 ]
zip GGlyon2.zip   [ Taille: 18.39 Ko - Téléchargements: 433 ]
Edité par GGlyon le 06/08/2009 11:06:27
Hors Ligne
Rapport   Haut 

Re: Tri de tableaux de longueurs variables sur différentes feuilles
#4
Webmestre

Inscription: 18/05/2006
De Saône-et-Loire (71)

Messages: 1539

Système d'exploitation:
PC
Version Excel utilisée:
97, 2000, 2002, 2003, 2007, 2010, 2013, 2016 et 365
Posté le : 06-08-2009 22h59
Bonsoir GGlyon, le Forum,

Tu trouveras ci-joint une proposition pour ta demande, en espérant que j'ai bien interprété tes indications...

N'ayant pas compris pourquoi tu avais scindé le traitement en 3 phases (3 boutons) alors que visiblement elles devaient être lancées successivement, et pour simplifier le code, j'ai rassemblé l'ensemble du traitement (Finance, Commandes et Factures) en une seule procédure "Traitement()" que tu trouveras toujours dans le module de code de la feuille "Finances". L'ensemble se déclenche donc avec l'unique bouton "Actualiser".

Je te laisse prendre connaissance du code VBA utilisé.
Pas franchement convaincu par le choix de certaines de tes variables (je pense notamment à X, Z, n, k par exemple), je les ai toutefois laissées telles quelles pour que tu puisses conserver tes repères dans tout ceci.

Sub Traitement()
'----------------------------------------------------------
'   myDearFriend! - www.mdf-xlpages.com
'   06/08/2009
'----------------------------------------------------------
Dim Sh As Worksheet
Dim DateFinProjet As Date, DateVirement As Date, DateCalendrier As Date, DateCommande As Date, DateFacture As Date
Dim DerniereCommande As Long, DerniereFacture As Long
Dim Virement As Single, CommandeTTC As Single, FactureTTC As Single
Dim i As Byte, k As Byte, n As Byte, X As Byte, Z As Byte

    'On fige l'affichage pour accélérer le traitement
    Application.ScreenUpdating = False
    Range("A4:BI69").ClearContents

    Range("A2:J3").Interior.Color = RGB(40, 215, 90)
    'Mise en forme des dates du calendrier pour que celles qui sont dépassées apparaissent en gris
    For Z = 12 To 83
        With Cells(3, Z)
            DateCalendrier = .Value
            Select Case DateSerial(Year(Date), Month(Date), 1)
            Case Is > DateCalendrier
                .Font.ColorIndex = 16
            Case Is = DateCalendrier
                .Font.ColorIndex = 30
            Case Else
                .Font.ColorIndex = 1
            End Select
        End With
    Next Z

    'Couleurs des tableaux
    For k = 4 To 69 Step 3
        'FINANCE--------------------------------------------------------
        Rows(k).Interior.Color = RGB(200, 255, 110)
        'COMMANDES------------------------------------------------------
        Rows(k + 1).Interior.Color = RGB(255, 255, 255)
        Range(Cells(k + 1, 1), Cells(k + 1, 4)).Merge
        Cells(k + 1, 1).HorizontalAlignment = xlRight
        Cells(k + 1, 1).Value = "Commandes"
        Range(Cells(k + 1, 12), Cells(k + 1, 83)).Font.ColorIndex = 3
        'FACTURES-------------------------------------------------------
        Rows(k + 2).Interior.ColorIndex = 34 'RGB(40, 215, 200)
        Range(Cells(k + 2, 1), Cells(k + 2, 4)).Merge
        Cells(k + 2, 1).HorizontalAlignment = xlRight
        Cells(k + 2, 1).Value = "Factures"
        Range(Cells(k + 2, 12), Cells(k + 2, 83)).Font.ColorIndex = 10
    Next k
   
    X = 4
    'recherche sur chacune des feuilles du classeur
    For Each Sh In Worksheets
        If Sh.Name <> "Finances" And Sh.Name <> "Général" Then
            'Savoir si le projet est encore actif
            DateFinProjet = Sh.Range("B13").Value
            If DateFinProjet > Date Then
                'FINANCES-----------------------------------------------------------
                'Récupérer les infos du projet
                Cells(X, 2).Value = Sh.Range("B7").Value    'Organisme financeur
                Cells(X, 3).Value = Sh.Range("L5").Value    'Acronyme Projet
                Cells(X, 4).Value = Sh.Range("K2").Value    'Année du projet
                Cells(X, 5).Value = Sh.Range("B9").Value    'Référence du projet
                Cells(X, 6).Value = Sh.Range("I2").Value    'Gestion
                Cells(X, 7).Value = Sh.Range("B12").Value   'Date de début de projet
                Cells(X, 8).Value = Sh.Range("B13").Value   'Date de fin de projet
                Cells(X, 9).Value = Sh.Range("B24").Value    'Montant total
                For i = 10 To 30 Step 10
                    If Sh.Cells(40 + i, 4).Value = "UMR" Then
                        Cells(X, 10).Value = Sh.Cells(48 + i, 7).Value
                        Exit For
                    End If
                Next i
                'Partie concernant le versement des subventions
                'Ajouter les infos concernant les référence projets répertoriées
                For n = 29 To 34
                    'Trouver les dates de virement et les sommes correspondantes pour un projet
                    With Sh.Cells(n, 11)
                        If .Value <> "" Then
                            DateVirement = .Value
                            DateVirement = DateSerial(Year(DateVirement), Month(DateVirement), 1)
                            Virement = .Offset(0, 1).Value
                        End If
                    End With
                    'Recherche le mois de la date du virement dans la feuille finance et inscrire le montant
                    For Z = 12 To 83
                        DateCalendrier = Cells(3, Z).Value
                        If DateCalendrier = DateVirement Then
                            Cells(X, Z).Value = Virement
                            Exit For
                        End If
                    Next Z
                Next n
                'COMMANDES----------------------------------------------------------
                'Recherche de la dernière cellule remplie pour les commandes
                DerniereCommande = Sh.Cells(Sh.Rows.Count, 18).End(xlUp).Row
                If DerniereCommande > 153 Then
                    'Parcourir toutes les commandes
                    For n = 154 To DerniereCommande
                        With Sh.Cells(n, 18)
                            DateCommande = .Value
                            DateCommande = DateSerial(Year(DateCommande), Month(DateCommande), 1)
                            CommandeTTC = .Offset(0, 1).Value
                        End With
                        'Recherche le mois dans la feuille finances et inscrire le montant de commande
                        'Si < au premier mois du tableau (< 01/2009)
                        If DateCommande < Cells(3, 12).Value Then
                            Cells(X + 1, 11).Value = Cells(X + 1, 11).Value + CommandeTTC
                        Else
                        'Sinon
                            For Z = 12 To 83
                                DateCalendrier = Cells(3, Z).Value
                                If DateCalendrier = DateCommande Then
                                    Cells(X + 1, Z).Value = Cells(X + 1, Z).Value + CommandeTTC
                                    Exit For
                                End If
                            Next Z
                        End If
                    Next n
                End If
                'FACTURES-----------------------------------------------------------
                'Recherche de la dernière cellule remplie pour les factures
                DerniereFacture = Sh.Cells(Sh.Rows.Count, 28).End(xlUp).Row
                If DerniereFacture > 153 Then
                    'Parcourir toutes les factures
                    For n = 154 To DerniereFacture
                        With Sh.Cells(n, 28)
                            DateFacture = .Value
                            DateFacture = DateSerial(Year(DateFacture), Month(DateFacture), 1)
                            FactureTTC = .Offset(0, 7).Value
                        End With
                        'Recherche le mois dans la feuille finances et inscrire le montant de facture
                        'Si < au premier mois du tableau (< 01/2009)
                        If DateFacture < Cells(3, 12).Value Then
                            Cells(X + 2, 11).Value = Cells(X + 2, 11).Value + FactureTTC
                        Else
                        'Sinon
                            For Z = 12 To 83
                                DateCalendrier = Cells(3, Z).Value
                                If DateCalendrier = DateFacture Then
                                    Cells(X + 2, Z).Value = Cells(X + 2, Z).Value + FactureTTC
                                    Exit For
                                End If
                            Next Z
                        End If
                    Next n
                End If
               
                X = X + 3
            End If
        End If
    Next Sh
    Application.ScreenUpdating = True
End Sub
Même si j'ai essayé de le structurer au mieux, je ne vais pas pouvoir te commenter tout ce code, mais je t'invite à revenir si tu souhaites avoir des explications sur tel ou tel point. N'hésite pas.


Par rapport à ton travail, voici quelques infos qui pourront t'être utiles je pense :

Lorsque tu écris par exemple :
Dim DateFinProjet, DateActuelle, DateVirement As Date
Sache que seule DateVirement est déclarée comme type Date. Les autres (DateFinProjet, DateActuelle) seront de type Variant !
Il te faut impérativement écrire :
Dim DateFinProjet As Date, DateActuelle As Date, DateVirement As Date

Par ailleurs, concernant l'utilisation de la propriété ThisWorkbook ou ActiveWorkbook : comme ton code VBA n'agit que sur le classeur dans lequel se trouve le code lui-même, tu n'as pas besoin d'utiliser cette propriété, elle est implicite. Tu verras que je ne l'ai pas utilisé dans le code ci-dessus.
De plus, comme tu as fait le choix de créer ta procédure de traitement dans le module de code Private de la feuille "Finances", tu n'as pas non plus besoin de faire précéder tes Ranges et autres Cells de l'expression Worksheets("Finances"), cette expression est également implicite puisque tu te trouves dans le module de code de cette feuille.

Cordialement,
Pièce jointe:
zip PourGGlyon.zip   [ Taille: 59.49 Ko - Téléchargements: 489 ]

Didier_mDF
Image redimensionnée
Le Webmaster

La réponse vous satisfait ? Merci de revenir solder le sujet en [résolu], voir ce lien
Hors Ligne
Rapport   Haut 

Re: Tri de tableaux de longueurs variables sur différentes feuilles
#5
Débutant XLPages

Inscription: 20/07/2009

Messages: 9

Système d'exploitation:
PC
Version Excel utilisée:
2007
Posté le : 07-08-2009 11h07
Bonjour le forum, Bonjour mDF,

Merci beaucoup mDF pour ce nouveau code qui fonctionne très bien et qui ressemble à quelque chose contrairement à ce que j'avais écris ! C'est impressionnant comme maintenant il est compact :)
J'ai juste modifié le "n as Byte" en "n as Integer" pour éviter le message "dépassement de capacité" du au fait que certains tableaux "commandes" et/ou "factures" dépassent la ligne 254.

En ce qui concerne ma compréhension du code, je bloque sur Select Case et Dateserial... J'ai lu l'aide VBA là-dessus mais ça ne m'a pas éclairé ! Est-ce que tu pourrais m'expliquer ?

Pour mes variables n, Z, etc je me demande ce qui pose problème ?! Il faudrait qu'elles soient plus explicites ?

Pour voir si j'ai bien tout compris, je vais essayer de modifier la macro concernant la feuille "Général" :)

Merci encore.
Gaël

Hors Ligne
Rapport   Haut 

Re: Tri de tableaux de longueurs variables sur différentes feuilles
#6
Webmestre

Inscription: 18/05/2006
De Saône-et-Loire (71)

Messages: 1539

Système d'exploitation:
PC
Version Excel utilisée:
97, 2000, 2002, 2003, 2007, 2010, 2013, 2016 et 365
Posté le : 07-08-2009 16h01
Bonjour GGlyon, le Forum,

Citation :
GGlyon a écrit :

En ce qui concerne ma compréhension du code, je bloque sur Select Case et Dateserial... J'ai lu l'aide VBA là-dessus mais ça ne m'a pas éclairé ! Est-ce que tu pourrais m'expliquer ?


Select Case
Il s'agit là d'une instruction de bloc très pratique et indispensable à connaitre à mon avis. Elle remplace très avantageusement des cascades de IF... THEN... ELSEIF...

Prenons l'exemple d'une variable MaValeur que tu souhaiterais tester. Suivant sa valeur, tu souhaites exécuter des instructions différentes. Ce test pourra se présenter sous cette forme par exemple :
   Select Case MaValeur
   
    Case Is < 0
        'ICI, instructions si MaValeur est négative (inférieure à zéro)
        '...
    Case 0, 1000
        'ICI, instructions si MaValeur est égale à zéro OU égale à 1000
        '...
    Case 1 To 100
        'ICI, instructions si MaValeur est compris entre 1 et 100 (inclus)
        '...
    Case Else
        'ICI, instructions si MaValeur ne correspond à aucun cas plus haut...
        '...
       
    End Select
On retrouve là une façon très simple et surtout très clair d'exécuter du code selon la valeur de cette variable. Pour ma part, je l'utilise très souvent pour tester des valeurs de date.

Pour info, sache qu'on peut également l'utiliser pour tester une variable de type String. Par exemple, si on considère une variable MaChaine sensée stocker un nom d'utilisateur, on pourrait faire quelque chose comme ça :
   Select Case MaChaine
   
    Case "mDF"
        MsgBox "Salut mDF !"
       
    Case "GGlyon"
        MsgBox "Salut GGlyon !"
       
    Case "Jean-Marie", "Mth"
        MsgBox "Salut les jeunes !"
       
    Case Else
        MsgBox "Bonjour " & MaChaine & ", bienvenue sur mDF-XLpages.com"
       
    End Select
Il est par ailleurs notoire que cette instruction est plus rapide à l'exécution que des instructions conditionnelles IF... THEN en cascade.
Cette instruction est donc in-dis-pen-sa-ble ! N'hésite pas à en abuser.

DateSerial
Je ne sais pas si je peux être plus clair que l'aide Excel au sujet de cette fonction...

Sa syntaxe est :
DateSerial(valeur qui représente l'année, valeur qui représente le mois, valeur qui représente le jour)

Cette fonction retourne donc une valeur de Date en fonction des arguments donnés.

Exemple :
DateSerial(2009, 8, 15) te retournera donc la date "15/08/2009"

Autre exemple (utilisé dans le code proposé dans ton classeur) :
DateSerial(Year(Date), Month(Date), 1)

Comme nous sommes le 07/08/2009, la fonction Date retourne donc "07/08/2009"
- Year(Date) donnera donc "2009"
- Month(Date) donnera donc "08"
- DateSerial(Year(Date), Month(Date), 1) donnera donc "01/08/2009"


Citation :
GGlyon a écrit :

Pour mes variables n, Z, etc je me demande ce qui pose problème ?! Il faudrait qu'elles soient plus explicites ?

Rien de grave là GGlyon... c'était juste du chipotage façon mDF !
C'était juste pour dire que nous avons tous nos habitudes et que j'avais délibérément mis les miennes de côté pour que tu puisses conserver tes proprres repères. Par exemple, je t'avoue que pour moi, l'expression Cells(X,Y) ce n'est pas très conventionnel... car généralement, le X on l'utilise plutot pour les abscisses (colonnes) et le Y pour les ordonnées (lignes) et non le contraire.

Un conseil toutefois (et en rapport avec ta remarque d'ailleurs) : si tu crées une variable qui devra stocker des numéros de ligne, il conviendrait systématiquement de la déclarer de type Long. Et si tu en crées une sensée stocker des numéros de colonnes, elle devrait être au minimum de type Integer pour éviter tout plantage (256 colonnes sur une feuille Excel).

Par ailleurs, en terme d'optimisation, tu aurais pu aussi déclarer de type Currency, les variables correspondant à des montants (d'euros) au lieu de Single. Mais bon, tout ça reste du chipotage, surtout si tu n'es pas appelé à réaliser des calculs complexes avec ces valeurs.

Bien cordialement,

Didier_mDF
Image redimensionnée
Le Webmaster

La réponse vous satisfait ? Merci de revenir solder le sujet en [résolu], voir ce lien
Hors Ligne
Rapport   Haut 

Re: Tri de tableaux de longueurs variables sur différentes feuilles
#7
Débutant XLPages

Inscription: 20/07/2009

Messages: 9

Système d'exploitation:
PC
Version Excel utilisée:
2007
Posté le : 07-08-2009 16h40
 Re,

merci pour ces explications supplémentaires, tout est clair maintenant :)

Cordialement,
Gaël
Hors Ligne
Rapport   Haut 


Vous pouvez voir les sujets.
Vous ne pouvez pas débuter de nouveaux sujets.
Vous ne pouvez pas répondre aux contributions.
Vous ne pouvez pas éditer vos contributions.
Vous ne pouvez pas effacez vos contributions.
Vous ne pouvez pas ajouter de nouveaux sondages.
Vous ne pouvez pas voter en sondage.
Vous ne pouvez pas attacher des fichiers à vos contributions.
Vous ne pouvez pas poster sans approbation.

[Recherche avancée]


Qui consulte actuellement ce sujet ?   1 Utilisateur(s) anonymes