Variable dictionnaire ou tableau

Résolu/Fermé
1Globule Messages postés 62 Date d'inscription mercredi 4 mai 2016 Statut Membre Dernière intervention 28 mars 2019 - Modifié le 25 mars 2019 à 17:45
1Globule Messages postés 62 Date d'inscription mercredi 4 mai 2016 Statut Membre Dernière intervention 28 mars 2019 - 28 mars 2019 à 08:15
Bonjour à tous,

J'ai un fichier Excel très simple avec une seule colonne de près de 7000 lignes, contenant des codes produit.
Les informations des produits se trouvent dans un autre fichier csv, qui lui dépasse les 10 000 lignes, et qui a de nombreuses colonnes dont je n'ai pas besoin.

Ce que je fais pour l'instant, c'est importer le fichier csv sur une autre feuille, que je nomme "Temp".
Ensuite à l'aide d'innombrables formules Index/Equiv, je récupère les données dont j'ai besoin, je les colle en valeur et je supprime la feuille "Temp".

Le tout en Vba me prend environ 10 secondes, c'est assez long puisque je dois faire la manoeuvre plusieurs fois par heure (les données produits changent régulièrement).

Je me suis donc intéressé aux variables Dictionnaire et Tableau, mais je n'y arrive pas vraiment.
Rien que sur une colonne recherchée, je perds du temps par rapport à un Index-Equiv.

Ci-dessous je vous joins ce que j'ai réussi à coder.
Ce n'est pas très convainquant. Pourriez-vous éventuellement m'aider à l'améliorer ?

' Création du dictionnaire et alimentation par boucle
Set prod = CreateObject("Scripting.Dictionary")
For i = 2 To Sheets("Temp").Cells(Rows.Count, 1).End(xlUp).Row
    If Not prod.Exists(Sheets("Temp").Cells(i, 1).Value) Then prod.Add Sheets("Temp").Cells(i, 1).Value, Sheets("Temp").Cells(i, 3).Value ' Je stocke le code produit et la troisième colonne
Next

' Récupération des données dans la première feuille
Sheets("Produits").Select
For j = 2 To Cells(Rows.Count, 1).End(xlUp).Row
  Cells(j, 3).Value = prod.Item(Cells(j, 1).Value)
Next



Configuration: Windows / Firefox 45.0
A voir également:

5 réponses

1Globule Messages postés 62 Date d'inscription mercredi 4 mai 2016 Statut Membre Dernière intervention 28 mars 2019 2
26 mars 2019 à 08:59
Merci Patrice,

Effectivement, je n'y étais pas du tout...

Pourrais-tu m'éclairer sur ton code ?

Cette ligne : P(T(L, 1)) = T(L, 3) me semble signifier que :
P est le dictionnaire auquel on ajoute une clé (la ligne L, colonne 1) du tableau T.
Et la valeur associée à cette clé est égale à la ligne L, colonne 3 du tableau T.

Si c'est correct, comment dois-je faire pour récupérer plusieurs valeurs ?
J'ai besoin de la colonne 3, mais aussi de la 6 et de la 13, or il me semblait que les dictoinnaires ne supportaient qu'une valeur par clé.

Merci pour ton aide,
1
Patrice33740 Messages postés 8556 Date d'inscription dimanche 13 juin 2010 Statut Membre Dernière intervention 2 mars 2023 1 776
25 mars 2019 à 18:19
Bonjour,

Le plus rapide est d'utiliser des tableaux :
Sub test()
Dim P As Object
Dim T, L&, D&
  With Worksheets("Temp")
    D = .Cells(.Rows.Count, 1).End(xlUp).Row
    T = .Range("A2:C" & D).Value
  End With
  Set P = CreateObject("Scripting.Dictionary")
  For L = LBound(T) To UBound(T)
    P(T(L, 1)) = T(L, 3)
  Next L
  With Worksheets("Produits")
    D = .Cells(.Rows.Count, 1).End(xlUp).Row
    T = .Range("A2:C" & D).Value
    For L = LBound(T) To UBound(T)
      T(L, 3) = P(T(L, 1))
    Next L
    .Range("A2:C" & D).Value = T
  End With
End Sub
0
Patrice33740 Messages postés 8556 Date d'inscription dimanche 13 juin 2010 Statut Membre Dernière intervention 2 mars 2023 1 776
Modifié le 26 mars 2019 à 11:36
Bonjour,

Effectivement, la ligne P(T(L, 1)) = T(L, 3), ajoute la clé du tableau T si elle n'existe pas et y associe l'item de la colonne 3. Si la clé existe, elle y associe le nouvel item.
Pour mémoriser 3 valeurs, plusieurs solutions se présentent, plus ou moins gourmandes en mémoire vive.

