Un tableau de Dictionnaire

8 réponses
Avatar
FdeCourt
Bonjour tous le monde,

J'essaye d'utiliser VBA pour travailler sur de tr=E8s gros fichiers
textes (plusieurs millions de ligne). Je n'ai pas Access, et ne
pourrait pas l'avoir.

Donc pour palier ce probl=E8me, je me suis attel=E9 =E0 ce travaille en VBA=
.

Mon but premier est d'identifier tous les doublons dans un fichier.
Pour cela j'utilise un dictionnaire, mais tr=E8s vite, cela rame
terriblement, et =E0 partir de 2,5 millions de ligne, j'ai l'impression
que mon dictionnaire est r=E9initialis=E9.
Pour =E9viter cela, j'essaye de cr=E9er un tableau contenant de multiple
sous dictionnaires :

Dim tablo()
Set oFSO =3D CreateObject("Scripting.FileSystemObject")
Path =3D ThisWorkbook.Path

fichier1 =3D Path & "\DONNEES\Fichier_" & Version1 & ".csv"


Set oDictTmp =3D CreateObject("Scripting.Dictionary")
Set oFile =3D oFSO.OpenTextFile(fichier1, ForReading)
xx =3D -1

Do Until oFile.AtEndOfStream
i =3D i + 1

strName =3D oFile.ReadLine
oDictTmp.Add strName, ""

If i Mod LimitTablo =3D 0 Then

xx =3D xx + 1

ReDim Preserve tablo(O To xx)
Set tablo(xx) =3D oDictTmp '<<<Toutes les =E9l=E9ments avant X
prennent le m=EAme contenu

oDictTmp.RemoveAll '<<<<Tout se supprime dans Tablo

End If

Loop

Le probl=E8me est que toutes les =E9l=E9ments de mon tableau semblent
toujours li=E9s au contenu de oDictTmp, ainsi, lorsque je le vide, tous
les =E9l=E9ments de mon tableau Tablo se vide, et quand je le remplis,
tous les =E9l=E9ments avant XX se remplissent avec les m=EAmes valeurs (le
contenu de oDictTmp).

