Un code qui ne fonctionne pas sans indiquer d'erreurs
Bonjour,
Apprenti autodidacte sur VBA, j'en suis pas moins dépassé par les nombreuses spécificité de ce langage, qui me semble pas loin du C++ que j'ai déjà un peu pratiqué précédemment.
Je cherche une âme charitable pour me donner un coup de main, je souhaite réaliser une liste de cellule égale à une valeur qui sera saisie par l'utilisateur en cellule K5 dans le document joint (la macro est focalisé sur ce qui se passe en feuille 2). Si la condition est vérifiée je souhaite que le numéro de référence en H:H associé la ligne qui sera vérifiée, soit écrit en colonne S:S à la suite.
J'ai mis en place un code en fonction des recherches et autres souvenirs de C++.
L'exécution du code ne m'indique aucune erreurs, mais malheureusement rien ne se passe.
Sub Copierdansordre()
'Essai de macro pour Trier/copier les numéro de liste qui sont définis par critère
Dim i As Long 'Variable de vérification colonne schedule
Dim tampon As Variant
Dim s As Variant 'Variable définissant où copier le résultat
Worksheets("Feuil2").Activate
tampon = 10
s = 1
For i = tampon To tampon + 48
If Range("M" & i).Value = Cells(5, 11).Value Then
Range("H" & i).Select
Copie.Value.Selection
Range("S" & s).Paste
s = s + 1
End If
Next i
End SubJe ne sais pas si quelqu'un peut me donner un coup de main,
Merci d'avance pour votre aide.
Salut Sarfate,
bienvenue en VBA!
Malheureux, que mon frère n'entende jamais que VBA ressemble à C++ : il va te bouffer le nez!
Cela dit, même sans erreurs, ton code n'aurait quand même rien fait puisque ta recherche en [K5] (BLD) ne figure pas dans la colonne "M".
Sub Copierdansordre()
'Essai de macro pour Trier/copier les numéro de liste qui sont définis par critère
'
Dim i As Long 'Variable de vérification colonne schedule
Dim s As Integer 'Variable définissant où copier le résultat
'
s = 1
'
With Worksheets("Feuil2")
For i = 10 To .Cells(Rows.Count, 8).End(xlUp).Row
If .Range("M" & i).Value = .Range("K5").Value Then
.Range("S" & s).Value = .Range("M" & i).Value
s = s + 1
End If
Next i
End With
'
End SubBon courage!
A+
Merci pour ta réponse rapide curulis57,
Je ne veux brusquer personne avec mon manque de culture en codage
Je viens de l'inséré et [RECTIFICATION] ca fonctionne
Je profite de ton code pour poser la question, peux-tu m'expliquer juste les éléments composants la ligne:
For i = 10 To .Cells(Rows.Count, 8).End(xlUp).RowEt pourquoi mettre des points avant les différentes "commandes "?
Dsl pour le dérangement,
merci encore.
Salut,
ne commence pas à t'excuser tout le temps : tu ne déranges personne! Si quelqu'un te répond, c'est qu'il le veut bien!
- Si tu veux voir du mouvement, change ta recherche en [K5] par exemple par PL1... ;
- Cells(Rows.Count, 8).End(xlUp).Row calcule la dernière ligne (Row) contenant une valeur de la colonne 8, en partant du bas de la feuille (Rows.Count) et en remontant la colonne (End(xlUp) ;
- pourquoi des points? J'ai utilisé With... : toutes les références 'enfant' de cette feuille 'parent' doivent y référer avec un petit point, ce qui évite d'écrire, peut-être 20 fois, WorkSheets("...")....
A+
Merci pour ta pédagogie.
Je suis content d'apprendre plein de nouvelles choses.
(si tu habite en France) Bonne journée
Ah? Et si j'habite en Belgique... mauvaise journée?
curulis57 a écrit :Ah? Et si j'habite en Belgique... mauvaise journée?
Haha non, à ne pas mal interpréter. Je suis juste expat en australie pour 2 mois, du coup je faisais surtout référence au fuseau horaire français.
Je me disais juste qu'il devait être pas loin de 6h du mat de par chez vous
Sans restriction aucune, alors, Bonne journée à l'Europe.
Bonjour, et Salut Curulis !
Curulis aurait pu ajouter qu'un bloc With ne te fait pas seulement gagner en écriture, il permet aussi une exécution plus rapide. Et tes expressions étant qualifiées (par la référence à l'objet parent), le code est plus fiable et tu ne risqueras pas d'aléas lors de développements futurs.
3 autres petites remarques sur ton code initial pour te faire comprendre... Tu déclares une variable i Long, pour parcourir des lignes. Cela se justifie dès lors que tu prévois que ta base va dépasser 32767 lignes. Sinon c'est superflu, une variable Integer est préférable parce que VBA sera plus rapide avec.
De même 2 variables de type Variant dont l'usage est de récupérer des numéros de lignes : 8 fois plus de place en mémoire qu'une variable Integer pour le même usage... Une variable Variant est une variable non typée, accès plus lent que toute autre variable typée (certes, dans ce bout de code on ne pourra même pas le mesurer...
Dans le même sens, ta variable tampon n'est utilisée que pour initialiser la boucle, elle ne te fait rien gagner par rapport au fait de mettre directement 10 ! (c'est du temps perdu que l'affecter pour un seul usage).
Par contre, tu réfères à ta cellule K5 à chaque tour de boucle, là il devenait intéressant d'utiliser une variable String...
Cordialement et bonne journée.
MFerrand a écrit :Dans le même sens, ta variable tampon n'est utilisée que pour initialiser la boucle, elle ne te fait rien gagner par rapport au fait de mettre directement 10 ! (c'est du temps perdu que l'affecter pour un seul usage).
Par contre, tu réfères à ta cellule K5 à chaque tour de boucle, là il devenait intéressant d'utiliser une variable String...
Cordialement et bonne journée.
Merci pour ces nouvelles informations précieuses. Le temps d'exécution est relativement lent sur les quelques essais que j'ai déjà mis en place. Je vais pouvoir améliorer tout ça grâce à ces premières informations.
L'intérêt de créer une variable string se présente quand on boucle des opérations ? Comment faire ?
Dim Boucle as String 'nom de la variable boucle
String = Cells(K5) ?
merci pour ton intervention.
Une variable String c'était pour y affecter la valeur de K5. Tu t'y réfères à chaque ligne pour comparer : utiliser une variable pour la comparaison à la place de la cellule elle-même est bien plus rapide.
MFerrand a écrit :Une variable String c'était pour y affecter la valeur de K5. Tu t'y réfères à chaque ligne pour comparer : utiliser une variable pour la comparaison à la place de la cellule elle-même est bien plus rapide.
D'accord. Je vais utiliser ces premières informations pour avancer.
Merci encore.
Sub Copierdansordre()
'Essai de macro pour Trier/copier les numéro de liste qui sont définis par critère
'
Dim i As Long 'Variable de vérification colonne schedule
Dim s As Integer 'Variable définissant où copier le résultat
Dim boucle1 As String
Dim boucle2 As String
Dim boucle3 As String
boucle1 = UCase(Range("K5").Value)
boucle2 = UCase(Range("L5").Value)
boucle3 = UCase(Range("M5").Value)
Range("S:S").Delete
s = 10
With Worksheets("Feuil2")
For i = 10 To Cells(Rows.Count, 8).End(xlDown).Row
If .Range("J" & i).Value = boucle1 Then
If .Range("K" & i).Value = boucle2 Then
If .Range("L" & i).Value = boucle3 Then
.Range("S" & s).Value = .Range("H" & i).Value
s = s + 1 'Jusque la je copie les colonne qui réponde au 3 conditions
ElseIf boucle3 = "" Then
.Range("S" & s).Value = .Range("H" & i).Value
s = s + 1 'Jusque la je copie les colonne qui réponde au 3 conditions
End If
ElseIf boucle2 = "" Then
If .Range("L" & i).Value = boucle3 Then 'Si le level n'est pas renseigné, mais que le reste oui
.Range("S" & s).Value = .Range("H" & i).Value
s = s + 1
ElseIf boucle3 = "" Then
.Range("S" & s).Value = .Range("H" & i).Value
s = s + 1
End If
End If
ElseIf boucle1 = "" Then
If .Range("K" & i).Value = boucle2 Then
If .Range("L" & i).Value = boucle3 Then
.Range("S" & s).Value = .Range("H" & i).Value
s = s + 1 'Jusque la je copie les colonne qui réponde au 3 conditions
ElseIf boucle3 = "" Then
.Range("S" & s).Value = .Range("H" & i).Value
s = s + 1 'Jusque la je copie les colonne qui réponde au 3 conditions
End If
ElseIf boucle2 = "" Then
If .Range("L" & i).Value = boucle3 Then 'Si le level n'est pas renseigné, mais que le reste oui
.Range("S" & s).Value = .Range("H" & i).Value
s = s + 1
ElseIf boucle3 = "" Then
.Range("S" & s).Value = .Range("H" & i).Value
s = s + 1
End If
End If
End If
Next i
End With
End SubJe reviens vers vous. J'ai élargi le code pour que cela prenne en considération l'ensemble des informations du tableau de sélection. Mais je n'arrive pas faire terminé à excel le calcul. Il m'indique une erreur d'exécution 13. Incompatibilité de type. Malgré les recherches je ne comprend pas bien ce qu'il faudrait que je fasse pour exclure le problème.
De plus, ce qui me rend perplexe c'est que la macro fonctionne tant que la première cellule à compléter n'est pas vide. Sinon elle indique le message que je vous ai dit.
Avez un conseil pour me mettre sur la piste, pour trouver d'où vient mon erreur.
Merci d'avance
Bonjour,
J'arrive et je regarderai ça tout à l'heure... mais on va commencer prendre de bonnes habitudes, et d'abord réduire le nombre de module (standard) à 1 !
Module1 contient une macro enregistrée, nommée Tri qui ne trie rien : elle filtre ! Un peu de ogique ne nuierait pas !
Ce code aurait dû être correctement écrit ainsi :
Worksheets(laquelle?).Range("B11").AutoFilter 2, ">2"On pouvait penser Feuil2 ! mais la ligne 11 ne correspond pas à une ligne d'en-tête, il n'y a d'ailleurs pas d'entête !
Je l'écris juste pour l'aspect didactique : on réfère à la feuille (on qualifie !), on cible la mise en place sur la cellule tête du champ à filtrer (Excel prendra toute la base) [s'il peut y avoir ambiguïté en ce qui concerne l'ordre des champs de filtrage, on délimite la ligne d'en-tête : "B11:E11" par exemple, mais le filtrage affectera toute la feuille...], on passe les arguments par position (inutile de singer l'enregistreur !), l'opérateur xlAnd est sans effet sans critère2, et aucun opérateur ne s'imposant on s'abstient.
Ceci étant, il vaut mieux ne pas l'exécuter, en état du fichier, c'est erreur ou résultat inattendu, la composition de l'une ou l'autre des feuille ne correspondant pas au code...
Je supprime Module1 !
Un peu la même chose pour Module2, on supprime !
Module4 a l'air de correspondre à la proc. citée, on supprime donc Module3.
Il y a doublon avec le Module de Feuil2... On efface ce dernier. Une procédure "normale" est normalement placée dans un module standard. Il convient de reserver les module dédiés (sauf cas particuliers) aux procédures d'évènements les concernant.
A suivre
Il y a 2 choses :
1) une erreur en L30, qui te créera une incompatibilité de type...
2) "p5" en M5 alors que dans la colonne L figure éventuellement "P5" : contrairement à Excel, VBA est par défaut sensible à la casse, "p5" est donc différent de "P5" !
Il n'y a pas que ça, parce que c'est très lent !.... (àsuivre)
Mais bien sûr ! J'avais pas noté le xlDown!!!... avec ça ta boucle parcourt plus d'un million de lignes au lieu de 38 !
Du coup, j'ai été au bout... J'avais commencé par arranger l'indentation (pas complètement défectueuse, mais qui restait à réablir plus rigoureusement), à compléter tes non qualifications (point absent devant Cells ou Range...), et hormis une petite simplification possible tes boucles imbriquées s'avéraient tout à fait correctes.
Mais le risque de cellule en erreur, m'a conduit à structurer autrement. En même temps, introduction d'un tableau pour recueillir les résultats et ne les affecter qu'en une seule fois à la fin.
Sub Copierdansordre()
Dim i As Long, j As Integer, s As Integer, NumLst(), yes As Boolean
Dim boucle(1 To 3) As String
With Worksheets("Feuil2")
With .Range("K5:M5")
For i = 1 To 3
boucle(i) = .Cells(1, i).Value
Next i
End With
Application.ScreenUpdating = False
.Columns("S").ClearContents
For i = 10 To .Cells(.Rows.Count, 8).End(xlUp).Row
For j = 1 To 3
If Not IsError(.Cells(i, j + 9)) Then
Select Case .Cells(i, j + 9).Value
Case ""
yes = True: Exit For
Case boucle(j)
Case Else
yes = False: Exit For
End Select
Else
yes = True: Exit For
End If
Next j
If yes Then
ReDim Preserve NumLst(s)
NumLst(s) = .Range("H" & i).Value
s = s + 1: yes = False
End If
Next i
.Range("S10").Resize(s) = WorksheetFunction.Transpose(NumLst)
End With
End SubVariables boucle sous forme de tableau (plus pratique pour utilisation dans une boucle, ne change rien fondamentalement).
Ajouté variables : j (Integer) pour boucle de parcours des 3 colonnes à chaque ligne i, NumLst() tableau pour recueillir les résultats (à incrémenter au fur et à mesure, yes booléenne qui sera à True si la valeur en H de la ligne est à récupérer ou à False sinon.
Note les petites particularités :
Affectation de boucle(?), en utilisant une boucle
L'initialisation de la boucle de parcours des lignes est inchangée, pour chaque ligne on opère une boucle sur les 3 colonnes à tester (j = 1 à 3) [les index des colonnes seront donc j+9...]
On teste d'abord que la cellule n'est pas en erreur, pour éliminer les risques ultérieurs d'incompatibilité...
Si elle l'est, on assimile à la valeur "" (ce qui conduit à recueillir la valeur de H : si tu souhaites le contraire, au lieu de mettre yes=True dans le Else, tu mettras yes=False !
Si pas erreur, on teste si valeur "", ce qui provoque True (sortie de la boucle j), puis si égalité avec boucle(i), ce qui conduit à poursuivre sur colonne suivante, et sinon : False (et sortie de la boucle)...
En sortie de boucle j, si yes est True on recueille résultat (et on réinitialise yes à False).
Pour le résultat on incrémente NumLst avec s (à 0 au départ, on l'incrémente de +1 pour la valeur suivante). Preserve conserve les valeurs déjà recueillies dans le tableau lorsqu'on l'agrandit.
A la fin on affecte le tableau à la plage S10 redimensionné du nombre de lignes correspondant aux valeurs du tableau (lequel est égal à s, les indices du tableau partant de 0).
Cordialement.
Genial,
C'est très détaillé et instructif. En plus vous prenez le temps de m'expliquer mes erreurs et les formules que vous utilisez. Merci pour votre pédagogie et votre expertise.
Je commence à connaitre de plus en plus de commandes grâce à vous.
Merci encore.
Bonne continuation.