Syntaxe sur un tri dans une macro

bonsoir,

je me permets de vous soumettre le code dune macro qui plante avec ce message juste à l'initialisation des 2 tris présents dans cette macro :

"la methode range de l'objet worksheet a échoué "

comme vous pouvez vous en rendre compte, j'ai encore beaucoup de lacunes !!!

merci pour vos éclairages!

Sub ARCHIVAGE()

' cette macro effectue le transfert des écritures de POINTES vers ARCHIVES

Dim i%, n%, iDisp%, wDisp As Worksheet

Dim wmont, nbecr As Single

Dim lheure As Date, ladate As Date

Dim nr1, nrnew, nran, nrsq As String

Set L = Worksheets("LISTES") 'définit l'onglet LISTES

nr1 = L.Range("E9") 'on stocke le n° rlv disponible

'tri des POINTES avant traitement pour être sur d'avoir les notifs (H4) en tete

With wDisp.Range("A4:K" & iDisp)

.Sort key1:=.Range("H4"), order1:=xlAscending, order3:=xlAscending, Header:=xlNo

End With

With Worksheets("POINTES")

n = .Range("A" & .Rows.Count).End(xlUp).Row 'n° de la dernière ligne renseignée de POINTES

Set wDisp = Worksheets("ARCHIVES")

iDisp = wDisp.Range("A" & wDisp.Rows.Count).End(xlUp).Row 'idisp = n° de la 1ere ligne dispo de ARCHIVES

nbecr = 0

For i = n To 4 Step -1 'recherche sur POINTES en remontant vers le haut

If .Range("H" & i) = nr1 Then 'sélection des lignes par rapport au n° relevé

iDisp = iDisp + 1

With .Range("A" & i).Resize(, 11)

.Copy wDisp.Range("A" & iDisp) ' copie de POINTES vers ARCHIVES

.Delete xlShiftUp ' delete de POINTES

nbecr = nbecr + 1

End With

End If

Next i

End With

'MsgBox "mef nouveau rlv"

If Val(Mid(nr1, 5, 2)) = 12 Then

nrnew = CStr(Val(Mid(nr1, 1, 2)) + 1) & "-r01" 'nouv num rlv avec changement d'année

Else

nrnew = Mid(nr1, 1, 4) & Format((Val(Mid(nr1, 5, 2)) + 1), "00") 'nouv num rlv avec changement séquence

End If

Set L = Worksheets("LISTES") 'définit l'onglet LISTES

L.Range("E9").Value = nrnew 'num du prochain rlv dispo à archiver

lheure = Time

ladate = Date

L.Range("F10").Value = "dernier archivage effectué le :"

L.Range("F11").Value = Replace((ladate & " à " & lheure), "/", "-")

L.Range("G10").Value = nbecr

'tri sur ARCHIVES : notif (H4) date (A4) mont (G4) sens (J4)

With wDisp.Range("A4:K" & iDisp)

.Sort key1:=.Range("J4"), order1:=xlAscending, Header:=xlNo

.Sort key1:=.Range("H4"), order1:=xlAscending, key2:=.Range("A4"), order2:=xlAscending, _

key3:=.Range("G4"), order3:=xlAscending, Header:=xlNo

End With

wDisp.Activate

End Sub

Bonjour

Sans ton fichier, il sera difficile de comprendre pourquoi ta macro ne marche pas....

Bye !

Bonjour,

Si tu utilises la balise Code pour le code dans un post, ce serait bien !

Et si de plus le code était systématiquement bien indenté et sans sauter de ligne, ce serait encore mieux !

Une première remarque (en attendant peut-être de pouvoir lire sans se fatiguer inutilement) :

.Sort key1:=.Range("H4"), order1:=xlAscending, order3:=xlAscending, Header:=xlNo

Un peu de logique !

Si tu mets un paramètre order3, c'est que tu mets aussi un paramètre key3, parce que l'ordre sera sans effet si la clé de tri n'est pas précisée, et si une 3e clé est indiquée, c'est qu'il y en a une 2e ! donc key2 et order2 !!

Peut-être est-il utile de te préciser que les clés 1 2 3 correspondent aux colonnes sur lesquelles tu tries dans l'ordre de priorité...

Et que la méthode n'admet que 3 clés, mais n'empêche pas de trier sur un plus grand nombre de clés. Par exemple tu veux trier sur 5 clés, tu fais d'abord un tri sur tes clés 4 et 5 (qui seront key1 et key2, puis un tri sur les clés 1, 2 et 3 et ta base sera triée sur les 5 clés dans l'ordre retenu.

Cordialement.

bonjour

