Extraire valeur si unique

Bonjour,

Là, tu as utilisé une procédure qui te permet de prélever une liste sans doublons pour l'affecter à une ComboBox ou une ListBox. C'est évidemment utile si tu as à le faire (prélever des valeurs uniques dans une plage comportant des doublons).

Généralement si on prépare les listes dont on aura besoin (dans une feuille qu'on nomme Tables ou Listes ou comme on veut) et qu'on les nomme... on n'aura pas besoin de cela pour constituer une liste : si une liste d'éléments uniques est à établir à partir d'une base, on aura plus d'intérêt, à chaque mise à jour de la base, à utiliser un filtrage avancé sur la colonne voulue de la base (après tri de cette dernière) pour mettre à jour les listes.

Note aussi que tu as au moins 3 méthodes pour affecter une liste à une Combo ou ListBox : AddItem (soit élément par élément), propr. List (comme ici, surtout intéressante si liste multicolonne), propr. RowSource (qui te permet de l'affecter par défaut si ta liste est préconstituée, donc de ne plus t'en occuper dans le code ou très peu).

Dans le cas que tu indiques : des éléments de dico constitués par ta colonne B dont la clé de l'élément est constituée par ta colonne A, tu codes la création des éléments :

monDico(p.Range("A" & i)) = p.Range("B" & i)

Attention, là tu ne l'utilises plus pour filtrer des doublons en A. Et si tu en as dont tu veux regrouper les données de B ou leur faire subir telle ou telle opération (exemple : B contient des nombres [entiers pour simplifier] dont tu veux faire la somme) tu testes l'existence de l'élément dico avant recréation :

If monDico.Exists(p.Range("A" & i)) Then
    v = CInt(monDico(p.Range("A" & i))) + p.Range("B" & i)
    monDico(p.Range("A" & i)) = v
Else
    monDico(p.Range("A" & i)) = p.Range("B" & i)
End If

[Il y a souvent intérêt à passer par une variable pour opérer sur le contenu d'éléments de dico afin d'assurer la conversion dans le type de données voulu dans chaque cas...]

Cordialement et bon dimanche.

Rebonjour!

Merci pour ces informations je regarde si je peux m'en sortir!

Mais juste pour être sûr qu'on parle de la même chose j'ai mis une image.

On a une liste de données en feuil1 (colonne A).

1/ Avec le dictionnaire je vais créer une liste sans doublon (en mémoire vive si j'ai bien compris).

2/ Ensuite je compare cette liste (qui correspond donc aux valeurs possibles trouvées en feuil1) à la colonne A d'une deuxième feuille (feuil 2) et pour chaque correspondance je récupère la valeur de la cellule associée .offset(0,1).

3/ Je veux pouvoir par exemple copier ces valeurs associées dans une troisième feuille.

Avec tes commentaire j'essaye des codes comme celui-là:

Private Sub tri()
Dim v As Variant
Set f = Sheets("Feuil1")
Set p = Sheets("Feuil2")
Set g = Sheets("Feuil3")
Set mondico = CreateObject("Scripting.Dictionary")
  a = f.Range("A12:A" & f.[A65000].End(xlUp).Row)     ' tableau a(n,1) pour rapidité

For i = LBound(a) To UBound(a)
    If a(i, 1) <> "" Then mondico(a(i, 1)) = ""
    Next
    If mondico.exists(p.Range("A" & i)) Then
    v(i) = p.Range("B" & i).Value
    g.Range("A" & i) = v(i).Value
Next i

End Sub

Mais ça fonctionne pas!!

Merci et bon dimanche aussi!

exemple

Non ! ça peut pas marcher !

Si tu indentais mieux ton code, tu aurais vu tout de suite une partie des erreurs.

Au moins au niveau des boucles.

Tu fais un mélange des 3 feuilles, qu'il faut traiter successivement.

Tu n'as apparemment pas besoin de v (et ce n'est pas parceque Boisgontier dans ces exemples shunte les déclarations de variables, sauf particularités, qu'il est judicieux de ne plus les déclarer).

C'est l'heure de repas qui approche !!! Si tu veux bien on reprend pas à pas plus tards.

A+

C'est noté merci, je continue à chercher la solution!

Bon appétit ,

A+

Re salut !

1re étape : mise en place...

Sub tri()
    Dim f As Worksheet, mondico As Object, a, i%

On fait du pas à pas !

D'abord le Private Sub n'est pas très indiqué, une procédure privée n'est accessible qu'à l'intérieur du module où elle se trouve. Elle peut tout de même être lancée, sans être visible... c'est donc une complication inutile...

On fait un traitement successif sur chaque feuille, si on souhaite utiliser une variable feuille, une seule suffit, elle peut être réutilisée pour chacune tour à tour. De même pour la variable compteur utilisée pour les boucles, vu qu'il n'y a pas de boucle imbriquée. Et il en est de même pour la variable "à tout faire" de type Variant a. On n'a donc pas besoin de v.

Et accessoirement, quand on ne déclare pas de type pour une variable, elle est de type Variant, il n'est donc jamais utile de le préciser...


2e étape : feuille 1

    Set f = Sheets("Feuil1")
    Set mondico = CreateObject("Scripting.Dictionary")
    a = f.Range("A1:A" & f.[A65000].End(xlUp).Row)
    For i = LBound(a) To UBound(a)
        If a(i, 1) <> "" Then mondico(a(i, 1)) = ""
    Next i

On constitue le dico composé d'éléments sans doublons...

Rien de particulier par rapport à ta version d'origine, jusque là ça fonctionnait.

On utilise les affectations à f et a pour la feuille 1, on va les réutiliser pour la suite.

Note que tu avais bien le lancement de la boucle et sa fin (avec Next seulement, qui fonctionne, mais quand tu cherches tu ne vois pas immédiatement quelle était la variable) et For et Next n'était pas sur la même indentation, ce qui ne te permettait pas de voir immédiatement qu'il avait à la fin un Next i sans For.

Bonjour!!

D'accord alors f pourra désigner n'importe quelle feuille... comme il n'y a rien après a et i donc ils sont de type variant. Mais je comprends pas le % après le i!

3e étape : feuille 2

    Set f = Sheets("Feuil2")
    a = f.Range("A1:B" & f.[A65000].End(xlUp).Row)
    For i = LBound(a) To UBound(a)
        If mondico.exists(a(i, 1)) Then mondico(a(i, 1)) = a(i, 2)
    Next i

Là, tu affectes à tes éléments de dico les valeurs à prendre dans feuille 2 qui vont remplacer les "" mis initialement.

On utilise f et a de la même façon que pour feuille 1.

Et dans la boucle on teste l'existence d'un élément dico correspondant à la valeur de A dans la feuille pour lui affecter la valeur en B.

Le test d'existence est indispensable, sans quoi tu créerais de nouveaux éléments dico qui foutraient la pagaïe par la suite.

Il te faut mener cette étape à terme avant de passer à l'étape finale.


Intermède

a est de type Variant.

Pour certains type de données, il existe des caractères de déclarations de type qui permettent de raccourcir les déclarations...

Dim i% est équivalent à Dim i As Integer

On dispose également de : & pour Long, ! pour Single, # pour Double et $ pour String.

Merci pour ces explication je commence à y voir bcp plus claire!

Pour les "" je les utilises sans vraiment connaître leur signification.

If a(i, 1) <> "" Then mondico(a(i, 1)) = ""

Si les valeurs des cellules a(i,1) sont différentes de ??

Est-ce que a(i,1) représente les éléments de mondico? ici :

mondico(a(i, 1))

Je pensais que a(i,1) représentait les éléments de la colonne A?

4e étape : finale : affectations feuille 3

    Set f = Sheets("Feuil3")
    a = mondico.items
    For i = 0 To UBound(a)
        f.Range("A" & i + 1) = a(i)
    Next i
End Sub

On va changer un tout petit peu le processus...

f pareil : affectation de la feuille comme précédemment.

a par contre n'a plus à être utilisé pour lui affecter les valeurs d'une plage...

Au fait : j'ai omis de signaler que pour la feuille 2 on avait affecté à f les colonnes A et B (puisqu'on avait besoin des deux).

...je reviens à a, on lui affecte cette fois les items du dico, soit les valeurs qu'on va tranférer sur la feuille.

Petite parenthèse nécessaire :

Une variable tableau se déclare comme toute autre variable. On indique qu'il s'agit d'un tableau par une paire de parenthèses à la suite du nom. A l'intérieur des parenthèses, on indique la ou les dimensions du tableau. Et à la suite le type comme pour toute autre variable, ou (c'est fréquent pour les tableaux) rien qui indique type Variant et permet d'affecter des données de type différent aux divers éléments du tableau.

Dim Tablo(12) est un tableau de 13 éléments (0 à 12), les tableaux sont par défaut d'indice inférieur 0 lorsqu'on ne l'indique pas.

Dim Tablo(1 To 12) est un tableau de 12 éléments (1 à 12)

Dim Tablo(-2 To 12) est un tableau de 15 éléments (-2 à 12)

Dim Tablo(12, 2) est un tableau à 2 dimensions, 39 éléments (13 "lignes", 3 "colonnes"), on parle plutôt de 1re et 2e dimensions.

Un tableau peut avoir jusqu'à 60 dimensions... c'est un peu théorique, à 2 ça va, à 3 cela demande de l'attention, à 4 ça devient un peu casse-tête, au-delà ? sans parler de la consommation de mémoire qui augmente vite alors.

Dim Tablo() déclare un tableau dynamique (non dimensionné lors de sa déclaration) qui doit être dimensionné à l'exécution par l'instruction ReDim. On peut changer à plusieurs reprises les dimensions d'un tableau dynamique (indice supérieur) sans perdre le contenu avec l'instruction ReDim Preserve Tablo(25) par exemple.

Cela a l'air sans rapport avec la discussion mais on y vient... Il était nécessaire d'avoir une vue générale sur les tableaux qui sont un outil important de VBA.

Les variables de type Variant acceptent tout type de données et acceptent également des tableaux. Tes affectations de a constituent des affectations de tableaux à une variable de type Variant. Tableau officiellement déclaré ou Variant contenant un tableau, cela se passe le plus souvent à peu près de la même façon pour s'en servir, sauf qu'avec un Variant on ne maîtrise pas le dimensionnement.

Comme tu as pu voir, les 2 cas où tu as affecté une plage,soit une colonne de valeurs représentant en principe une dimension, tu as testé avec a(i, 1), soit en utilisant deux dimensions comme pour une plage, particularité de l'affectation de plages (qui n'occupent pas les indices 0).

Maintenant, en affectant les items du dico, on revient à une affectation ordinaire (comme on le ferait avec les fonctions Array ou Split).

On sait donc qu'on a un tableau qui débute à l'indice 0 présentant un décalage pour l'affectation à des cellules, la première ligne étant 1.

Dernière remarque : on a supposé ici que tout tes éléments listés en feuille 1 avait une correspondance dans la feuille 2. Si ce n'est pas le cas, on aurait des éléments de dico vides (à "") et donc il faudrait éventuellement (selon l'objectif) tester l'item lors de l'affectation.

Je crois qu'on a fait le tour.

Bonne fin de soirée.


a(i, 1)

Ce sont d'abord les éléments de ta col. A feuille 1.

Tu crées le dico : les clés de dico étant uniques, tu élémines de fait les doublons.

Tu crées 3 fois mondico(1), mais à la fin il n'y a qu'un élément mondico(1)

Sur la feuille 2, tes a(i, 1) sont les éléments de ta col. A de feuille 2, mais sur cette feuille il sont uniques.

Tu testes pour voir à chaque élément de A si une clé de dico existe. Si elle existe, tu affectes à l'élément de dico la valeur figurant en B.

Si toutes tes clés étaient en col. A, tous tes éléments de dico auront pris une valeur.

Sur la feuille 3, tu ne veux récupérer que les valeurs, tu sors donc tous les items du dico...

Re,

Le code marche comme je veux! Merci pour toutes ces informations, j'ai fais un grand pas dans la compréhension de ce que je faisais!

Bonne soirée!!

et bonne continuation.

Rechercher des sujets similaires à "extraire valeur unique"