Vlookup sur variable : Erreur 424

Résolu
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

  1. 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
    1. @pijakuMerci pour ces liens.
      Ce n'est pas encore limpide mais je commence à mieux comprendre.
      Et ce dictionary est une vraie découverte !
  2. Modérateur
    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 🎶
    1. Modérateur
      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)")
      ...
      1. 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
      2. Modérateur
        @Miss_marmotte1- 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
      3. @pijakuBonjour 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
      4. Modérateur
        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...
      5. @pijakuBonjour 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
    2. Modérateur
      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)
      

      1. 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.
      2. Modérateur
        @Miss_marmotteTu 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")
        
      3. @jordane45Bonjour 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.