Vlookup sur variable : Erreur 424

Résolu
Miss_marmotte Messages postés 1 Date d'inscription   Statut Membre Dernière intervention   -  
 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 :
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.

4 réponses

jordane45 Messages postés 38486 Date d'inscription   Statut Modérateur Dernière intervention   4 752
 
Bonjour,
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)

0
Miss_marmotte
 
Merci beaucoup de me répondre.
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.
0
jordane45 Messages postés 38486 Date d'inscription   Statut Modérateur Dernière intervention   4 752 > Miss_marmotte
 
Tu as mis le .value sur cde (comme moi ) ?
Une autre possibilité. .. change ton range de recherche sur une plage définie au leu des deux colonnes.
Range ("a1:h5000")
0
Miss_marmotte > jordane45 Messages postés 38486 Date d'inscription   Statut Modérateur Dernière intervention  
 
Bonjour Jordane,

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.
0
pijaku Messages postés 12263 Date d'inscription   Statut Modérateur Dernière intervention   2 761
 
Bonjour Marmotte, Jordane45,

Oula!
Pas mal d'erreurs.

Commençons par le début :
Tu déclares
Cde As Range
et 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)")
...
0
Miss_marmotte
 
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
0
pijaku Messages postés 12263 Date d'inscription   Statut Modérateur Dernière intervention   2 761 > Miss_marmotte
 
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.

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
0
Miss_marmotte > pijaku Messages postés 12263 Date d'inscription   Statut Modérateur Dernière intervention  
 
Bonjour Pijaku,

Je te remercie pour toutes tes précieuses indications.
Malheureusement, avec mon code modifié ou le tien, ça ne fonctionne pas (la partie vlookup) je reçois toujours le message d'erreur 424.
Je ne comprends pas pourquoi...
Bien cordialement
0
pijaku Messages postés 12263 Date d'inscription   Statut Modérateur Dernière intervention   2 761
 
Bonjour,

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...
0
Miss_marmotte > pijaku Messages postés 12263 Date d'inscription   Statut Modérateur Dernière intervention  
 
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
0
pijaku Messages postés 12263 Date d'inscription   Statut Modérateur Dernière intervention   2 761
 
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 :

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 🎶
0
Miss_marmotte
 
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
0
pijaku Messages postés 12263 Date d'inscription   Statut Modérateur Dernière intervention   2 761
 
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++
0
Miss_marmotte > pijaku Messages postés 12263 Date d'inscription   Statut Modérateur Dernière intervention  
 
Merci pour ces liens.
Ce n'est pas encore limpide mais je commence à mieux comprendre.
Et ce dictionary est une vraie découverte !
0