merci à MFerrand pour ta réponse

  • pour le fichier : voir ci joint
  • pour l'indentation c'est l'affichage dans le post qui l'a annulé
  • pour le 1er tri j'avais effectivement une erreur que je n'avais pas vue (order3) c'est corrigé mais ça ne change rien à l'anomalie
  • pour le reste je vais y veiller!

pour le fichier j'espère que tu ne vas pas t'arracher les cheveux !

c'est manifestement un code un peu brouillon parfois pas toujours cohérent,

merci

6test-07.xlsm (94.71 Ko)

Pour les cheveux, je n'en ai plus beaucoup en réserve, alors j'évite !

Ceci dit s'il y a des remarques à faire, ton code demeure assez présentable...

Je dois m'interrompre (en étant arrivé à peu près à la moitié), je peux noter que toutes tes variables ne sont pas typées (pour celles qui devraient l'être, ex. : nr1) [les variables non typées individuellement ne sont pas typées, on ne type pas en groupe...]

Lors de ta première utilisation de iDisp, cette variable n'a pas été initialisée (donc = 0) et il est assez probable que l'appel de la plage A4:K0 provoque l'erreur que tu signales...

Ton code doit par ailleurs pouvoir être amélioré... (mais faut d'abord que je le lise jusqu'au bout).

merci Mferrand pour tes remarques et tes conseils

j'attends tes remarques

dernière minute !

j'ai trouvé! ..Enfin... j'ai corrigé !...grâce à MFerrand qui m'a mis le doigt sur l'anomalie!

c'était bien "idisp" qui posait problème : il était utilisé avant même d'être valorisé!

Je remets un fichier avec le correctif : attention les cheveux !!

4test-07.xlsm (96.87 Ko)

OK ! Je vais essayer d'ordonner à peu près les remarques :

Tu as un certain nombre de variables déclarée et inutilisées. On pourra les supprimer. L n'est pas déclarée (à faire).

Ton acrobatie avec wDisp... [Je ne vais pas la critiquer, je suis coutumier de la réutilisation de variable dans une même procédure ], mais je pense que tu n'en as pas besoin car on peut traiter chaque feuille tour à tour sans recoupement en exploitant mieux la logique de ton code...

Tu fais un premier tri de la feuille POINTES, sur la colonne "notif." et c'est sur la valeur de cette colonne que tu définis les lignes à archiver. En triant, tu vas donc nécessairement regrouper les lignes à archiver. Il suffira donc de déterminer le début et la fin de cette plage à archiver et de l'affecter à une variable Range (ce qui sera plus productif que les variables feuilles...). La plage peut être collée globalement (NB: collage justifié pour reproduire les formats avec les valeurs, sinon l'affectation des valeurs resterait préférable) et pourra être supprimée ensuite...

Le nombre sera fourni par le nombre de ligne de la plage...

Pour la modification des éléments de LISTES, tu peux te contenter de variables String pour la date et l'heure. F10 ne varie pas...

Je suppose aussi que le tri d'ARCHIVES, non opéré car un Exit Sub précède est tout de même à faire, mais tu n'as à trier que la plage que tu viens de coller, et la colonne H peut être laissée de côté puisqu'il s'agit du critère d'archivage...

Je modifie pour te proposer ta procédure modifiée.

Et voilà la proposition :

Sub ARCHIVAGE()
    ' cette macro effectue le transfert des écritures de POINTES vers ARCHIVES
    Dim Disp As Range, L As Worksheet
    Dim nr1$, nrnew$, ladate$, lheure$, nbecr%, i%, n%, ld%, lf%
    MsgBox "ARCHIVAGE démarré ! tapez OK et patienter jusqu'au message de fin d'archivage"
    'on mémorise les élements du dernier archivage
    Set L = Worksheets("LISTES")         'définit l'onglet LISTES
    nr1 = L.Range("E9")                  'on stocke le n° rlv disponible
    With Worksheets("POINTES")
        n = .Range("H" & .Rows.Count).End(xlUp).Row
        ' tri sur la colonne H
        .Range("A4:K" & n).Sort key1:=.Range("H4"), order1:=xlAscending, Header:=xlNo
        ' on définit le début et la fin de la plage à archiver
        For i = 4 To n
            If .Range("H" & i) = nr1 Then
                ld = i: Exit For
            End If
        Next i
        If ld = 0 Then Exit Sub
        For i = n To ld Step -1
            If .Range("H" & i) = nr1 Then
                lf = i: Exit For
            End If
        Next i
        Set Disp = .Range("A" & ld & ":K" & lf) 'plage à archiver
    End With
    nbecr = Disp.Rows.Count
    Application.ScreenUpdating = False
    With Worksheets("ARCHIVES")
        n = .Range("A" & .Rows.Count).End(xlUp).Row + 1 'ligne où coller l'archivage
        Disp.Copy .Range("A" & n) 'copie et collage
        ' Tri de la plage collée
        .Range("A" & n).Resize(nbecr, 11).Sort key1:=.Range("A" & n), order1:=xlAscending, _
          key2:=.Range("G" & n), order2:=xlAscending, key3:=.Range("J" & n), order3:=xlAscending, _
          Header:=xlNo
        .Activate
    End With
    Application.ScreenUpdating = True
    Disp.Delete xlShiftUp 'Suppression plage copiée
    ' mise à jour LISTES
    i = Val(Mid(nr1, 5, 2)): n = Val(nr1)
    n = IIf(i = 12, n + 1, n): i = i Mod 12 + 1
    nrnew = n & "-r" & Format(i, "00")                      'nouv num rlv avec changement d'année
    ladate = Format(Date, "dd-mm-yyyy") & " à "
    lheure = Format(Time, "hh:mm:ss")
    L.Range("E9").Value = nrnew              'num du prochain rlv dispo à archiver
    L.Range("F11").Value = ladate & lheure
    L.Range("G10").Value = nbecr
    MsgBox "ARCHIVAGE terminé (" & nbecr & " écritures transférées) pour RLV = " & nr1 & " - prochain = " & nrnew
    Exit Sub
End Sub

Avec les explications précédentes, tu ne devrais pas avoir de problèmes à t'y retrouver... Je n'ai pas modifié fondamentalement ta méthode, j'ai juste exploité complètement ce que tu avais commencé. Et quelques petits détails sur la fin...

Cordialement.

merci pour ta patience et ton aide MFerrand !

" ' mise à jour LISTES

n = IIf(i = 12, n + 1, n): i = i Mod 12 + 1"

question spécifique au forum : comment fait-on pour citer une partie de ton message ?

je n'ai pas compris sur la 3ème ligne "n = ???(i = 12, ...

"erreur compilation sur "???" (IIf?)

je n'ai pas compris les 3 caractères mais je n'ai pas compris non plus le modulo

pour le reste, je vais m'y atteler pour essayer de comprendre "le code" de ta proposition (que j'ai bien comprise dans tes explications)