J'ai opté pour une des moins gourmandes : utiliser 4 tableaux et un dictionnaire en mettant les 3 valeurs dans l'item séparées par un séparateur spécial (hors caractères utilisables).
Sub test()
Dim P As Object
Dim T1, T2, T3, T4, L&, D&
  ' definir les tableaux sources
  With Worksheets("Temp")
    D = .Cells(.Rows.Count, 1).End(xlUp).Row
    T1 = .Range("A2:A" & D).Value  'clé
    T2 = .Range("C2:C" & D).Value  '1° valeur
    T3 = .Range("F2:F" & D).Value  '2° valeur
    T4 = .Range("M2:M" & D).Value  '3° valeur
  End With
  ' mémoriser les valeurs dans un dictionnaire
  Set P = CreateObject("Scripting.Dictionary")
  For L = LBound(T1) To UBound(T1)
    P(T1(L, 1)) = T2(L, 1) & Chr(1) & T3(L, 1) & Chr(1) & T4(L, 1) 'concatène les 3 valeurs dans le dictionnaire
  Next L
  ' restituer les valeurs
  With Worksheets("Produits")
    D = .Cells(.Rows.Count, 1).End(xlUp).Row
    T1 = .Range("A2:A" & D).Value   'clé
    T2 = .Range("C2:C" & D).Value   'colonne de destination de la 1° valeur (on pourrait changer de colonne)
    T3 = .Range("F2:F" & D).Value   'colonne de destination de la 2° valeur (on pourrait changer de colonne)
    T4 = .Range("M2:M" & D).Value   'colonne de destination de la 3° valeur (on pourrait changer de colonne)
    For L = LBound(T1) To UBound(T1)
      T2(L, 1) = Split(P(T1(L, 1)), Chr(1))(0)
      T3(L, 1) = Split(P(T1(L, 1)), Chr(1))(1)
      T4(L, 1) = Split(P(T1(L, 1)), Chr(1))(2)
    Next L
    .Range("C2:C" & D).Value = T2   'Ici on remet les valeurs en place
    .Range("F2:F" & D).Value = T3  '  "
    .Range("M2:M" & D).Value = T4  '  "
  End With
End Sub

On aurait pu utiliser un seul tableau, le code serait plus simple mais cela mémorise de nombreuses colonnes inutilement.


0
Patrice33740 Messages postés 8556 Date d'inscription dimanche 13 juin 2010 Statut Membre Dernière intervention 2 mars 2023 1 776
26 mars 2019 à 11:48
PS : Attention si il s'agit de dates, il faut traiter le tableau restitué ligne par ligne en format local.
0
1Globule Messages postés 62 Date d'inscription mercredi 4 mai 2016 Statut Membre Dernière intervention 28 mars 2019 2
26 mars 2019 à 16:28
Le code se complique :/

En tout cas il fonctionne très bien (je gagne plus d'une seconde juste sur cette partie).

Un tout petit souci : Si le produit n'existe pas dans la feuille Temp (ce qui ne devrait pas arriver, mais qui malheureusement arrive de temps en temps), j'ai un plantage (L'indice n'appartient pas à la sélection).

Est-ce qu'il pourrait renvoyer un #N/A, si possible ?
Si tu veux bien m'aider sur ce dernier point, et ensuite j'étudierais le code en détails pour récupérer des données qui se trouvent dans d'autres feuilles. A priori pas de date (ouf !).

Un grand merci en tout cas !
0
Patrice33740 Messages postés 8556 Date d'inscription dimanche 13 juin 2010 Statut Membre Dernière intervention 2 mars 2023 1 776
26 mars 2019 à 23:31
Remplaces :
    For L = LBound(T1) To UBound(T1)
      T2(L, 1) = Split(P(T1(L, 1)), Chr(1))(0)
      T3(L, 1) = Split(P(T1(L, 1)), Chr(1))(1)
      T4(L, 1) = Split(P(T1(L, 1)), Chr(1))(2)
    Next L

Par :
    For L = LBound(T1) To UBound(T1)
      If P.Exists(T1(L, 1)) Then
        T2(L, 1) = Split(P(T1(L, 1)), Chr(1))(0)
        T3(L, 1) = Split(P(T1(L, 1)), Chr(1))(1)
        T4(L, 1) = Split(P(T1(L, 1)), Chr(1))(2)
      Else
        T2(L, 1) = "#N/A"
        T3(L, 1) = "#N/A"
        T4(L, 1) = "#N/A"
      End If
    Next L
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
1Globule Messages postés 62 Date d'inscription mercredi 4 mai 2016 Statut Membre Dernière intervention 28 mars 2019 2
28 mars 2019 à 08:15
Merci mille fois Patrice.

Ce code est parfait et très rapide. Je vais maintenant essayer de le transposer aux autres données que je dois récupérer.
Je place le sujet en Résolu, mais j'ai comme l'impression que j'aurais encore besoin d'aide sur les varaibles tableaux et dictionnaires (qui restent quand même un peu mystérieuses pour moi).

Merci encore.
0