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 :
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