IIf c'est la fonction SI en VBA...

Si i = 12 (condition vraie), elle renvoie n + 1, sinon n

Mod est un opérateur en VBA, il renvoie le modulo (mais il convient de ne l'utiliser qu'avec des entiers, de même que l'opérateur \ qui renvoie un quotient entier...)

i Mod 12 pour i = 1 à 11 va renvoyer 1 à 11, et 0 pour i = 12

donc i Mod 12 + 1 renverra 2 à 12 pour i = 1 à 11 et 1 pour i = 12

[NB- Pas besoin de parenthèses, Mod est prioritaire par rapport à +]

Pour citer une partie de message, pour ma part je copie et colle, sélectionne et clic sur la balise Quote. Je ne sais s'il y a une meilleure méthode...

Pour le code, pareil, tu sélectionnes ton code dans le post et tu cliques sur la balise Code. Il sera plus lisible, et l'indentation sera conservée pour l'essentiel (ton code étant à peu près correctement indenté, dommage de la perdre...)

Ah ! également : si le trait de soulignement précédé d'une espace en bout de ligne a pour effet de ne pas interrompre une ligne de code

       .Range("A" & n).Resize(nbecr, 11).Sort key1:=.Range("A" & n), order1:=xlAscending, _
          key2:=.Range("G" & n), order2:=xlAscending, key3:=.Range("J" & n), order3:=xlAscending, _
          Header:=xlNo

ci-dessus une seule ligne de code...

Le caractère deux-points (:) est un séparateur qui permet d'écrire plusieurs lignes de code (constituant des commandes distinctes) sur la même ligne

   i = Val(Mid(nr1, 5, 2)): n = Val(nr1)
    n = IIf(i = 12, n + 1, n): i = i Mod 12 + 1

là, il y a 4 lignes de code sur ces deux lignes.

Cordialement.

merci encore pour ta réponse

j'ai pigé les 2 lignes de code pour modulo!

je vais regarder le reste!

je te tiens au courant

a+

salut à tous,

un grand merci à Mferrand, pour ses explications et ses conseils

tout fonctionne trés bien !

j'ai bien compris tes propositions je vais essayer d'en faire usage pour tenter de simplifier ce que j'avais fait, par ailleurs, en amont

Bon courage... A+

Rechercher des sujets similaires à "syntaxe tri macro"