Structure dictionnaire

Bonjour,

3 colonnes, A B et C

colonne A des chaines de caractères

colonne B des chaines de caractères

Je souhaite que la colonne C prenne la valeur 1 si A est inclus dans B

2 si A n'est pas dans B

3 si A est dans B en doublon ou plus

Le code qui suit j'initialise les 2 dictionnaires, mais je ne sais pas si je m'y prend bien sachant que j'aimerais que la comparaison se fasse le plus rapidement possible.

Sub StructureDictionnaire()
    Dim DicoT As New Scripting.Dictionary
    Dim DicoC As New Scripting.Dictionary
    Dim li%, Der%
    li = 1
    Der = Range("A1048576").End(xlUp).Row
    While li <= Der
        If Not DicoT.Exists(li) Then MonDico.Add li, UCase(Cells(li, 1).Value)
        li = li + 1
    Wend
    li = 1
    Der = Range("B1048576").End(xlUp).Row
    While li <= Der
        If Not DicoC.Exists(li) Then MonDico.Add li, UCase(Cells(li, 2).Value)
        li = li + 1
    Wend

    '....... o-O ???

    Set DicoT = Nothing
    Set DicoC = Nothing
End Sub

Merci par avance, je débute avec les dictionnaire et j'ai un peu de mal.

Si j'ai bien compris les dictionnaire sont comme des tableaux à 2 dimensions de taille variable.

Salutation

Bonjour,

Merci de joindre un fichier à ta demande.

Cdlt.

voici :

40test.xlsm (18.66 Ko)

Bonjour,

C'est pour t'entrainer ?

Parce qu'avec =NB.SI(B:B;"*"&A1&"*") tu as le nombre de fois où il est présent.

(que tu peux adapter en vba)

eric

Bonjour,

Avant je passais par du VBA,

Je testais la présence de doublon, puis chaque séquence de A dans B, le problème est que dans la colonne A maintenant j'ai 1000 séquence et dans B 10.000 donc le code prenait 4 minutes d'exécution et j'ai entendu parler de scripting dictionaire qui permet de réduire énormément le temps d'exécution.

Et je ne souhaite passer que par le VBA,

Emmanuel

Bonjour,

VBA est rarement plus rapide que les fonctions feuilles qui sont largement plus optimisées, c'est valable uniquement dans des cas précis.

Et je le répète, tu peux traduire en vba NB.SI(B:B;"*"&A1&"*").

Je ne ferais pas le test mais toutes les chances que ce soit plus rapide (même avec les dictionaries) en plus d'être plus simple.

Mais bon, ça t'entrainera à utiliser les dict

eric

Pour plus de détails :

La colonne A et B ne sont pas sur la même feuille, et selon le résultat je colore ces cellules en vert jaune ou rouge.

A partir de ces couleurs je compte et affiche un résultat.

Hors je considère que les "conditionnelle de mise en forme ne sont pas fiable" j'ai déjà eu des erreurs ou approximations.

Je cherche un moyen d'effectuer ces recherches et d'afficher le résultat : doublon dans colonne B et si A est inclut dans B, le plus vite possible en VBA.

Avant je parcourais B et recherchais les doublons ce qui faisait une recherche exponentielle car parcourt la colonne autant de fois qu'il y a de séquence à rechercher. Et après re-parcourt une fois pour chaque séquence de colonne A.

Si A contient 1000 séquence alors B qui en contient 10.000 est parcouru 10.000*1000*2 = 20.000.000 d'où la longueur d'exécution.

J'avais penser utiliser un tableau à 2 dimensions et classer les séquences B par ordre alphanumérique de façon à optimiser la recherche. Mais je ne sais pas déclarer un tableau à 2 dimension de taille variable.

Ensuite j'ai entendus parler des scripting dictionnaire qui semble corresponde à ce que je cherche mais là c'est sur l'utilisation que je patauge.

Gloutoni

Dernière chose en ce qui concerne les dictionnaires je n'arrive pas à me représenté mentalement en quoi cela consiste et comment cela fonctionne.

Et avec le tableau à 2 dimension de taille variable je pensais implémenter une recherche dichotomique.

Gloutoni

Hors je considère que les "conditionnelle de mise en forme ne sont pas fiable" j'ai déjà eu des erreurs ou approximations.

Etonnant. On n'a jamais tout vu mais jamais vu de signalement de cet ordre.

Sans doute que tu avais des valeurs particulières dont ta formule ne tenait pas compte.

Par curiosité ça prend combien de temps avec 1000 lignes en A et 10000 en B :

Sub test()
    Dim datas
    Dim lig As Long, t As Single
    t = Timer
    Range("C1:C" & Cells(Rows.Count, 1).End(xlUp).Row) = "=COUNTIF(Sheet1!C[-1],""*""&RC[-2]&""*"")"
    datas = Range("C1:C" & Cells(Rows.Count, 1).End(xlUp).Row).Value
    [C1].Resize(UBound(datas)) = datas
    MsgBox Timer - t
End Sub

et tu veux vraiment tes valeurs 1, 2, 3 mais autant changer ta formule MFC tu peux insérer :

    For lig = 1 To UBound(datas)
        If datas(lig, 1) = 0 Then
            datas(lig, 1) = 2
        ElseIf datas(lig, 1) > 1 Then
            datas(lig, 1) = 3
        End If
    Next lig

Pour les tableaux de taille variable j'ai trouvé déclarer un tableau et le redimensionner à l'aide de ReDim :

    Dim tabloT() As String, tabloC() As String
    Dim li%, derT%, derC%
    derT = Range("A1048576").End(xlUp).Row
    derC = Range("B1048576").End(xlUp).Row
    li = 1

    ReDim tabloT(derT)
    ReDim tabloC(derC)

mais pour le scripting dictionnary je patauge


je vais tenter d'exploiter le tableau, après je regarde ton code et ensuite je testerais avec les dictionnaire, le temps d'exécution choisiras


"Par curiosité ça prend combien de temps avec 1000 lignes en A et 10000 en B :" : 6.050781 sec

ok

Pour les dictionaries (et en général) évite la déclaration avec As New qui risquent de te poser de problèmes selon les config.

Utilise plutôt Set dict = CreateObject("Scripting.Dictionary")

Et si tu veux que ce soit rapide lit toute la plage d'un coup dans une variable tableau et travaille dessus, lire cellule par cellule est très lent.

Ex dict sans doublon :

    Dim dict, lig As Long, pl() As Variant
    Set dict = CreateObject("Scripting.Dictionary")
    pl = [A2].Resize(Cells(Rows.Count, 1).End(xlUp).Row - 1, 1).Value
    For lig = 1 To UBound(pl)
        If pl(lig, 1) <> "" Then
            dict(pl(lig, 1)) = pl(lig, 1)
        End If
    Next lig
    '[c2].Resize(dict.Count, 1) = Application.Transpose(dict.Keys)

La dernière ligne est pour coller le résultat. Attention Transpose limite à 65536 lignes. Si plus il faut faire autrement.

Pour voir si une entrée existe :

If dict.Exists(clé) then

Mais je ne vois pas bien ce que tu vas y mettre dans tes dict puisque tu recherches la présence d'une sous-chaine... Toutes les sous-chaines possibles et imaginables ? Qq chose m'échappe...

eric

Rechercher des sujets similaires à "structure dictionnaire"