Vlookup sur variable : Erreur 424
Résolu
Miss_marmotte
Messages postés
1
Date d'inscription
Statut
Membre
Dernière intervention
-
Miss_marmotte -
Miss_marmotte -
Bonjour,
Je suis novice en VBA et j'ai beau chercher, je n'avance plus.
J'ai un onglet avec des lignes de détail de commandes et entre autres un montant associé, je veux donc créer un onglet qui me donne pour chaque numéro de commande son total (une ou plusieurs lignes de détail).
Je pensais utiliser Do While avec For each pour tenir compte de la possibilité (fréquente) de plusieurs lignes de détail pour une commande, mais je suis de toute façon restée bloquée à la phase antérieure. Qu'est-ce que je fais mal ?
Si quelqu'un peut m'aider, ce serait vraiment très sympa, merci d'avance
Voici mon code :
EDIT : Ajout des balises de code.
Je suis novice en VBA et j'ai beau chercher, je n'avance plus.
J'ai un onglet avec des lignes de détail de commandes et entre autres un montant associé, je veux donc créer un onglet qui me donne pour chaque numéro de commande son total (une ou plusieurs lignes de détail).
Je pensais utiliser Do While avec For each pour tenir compte de la possibilité (fréquente) de plusieurs lignes de détail pour une commande, mais je suis de toute façon restée bloquée à la phase antérieure. Qu'est-ce que je fais mal ?
Si quelqu'un peut m'aider, ce serait vraiment très sympa, merci d'avance
Voici mon code :
Option Explicit Sub essai_totaux() Application.DisplayAlerts = False Dim Sh As Worksheet Dim cdes As Range Dim cde As Range Set cdes = Worksheets("Récap").Range("a1").CurrentRegion.Resize(Worksheets("Récap").Range("a1").CurrentRegion.Rows.Count - 1, 1).Offset(1) cde = Application.Min(Worksheets("Détails").Range("a:a")).Value For Each Sh In Worksheets If Sh.Name = "Récap" Then Sh.Delete End If Next Sheets.Add(after:=Worksheets("Détails")).Name = ("Récap") Worksheets("Détails").Activate Columns("A:A").Copy Worksheets("Récap").Range("a1") Worksheets("Récap").Range("a:a").RemoveDuplicates Columns:=1, Header:=xlYes For Each cde In cdes Worksheets("Récap").Cells(cde.Row, 2).Value = Application.VLookup(cde, Worksheets("Détails").Range("a:h"), 8, False) Next cde Application.DisplayAlerts = True End Sub
EDIT : Ajout des balises de code.
A voir également:
- Vba currentregion
- Vba range avec variable ✓ - Forum VB / VBA
- Variable d'environnement temp ✓ - Forum Microsoft Office
- Variable objet ou variable de bloc with non définie - Forum VB / VBA
- Le fichier contient un programme écrit en python. le programme construit un mot secret mais il ne l'affiche pas. modifiez ce programme afin que à chaque itération de la boucle : la variable a augmente de 2 la variable b diminue de 1 ajoutez une instruction pour faire afficher le mot secret construit. quel est ce mot secret ? ✓ - Forum Python
- Variable objet ou bloc "with" non définie - Forum VB / VBA
4 réponses
Bonjour,
Je n'ai pas testé ton code.. mais déjà il me semble que tu as omis : WorkSheetFunction devant ton Vlookup
Je n'ai pas testé ton code.. mais déjà il me semble que tu as omis : WorkSheetFunction devant ton Vlookup
Application.WorksheetFunction.VLookup(cde.value, Worksheets("Détails").Range("a:h"), 8, False)
Bonjour Marmotte, Jordane45,
Oula!
Pas mal d'erreurs.
Commençons par le début :
Tu déclares
Pas bon!
La ligne :
ne te sers à rien???
Si oui, supprimes là.
En plus elle est totalement fausse et ne te renverra qu'un message d'erreur.
Ensuite, plutôt que d'utiliser Application.WorkSheetFunction(blablabla), je te recommande l'utilisation de la méthode Evaluate en VBA. Plus simple, super maniable, beaucoup plus compréhensible.
Par exemple, pour calculer la minimum de la colonne A :
Difficile de faire plus simple...
Ah si! En utilisant une autre écriture de la méthode Evaluate, les crochets :
Nota : lorsque l'on écrit la méthode Evaluate dans sa syntaxe complète (Evaluate("blabla")), son argument doit être de type String. Pas dans son écriture simplifiée. D'où l'absence des guillemets dans
Oula!
Pas mal d'erreurs.
Commençons par le début :
Tu déclares
Cde As Rangeet après tu cherches à lui attribuer une valeur numérique avec la fonction Min...
Pas bon!
La ligne :
cde = Application.Min(Worksheets("Détails").Range("a:a")).Value
ne te sers à rien???
Si oui, supprimes là.
En plus elle est totalement fausse et ne te renverra qu'un message d'erreur.
Ensuite, plutôt que d'utiliser Application.WorkSheetFunction(blablabla), je te recommande l'utilisation de la méthode Evaluate en VBA. Plus simple, super maniable, beaucoup plus compréhensible.
Par exemple, pour calculer la minimum de la colonne A :
Dim monMini As Double monMini = Evaluate("MIN(A:A)")
Difficile de faire plus simple...
Ah si! En utilisant une autre écriture de la méthode Evaluate, les crochets :
Dim monMini As Double monMini = [MIN(A:A)]
Nota : lorsque l'on écrit la méthode Evaluate dans sa syntaxe complète (Evaluate("blabla")), son argument doit être de type String. Pas dans son écriture simplifiée. D'où l'absence des guillemets dans
monMini = [MIN(A:A)]et leur présence dans
Evaluate("MIN(A:A)")...
Bonjour Pijaku,
Merci à toi aussi de ton aide.
Je croyais qu'il fallait initialiser la variable et c'est ce que j'ai tenté de faire avec la fonction Min.
Peux-tu en revanche me dire pourquoi elle est totalement fausse ?
J'avoue que je patauge complètement avec mes variables et je ne sais plus ce que je dois déclarer et comment pour faire ce que je voudrais faire.
Merci beaucoup pour le tip pour Evaluate, je ne connaissais pas.
Bien cordialement
Merci à toi aussi de ton aide.
Je croyais qu'il fallait initialiser la variable et c'est ce que j'ai tenté de faire avec la fonction Min.
Peux-tu en revanche me dire pourquoi elle est totalement fausse ?
J'avoue que je patauge complètement avec mes variables et je ne sais plus ce que je dois déclarer et comment pour faire ce que je voudrais faire.
Merci beaucoup pour le tip pour Evaluate, je ne connaissais pas.
Bien cordialement
1- Question idiote sans doute mais j'ai beau chercher, je ne trouve pas comment mettre le code en forme comme toi...
Le mode d'emploi (au cas ou) est ICI.
2- Reprenons ton code partie par partie.
Application.DisplayAlerts = False sert uniquement, dans ton cas, à ne pas voir le message en cas de suppression de feuille "récap".
Déclaration des variables. Ok.
Jusqu'ici tout va bien.
Tu attribues, à ta variable Range cdes, un objet Range. Ok, tout va bien.
Bon pour être honnête, la syntaxe utilisant les CurrentRegion et resize est pour le moins complexe. On pourrait simplifier si tu nous disais de quel Range il s'agit. Exemple : toute la colonne C...
te sers à "initialiser" ta variable cde...
cde étant déclarée comme Range, cette ligne te renvoie une erreur.
De plus, dans le reste du code, tu utilises cde dans une boucle For Each. Il n'y a donc pas besoin de l'initialiser.
Donc... supprimes cette ligne!
Te sers à supprimer une éventuelle "Récap" déjà faite.
Bon, il y a plus simple et plus rapide pour supprimer une éventuelle feuille :
Ici, pas de souci, tu crées une nouvelle feuille Récap et tu y colles les données de la feuille Détails colonne A...
Ici tu boucle sur toutes les cellules de ta plage définie (cdes) pour appliquer tes RECHERCHEV (VLookUp).
Attention aux remarques de Jordane45, sur
Pour la fin, pas de souci :
Donc, ta macro pourrait s'écrire :
Le mode d'emploi (au cas ou) est ICI.
2- Reprenons ton code partie par partie.
Option Explicit Sub essai_totaux() Application.DisplayAlerts = False
Application.DisplayAlerts = False sert uniquement, dans ton cas, à ne pas voir le message en cas de suppression de feuille "récap".
Dim Sh As Worksheet Dim cdes As Range Dim cde As Range
Déclaration des variables. Ok.
Jusqu'ici tout va bien.
Set cdes = Worksheets("Récap").Range("a1").CurrentRegion.Resize(Worksheets("Récap").Range("a1").CurrentRegion.Rows.Count - 1, 1).Offset(1)
Tu attribues, à ta variable Range cdes, un objet Range. Ok, tout va bien.
Bon pour être honnête, la syntaxe utilisant les CurrentRegion et resize est pour le moins complexe. On pourrait simplifier si tu nous disais de quel Range il s'agit. Exemple : toute la colonne C...
cde = Application.Min(Worksheets("Détails").Range("a:a")).Value
te sers à "initialiser" ta variable cde...
cde étant déclarée comme Range, cette ligne te renvoie une erreur.
De plus, dans le reste du code, tu utilises cde dans une boucle For Each. Il n'y a donc pas besoin de l'initialiser.
Donc... supprimes cette ligne!
For Each Sh In Worksheets If Sh.Name = "Récap" Then Sh.Delete End If Next
Te sers à supprimer une éventuelle "Récap" déjà faite.
Bon, il y a plus simple et plus rapide pour supprimer une éventuelle feuille :
On Error Resume Next 'désactive le gestionnaire d'erreurs 'si elle n'existe pas, pas de message d'erreur car gestionnaire désactivé Sheets("Récap").Delete 'supprime la feuille On Error Goto 0 'réactive le gestionnaire d'erreurs
Sheets.Add(after:=Worksheets("Détails")).Name = ("Récap") Worksheets("Détails").Activate Columns("A:A").Copy Worksheets("Récap").Range("a1") Worksheets("Récap").Range("a:a").RemoveDuplicates Columns:=1, Header:=xlYes
Ici, pas de souci, tu crées une nouvelle feuille Récap et tu y colles les données de la feuille Détails colonne A...
For Each cde In cdes Worksheets("Récap").Cells(cde.Row, 2).Value = Application.VLookup(cde, Worksheets("Détails").Range("a:h"), 8, False) Next cde
Ici tu boucle sur toutes les cellules de ta plage définie (cdes) pour appliquer tes RECHERCHEV (VLookUp).
Attention aux remarques de Jordane45, sur
Application.WorksheetFunction.VLookup
Pour la fin, pas de souci :
Application.DisplayAlerts = True End Sub
Donc, ta macro pourrait s'écrire :
Option Explicit Sub essai_totaux() Dim cdes As Range Dim cde As Range Application.DisplayAlerts = False Set cdes = Worksheets("Récap").Range("a1").CurrentRegion.Resize(Worksheets("Récap").Range("a1").CurrentRegion.Rows.Count - 1, 1).Offset(1) On Error Resume Next Sheets("Récap").Delete On Error Goto 0 Sheets.Add(after:=Worksheets("Détails")).Name = ("Récap") Worksheets("Détails").Activate Columns("A:A").Copy Worksheets("Récap").Range("a1") Worksheets("Récap").Range("a:a").RemoveDuplicates Columns:=1, Header:=xlYes For Each cde In cdes Worksheets("Récap").Cells(cde.Row, 2).Value = Application.WorksheetFunction.VLookup(cde.value, Worksheets("Détails").Range("a:h"), 8, False) Next cde Application.DisplayAlerts = True End Sub
Bonjour,
Il nous faut le classeur alors...
Il nous faut le classeur alors...
Pour transmettre un fichier, il faut passer par un site de pièce jointe tel que cjoint.com
Va sur ce site : https://www.cjoint.com/
Clic sur parcourir,
Cherche ton fichier,
clic sur ouvrir,
Clic sur "Créer le lien cjoint",
Copier le lien,
Revenir ici le coller dans une réponse...
Bonjour Pijaku,
Merci pour ta réponse et désolée du délai.
Voici donc mon fichier en suivant tes constructions :
http://cjoint.com/?0Lrnp5rgj3R
Je souhaite donc à partir de l'onglet Détails pouvoir créer un onglet Récap qui affiche le total de chacune des commandes, celles-ci pouvant comporter plusieurs lignes de détail.
Ma macro s'appelle essai_totaux et se trouve dans le module 2.
J'espère que je suis assez claire.
Et encore un grand merci pour ton aide.
Bien cordialement
Merci pour ta réponse et désolée du délai.
Voici donc mon fichier en suivant tes constructions :
http://cjoint.com/?0Lrnp5rgj3R
Je souhaite donc à partir de l'onglet Détails pouvoir créer un onglet Récap qui affiche le total de chacune des commandes, celles-ci pouvant comporter plusieurs lignes de détail.
Ma macro s'appelle essai_totaux et se trouve dans le module 2.
J'espère que je suis assez claire.
Et encore un grand merci pour ton aide.
Bien cordialement
Bon, je supposes que les réponses à mon dernier commentaires sont oui...
Tout simplement, avec VLookup, tu étais hyper mal partie.
Pour réaliser ta récap, rien de mieux qu'un objet dictionnary.
Utilisé comme ceci :
🎼 Cordialement,
Franck 🎶
Tout simplement, avec VLookup, tu étais hyper mal partie.
Pour réaliser ta récap, rien de mieux qu'un objet dictionnary.
Utilisé comme ceci :
Sub Calcul_Toto() Dim myDico As Object, Tb(), i As Long 'création de la feuille Récap Application.DisplayAlerts = False On Error Resume Next Sheets("Récap").Delete On Error GoTo 0 Sheets.Add(after:=Worksheets("Détails")).Name = ("Récap") Application.DisplayAlerts = True 'entêtes de colonnes de la feuille Récap With Sheets("Détails") .Range("A1").Copy Sheets("Récap").Range("A1") .Range("H1").Copy Sheets("Récap").Range("B1") 'récolte des données Set myDico = CreateObject("Scripting.Dictionary") Tb = .Range("A2:H" & .Range("A" & Rows.Count).End(xlUp).Row).Value End With 'calculs sous totaux For i = LBound(Tb, 1) To UBound(Tb, 1) myDico(Tb(i, 1)) = myDico(Tb(i, 1)) + Tb(i, 8) Next i 'Restitution dans la feuille Récap With Sheets("Récap") .[A2].Resize(myDico.Count, 1) = Application.Transpose(myDico.keys) .[B2].Resize(myDico.Count, 1) = Application.Transpose(myDico.items) End With End Sub
🎼 Cordialement,
Franck 🎶
Bonjour Pijaku,
Désolée, je ne reçois plus les alertes indiquant un nouveau message et je n'ai donc pas vu ta question.
Je viens de faire tourner ton code et c'est effectivement exactement cela que je voulais. Je t'en remercie infiniment.
En revanche, je t'avoue que je ne comprends pas grand chose pour l'instant à la nouvelle partie de code, n'ayant jamais entendu d'un objet dictionary notamment.
Je vais donc travailler tout ça et je me permettrai de revenir vers toi si j'ai encore des questions.
Aurais-tu un manuel ou un site à m'indiquer pour approfondir mes connaissances sur Excel VBA ?
Merci encore.
Bien cordialement
Désolée, je ne reçois plus les alertes indiquant un nouveau message et je n'ai donc pas vu ta question.
Je viens de faire tourner ton code et c'est effectivement exactement cela que je voulais. Je t'en remercie infiniment.
En revanche, je t'avoue que je ne comprends pas grand chose pour l'instant à la nouvelle partie de code, n'ayant jamais entendu d'un objet dictionary notamment.
Je vais donc travailler tout ça et je me permettrai de revenir vers toi si j'ai encore des questions.
Aurais-tu un manuel ou un site à m'indiquer pour approfondir mes connaissances sur Excel VBA ?
Merci encore.
Bien cordialement
De rien.
En ce qui concerne l'objet dictionnary, tu trouveras un tuto ici :
http://boisgontierjacques.free.fr/pages_site/Dictionnaire.htm
Pour des liens vers des cours et tutos VBA, il y a ce forum, bien sur, mais également :
- http://boisgontierjacques.free.fr/index2.htm
- https://silkyroad.developpez.com/
- https://www.excel-pratique.com/fr/vba.php
etc...
A++
En ce qui concerne l'objet dictionnary, tu trouveras un tuto ici :
http://boisgontierjacques.free.fr/pages_site/Dictionnaire.htm
Pour des liens vers des cours et tutos VBA, il y a ce forum, bien sur, mais également :
- http://boisgontierjacques.free.fr/index2.htm
- https://silkyroad.developpez.com/
- https://www.excel-pratique.com/fr/vba.php
etc...
A++
Je croyais que le Worksheetfunction n'était pas obligatoire.
Je l'ai ajouté mais ça ne change rien...
Merci pour la "remise en forme de mon code", je n'ai pas compris comment faire quand j'ai posté ma question.
Une autre possibilité. .. change ton range de recherche sur une plage définie au leu des deux colonnes.
J'imagine que tu voulais dire ça :
Worksheets("Récap").Cells(cde.Row, 2).Value = Application.VLookup(cde, Worksheets("Détails").Range("Plage_recherche"), 8, False)
Ça ne change rien.
Question idiote sans doute mais j'ai beau chercher, je ne trouve pas comment mettre le code en forme comme toi...
Merci de ton aide.