Comment pourrais-je r=E9soudre ceci (sans Access, ou OpenOffice, ou
autre, ce n'est pas installable) ?

Merci pour votre aide

Cordialement,

F.

8 réponses

Avatar
MichD
Bonjour,

Dans ton fichier .CSV, tu as combien de colonnes ?

Est-ce que ton fichier contient des étiquettes de colonnes en première ligne ?

Quelle est la définition de "doublon" dans ton fichier ? Est-ce chaque champ de chaque colonne d'une ligne doit être
identique à chaque champ d'une autre ligne ou si seulement UN ou 2 champs spécifiques identiques forment un doublon.

Lorsque tu identifies un doublon, que veux-tu faire ? Le mettre dans un autre fichier ? Le supprimer ?

Que veux-tu obtenir à la fin ? Un fichier épuré de ses doublons ? Un fichier contenant seulement les doublons ? Autre chose ?

Et si tu veux faire ça en vba, une suggestion, prends le temps de déclarer adéquatement tes variables et leur type !



MichD
------------------------------------------
"FdeCourt" a écrit dans le message de groupe de discussion :


Bonjour tous le monde,

J'essaye d'utiliser VBA pour travailler sur de très gros fichiers
textes (plusieurs millions de ligne). Je n'ai pas Access, et ne
pourrait pas l'avoir.

Donc pour palier ce problème, je me suis attelé à ce travaille en VBA.

Mon but premier est d'identifier tous les doublons dans un fichier.
Pour cela j'utilise un dictionnaire, mais très vite, cela rame
terriblement, et à partir de 2,5 millions de ligne, j'ai l'impression
que mon dictionnaire est réinitialisé.
Pour éviter cela, j'essaye de créer un tableau contenant de multiple
sous dictionnaires :

Dim tablo()
Set oFSO = CreateObject("Scripting.FileSystemObject")
Path = ThisWorkbook.Path

fichier1 = Path & "DONNEESFichier_" & Version1 & ".csv"


Set oDictTmp = CreateObject("Scripting.Dictionary")
Set oFile = oFSO.OpenTextFile(fichier1, ForReading)
xx = -1

Do Until oFile.AtEndOfStream
i = i + 1

strName = oFile.ReadLine
oDictTmp.Add strName, ""

If i Mod LimitTablo = 0 Then

xx = xx + 1

ReDim Preserve tablo(O To xx)
Set tablo(xx) = oDictTmp '<<<Toutes les éléments avant X
prennent le même contenu

oDictTmp.RemoveAll '<<<<Tout se supprime dans Tablo

End If

Loop

Le problème est que toutes les éléments de mon tableau semblent
toujours liés au contenu de oDictTmp, ainsi, lorsque je le vide, tous
les éléments de mon tableau Tablo se vide, et quand je le remplis,
tous les éléments avant XX se remplissent avec les mêmes valeurs (le
contenu de oDictTmp).

Comment pourrais-je résoudre ceci (sans Access, ou OpenOffice, ou
autre, ce n'est pas installable) ?

Merci pour votre aide

Cordialement,

F.
Avatar
Yopop
Bonjour,

En complément de la réponse de MichD, La méthode que j'emploierai serait
de faire une feuille par premier caractère, puis dans chaque feuille,
une colonne en fonction du second caractère.

puis :

strName = oFile.ReadLine

myWSH = Asc(UCase(Left(strName, 1))) - 64
myCol = Mid(strName, 2, 1)
dern = Worksheets(myWSH).Range(myCol & "65535").End(xlUp).Row + 1
plg = Worksheets(myWSH).Name & "!" & myCol & "1" & ":" & myCol & dern
exist = Evaluate("=match(""" & strName & """," & plg & ",0)")
If IsError(exist) Then
Worksheets(myWSH).Range(myCol & dern).Value = strName
Else
'ici procedure de traitement du doublon
End If


A adapter si il y a autre chose que des caractères alphabétiques.
Mais ca risque d'etre long quand meme.
Je ne sait pas si on y gagnerait à faire la meme chose avec un tableau
en mémoire, mais pour trouver si il y a un doublon, on serait obligé de
faire une boucle et c'est encore plus chronophage a mon avis.

j-p
Avatar
FdeCourt
On 1 déc, 05:57, Yopop wrote:
Bonjour,

En compl ment de la r ponse de MichD, La m thode que j'emploierai serait
de faire une feuille par premier caract re, puis dans chaque feuille,
une colonne en fonction du second caract re.

puis :

     strName = oFile.ReadLine

     myWSH = Asc(UCase(Left(strName, 1))) - 64
     myCol = Mid(strName, 2, 1)
     dern = Worksheets(myWSH).Range(myCol & "65535").End(xlUp).Ro w + 1
     plg = Worksheets(myWSH).Name & "!" & myCol & "1" & ":" & myC ol & dern
     exist = Evaluate("=match(""" & strName & """," & plg & ",0 )")
     If IsError(exist) Then
         Worksheets(myWSH).Range(myCol & dern).Value = strNam e
     Else
         'ici procedure de traitement du doublon
     End If

A adapter si il y a autre chose que des caract res alphab tiques.
Mais ca risque d'etre long quand meme.
Je ne sait pas si on y gagnerait faire la meme chose avec un tableau
en m moire, mais pour trouver si il y a un doublon, on serait oblig de
faire une boucle et c'est encore plus chronophage a mon avis.

j-p



Bonjour Yopop,

J'ai essayé sous Excel, mais c'est totalement inexploitable ! Ca à
tourné pendant 2 jours pour planter au final ! Rien que l"import à
pris plus de 2 heures !
Ensuite j'ai plein d'opérations de transformation de ce fichier; à
partir d'autre fichiers, que j'insert dans d'autres fichiers CSV.
Je cherche à tout mettre en mémoire parce que c'est infiniment plus
rapide. J'ai testé en faisant des fichiers plus petits d'un million de
lignes que j'insert dans un seul dictionnaire, et tout mon programme
fonctionne correctement. C'est vraiment à partir de 2,5 millions de
lignes que ça plante, d'ou mon idée de créer plusieurs petits
dictionnaires, que j'insert dans un tableau, pour ensuite pouvoir
boucler sur ce tableau, puis sur chaque dictionnaire inséré.

Cordialement,

F.
Avatar
FdeCourt
Bonjour MichD,

Merci pour ta réponse. Il y a beaucoup de traitement ensuite de
transformation/ modification, en fonction de critères contenu dans
d'autres fichiers.
Pour répondre à toutes tes questions
Mon fichier ne contient pas d'entête.
Dans ce fichier, toutes les valeurs sont uniques, mais je le compare à
un autre fichier, par rapport à toute la ligne et non pas un champ
spécifique (j'ai déjà en VBA l'identification des doublons sur les 23
premiers caractères, et avec un seul dictionnaire, cela fonctionne,
puisque je créé un dictionnaire de bien plus petite taille).
Sinon, en sortie de mes traitements, j'ai plusieurs fichiers avec mes
données transformées.

J'
On 30 nov, 23:20, "MichD" wrote:
Bonjour,

Dans ton fichier .CSV, tu as combien de colonnes ?

Est-ce que ton fichier contient des étiquettes de colonnes en premièr e ligne ?

Quelle est la définition de "doublon" dans ton fichier ?  Est-ce chaq ue champ de chaque colonne d'une ligne doit être
identique à chaque champ d'une autre ligne ou si seulement UN ou 2 cham ps spécifiques identiques forment un doublon.

Lorsque tu identifies un doublon, que veux-tu faire ? Le mettre dans un a utre fichier ? Le supprimer ?

Que veux-tu obtenir à la fin ? Un fichier épuré de ses doublons ? U n fichier contenant seulement les doublons ? Autre chose ?

Et si tu veux faire ça en vba, une suggestion, prends le temps de déc larer adéquatement tes variables et leur type !

MichD
Avatar
FdeCourt
On 1 déc, 09:48, FdeCourt wrote:
Bonjour MichD,

Merci pour ta réponse. Il y a beaucoup de traitement ensuite de
transformation/ modification, en fonction de critères contenu dans
d'autres fichiers.
Pour répondre à toutes tes questions
Mon fichier ne contient pas d'entête.
Dans ce fichier, toutes les valeurs sont uniques, mais je le compare à
un autre fichier, par rapport à toute la ligne et non pas un champ
spécifique (j'ai déjà en VBA l'identification des doublons sur les 23
premiers caractères, et avec un seul dictionnaire, cela fonctionne,
puisque je créé un dictionnaire de bien plus petite taille).
Sinon, en sortie de mes traitements, j'ai plusieurs fichiers avec mes
données transformées.

J'


... oups erreur de manip !

Donc j'écrivais : j'ai essayé sur des fichiers de plus petites
tailles, et cela fonctionne correctement. A partir de 2,5 millions de
ligne, mon dictionnaire ne fonctionne plus ! c'est pourquoi je voulais
faire une boucle et insérer ces différents dictionnaires de plus
petite taille dans un tableau, puis ensuite boucler sur ce tableau.
Mais le problème et que les dictionnaires contenus dans ce tableau
contiendrons toujours les mêmes valeurs.

Sinon, toutes mes variables sont bien correctement déclarées ;)

Merci pour votre aide.

Cordialement,

F.
Avatar
FdeCourt
On 1 déc, 09:48, FdeCourt wrote:
Bonjour MichD,

Merci pour ta réponse. Il y a beaucoup de traitement ensuite de
transformation/ modification, en fonction de critères contenu dans
d'autres fichiers.
Pour répondre à toutes tes questions
Mon fichier ne contient pas d'entête.
Dans ce fichier, toutes les valeurs sont uniques, mais je le compare à
un autre fichier, par rapport à toute la ligne et non pas un champ
spécifique (j'ai déjà en VBA l'identification des doublons sur les 23
premiers caractères, et avec un seul dictionnaire, cela fonctionne,
puisque je créé un dictionnaire de bien plus petite taille).
Sinon, en sortie de mes traitements, j'ai plusieurs fichiers avec mes
données transformées.

J'



Oups double erreur de manip !
J'écrivais : J'ai essayer avec des fichiers de plus petite taille, et
cela fonctionne très bien. Le problème viendrais de dico trop
volumineux, c'est pourquoi j'essaye de les splitter dans un tableau

Cordialement,

F.
Avatar
MichD
Bonjour,

Voici un exemple scindant ton fichier principale en un
tableau de dictionnaires contenant 500 000 lignes possibles.

La grosseur des dictionnaires t'appartient...Je n'ai pas testé...
Est-ce plus rapide plus de petits dictionnaires que quelques gros dictionnaires ?

Tu dois ajouter la référence "Microsoft Scripting Runtime" à ton projetVBA

'---------------------------------------------------
Sub test()
'Microsoft Scripting Runtime
Dim T() As Dictionary, Chemin, Fichier, A As Integer
Dim LaLigne As String, B As Long, X As Long, Temp As String
Dim SansDoublon As String, Nb As Long, FicherAcomparer As String

'Section scinder le fichier principale en tableau de dictionnaires
'J'ai supposé que les fichiers sont dans le même répertoire
'
Chemin = "c:UsersTon ProfilDocuments"
Fichier = "toto.csv" 'Le gros fichier à scinder
FicherAcomparer = "Bozo.csv" 'Fichier de comparaison

X = FreeFile

Open Chemin & Fichier For Binary Access Read As #X
Do While Not EOF(X)
Nb = Nb + 1
'Crée un nouveau tableau à chaque 500000 lignes
'à toi de décider de la grosseur des dictionnaires
If Nb Mod 500000 = 1 Then
A = A + 1
ReDim Preserve T(1 To A)
Set T(A) = New Dictionary
End If
Input #X, LaLigne
'Si la ligne n'existe pas dans le dictionnaire
If Not T(A).Exists(LaLigne) Then
'elle est ajoutée
T(A).Add LaLigne, CStr(Nb)
'La variable SansDoublon doit contenu un fichier
'sans doublon que l'on pourra enregistrer...
SansDoublon = SansDoublon & LaLigne & vbCrLf
Else
'sinon elle est placée dans une variable
Temp = Temp & LaLigne & vbCrLf
'Debug.Print Temp
End If
Loop
'Ferme le fichier principale
Close #X
'Enregistre le contenu de la SansDoublon et temp
'seulement si temp a au moins une entrée
If Temp <> "" Then
Open Chemin & "SansDoublon_" & Fichier & ".csv" For Output As #X
Print #X, Temp
Close #X
'Enregistre un fichier de doublons si cela existe
Open Chemin & "Doublons_" & Fichier & ".csv" For Output As #X
Print #X, Temp
Close #X
End If

'Vide les variables Temp, SansDoublon, LaLigne
SansDoublon = ""
Temp = ""
LaLigne = ""

'Ici on doit avoir en en mémoire un tableau de dictionnaire
'contenant le fichier principale sans doublon

'Ouverture du fichier de comparaison

Open Chemin & FicherAcomparer For Binary Access Read As #X
Do While Not EOF(X)
Input #X, LaLigne
'Si la ligne du fichier à comparer existe dans un
'des tableaux, il est entré dans la variable Temp
For A = LBound(T) To UBound(T)
If T(A).Exists(LaLigne) Then
Temp = Temp & LaLigne & vbCrLf
End If
Next
Loop
Close #X

'à la fin du traitement du fichier,
'enregistre la variable Temp contenant les doublons
Open Chemin & "Doublons_" & Fichier & ".csv" For Output As #X
Print #X, Temp
Close #X
End Sub
'---------------------------------------------------


MichD
------------------------------------------
"FdeCourt" a écrit dans le message de groupe de discussion :


Bonjour MichD,

Merci pour ta réponse. Il y a beaucoup de traitement ensuite de
transformation/ modification, en fonction de critères contenu dans
d'autres fichiers.
Pour répondre à toutes tes questions
Mon fichier ne contient pas d'entête.
Dans ce fichier, toutes les valeurs sont uniques, mais je le compare à
un autre fichier, par rapport à toute la ligne et non pas un champ
spécifique (j'ai déjà en VBA l'identification des doublons sur les 23
premiers caractères, et avec un seul dictionnaire, cela fonctionne,
puisque je créé un dictionnaire de bien plus petite taille).
Sinon, en sortie de mes traitements, j'ai plusieurs fichiers avec mes
données transformées.

J'
On 30 nov, 23:20, "MichD" wrote:
Bonjour,

Dans ton fichier .CSV, tu as combien de colonnes ?

Est-ce que ton fichier contient des étiquettes de colonnes en première ligne ?

Quelle est la définition de "doublon" dans ton fichier ? Est-ce chaque champ de chaque colonne d'une ligne doit être
identique à chaque champ d'une autre ligne ou si seulement UN ou 2 champs spécifiques identiques forment un doublon.

Lorsque tu identifies un doublon, que veux-tu faire ? Le mettre dans un autre fichier ? Le supprimer ?

Que veux-tu obtenir à la fin ? Un fichier épuré de ses doublons ? Un fichier contenant seulement les doublons ? Autre chose
?

Et si tu veux faire ça en vba, une suggestion, prends le temps de déclarer adéquatement tes variables et leur type !

MichD
Avatar
FdeCourt
Bonsoir MichD,

Exactement ce que je cherchais à faire, mais en utilisant une très
mauvaise logique.
C'est l'absence de déclaration de chaque élément de mon tableau en
dico qui m'empêchait d'avancer (Set T(A) = New Dictionary )

Mille mercis !!!

Je regarde les effets sur les perfs et te tiens au courant (plein de
petits dicos, ou peu de très gros)

Cordialement,

F.