Supprimer une ligne en double dans un fichier excel [Résolu]

Signaler
Messages postés
61
Date d'inscription
mardi 4 mai 2004
Statut
Membre
Dernière intervention
1 août 2007
-
Messages postés
6786
Date d'inscription
vendredi 16 décembre 2005
Statut
Membre
Dernière intervention
21 décembre 2011
-
Bonjour,

En fait c'est pas tout à fait une ligne en double que j'aimerais supprimer, mais plutôt renommer une ligne entière. Je m'explique, j'ai un fichier .csv de la forme suivante (c'est un exemple) :
                    colonne 1:      colonne 2 :       colonne 3 :  ..........
ligne 1 :          Date                 Time                Name
ligne 2 :      09-05-2007       15:50:10       "ABCDEFG"
ligne 3 :      09-05-2007       15:55:30       "ABCDEFG"
[....]

Je cherche un moyen de balayer ce fichier jusqu'à la dernière ligne écrite afin de trouver deux ou plusieurs fois le même nom (colonne 3), et d'ainsi de renommer la ligne entière par une nouvelle ligne mais avec le jour et/ou l'heure le plus récent.
En fait dans cet exemple, la ligne 3 viendra remplacer la ligne 2, car l'heure dans la ligne 3 (colonne 2) est la plus récente.

Comment pourrais-je faire au mieux ?

Merci

19 réponses

Messages postés
6786
Date d'inscription
vendredi 16 décembre 2005
Statut
Membre
Dernière intervention
21 décembre 2011
18
Pourquoi partir de la fin, tout simplement parce que si tu supprimes une ligne, les autres au dessous remontent, et c'est comme ça qu'on passe au travers de possibles doublons, car la valeur suivante est incrémentée de 1 (en partant du haut) et donc la valeur remontée n'est pas lu.

Je t'ai fait un code exemple basé sur ton exemple cité plus haut, inspire-en toi si tes données sont plus élargies (en terme de colonne)

Private Sub test()
    Dim i As Long, j As Long, DL As Long
    
For i =  2 To PLV
    DL = PLV
    For j = DL To i + 1 Step -1
        If Cells(i, 3).Value = Cells(j, 3).Value Then
            If Cells(j, 1).Value < Cells(i, 1).Value Then
                Rows(j).Delete
            ElseIf Cells(j, 1).Value > Cells(i, 1).Value Then
                Cells(i, 1).Value = Range(Cells(j, 1), Cells(j, 3)).Value
            Else
                If Cells(j, 2).Value <= Cells(i, 2).Value Then
                    Rows(j).Delete
                Else
                    Range(Cells(j, 1), Cells(j, 3)).Copy
                    Cells(i, 1).PasteSpecial (xlAll)
                    Rows(j).Delete
                End If
            End If
        End If
    Next j
Next i
End Sub

Private Function PLV() As Long
    PLV = Range("C65536").End(xlUp).Row
End Function

~ <small> Mortalino ~ Colorisation automatique </small>

@++

<hr width ="100%" size="2" />
  --Mortalino--
Le mystérieux chevalier, ~Provençal, le Gaulois~
  
Messages postés
6786
Date d'inscription
vendredi 16 décembre 2005
Statut
Membre
Dernière intervention
21 décembre 2011
18
Salut,

heu sans dire de bétise, la logique (enfin, la mienne) voudrait que la valeur en doublon la plus récente soit toujours placée plus bas que les autres, non?
 
** Si oui, c'est simple, tu lis C2, ensuite tu compares avec Cx (x étant la dernière ligne), en remontant d'une ligne jusqu'à trouver la même valeur.
Quand c'est trouvé, Tu copies la ligne vers A2:C2 (vu qu'on a lu C2, au début). Ensuite, tu remontes encore jusqu'à la ligne 3, et supprime les éventuels autres doublons.
Ainsi de suite, C3, C4;, etc..

** Si non, bah suffit de faire presque pareil, à la différence près que dès que tu as trouvé un doublon (en partant du bas, donc), tu compares d'abord la date, puis l'heure, et copie si le doublon est plus récent. Ainsi de suite

@++

<hr width="100%" size="2" />
  --Mortalino--
Le mystérieux chevalier, ~Provençal, le Gaulois~
  
Messages postés
61
Date d'inscription
mardi 4 mai 2004
Statut
Membre
Dernière intervention
1 août 2007

C'est plutôt la deuxième solution, mais pourquoi commencer du bas ?
Coment coder cela, puis-je utiliser sheets et rows ici, dslé je ne connais pas bien le VBA...
Merci encore.
Messages postés
61
Date d'inscription
mardi 4 mai 2004
Statut
Membre
Dernière intervention
1 août 2007

Comment puis-je utiliser du code VBA dans le compilateur IDE Visual Basic 6, ou bien l'adapter ?
Comment puis-je travailler ce fichier excel de la même façon qu'un fichier texte ? (do until EOF(1) ...)
Messages postés
61
Date d'inscription
mardi 4 mai 2004
Statut
Membre
Dernière intervention
1 août 2007

J'essaye d'utiliser la méthode ADO, à la place de FileSystemObject, d'après ce site : http://www.supinfo-projects.com/fr/2006/csv_vb6/3/
mais sans succès pour l'instant (j'ai une erreur d'exécution lié à Microsoft Jet)

Set objConnection = CreateObject("ADODB.Connection")
Set objRecordset = CreateObject("ADODB.Recordset")
strPathtoTextFile = "C:\Logfolder" 'ceci spécifie le chemin où les fichiers csv ce trouvent
objConnection.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
    "Data Source=" & strPathtoTextFile & ";" & _
    "Extended Properties=""text;HDR=YES;FMT=Delimited"""



objRecordset.Open "SELECT * FROM Log_LP_09.05.2007.csv", objConnection



Do Until objRecordset.EOF
    Wscript.Echo "colonne 3: " & objRecordset.Fields.Item("colonne 3")
       objRecordset.MoveNext
Loop

Une idée ?
Messages postés
3877
Date d'inscription
mardi 19 mars 2002
Statut
Membre
Dernière intervention
23 août 2018
18
Pour ce que tu veux faire, je pense que le plus simple est d'importer ton fichier CSV dans Excel. De là, tu tries selon les critères nécessaires, à savoir la colonne 3 en premier, la colonne 2 en deuxième.

Ensuite, tu fais un peu comme Mortalino te disait.
En fait, comme ta liste est triée, tu n'as pas besoin de faire une double-boucle.
Tu pars de la fin et tu remontes en vérifiant si Cx = Cx - 1
Si oui, tu vérifies si Bx > Bx - 1
Si oui, ben là c'est pas clair... si tu remplaces la plus vieille heure par la plus récente, qu'est-ce que tu fais de l'autre qui devient identique ???

Si tu la supprimes, alors ça ne sert à rien de la remplacer; supprime la plus vieille heure immédiatement.

De toute façon, ton code avec WScript.Echo, je ne pense pas que ça pourra t'aider... à moins que tu n'aies pas tout dit...

Et ADO, je l'ai déjà expérimenté avec Excel et des fichiers textes (un peu comme des CSV finalement...), mais ça prenait un fichier "Schema.ini" qui contient la structure du fichier pour qu'ADO comprenne ce fichier comme si c'était une base de données (nom des colonnes et type de ces colonnes). Cette technique est intéressante si tu veux aller chercher seulement certains renseignements dans un fichier, mais pas pour le traiter comme tu veux le faire, je pense...

MPi
Messages postés
61
Date d'inscription
mardi 4 mai 2004
Statut
Membre
Dernière intervention
1 août 2007

Si oui, ben là c'est pas clair... si tu remplaces la plus vieille heure
par la plus récente, qu'est-ce que tu fais de l'autre qui devient
identique ???



En fait, ce n'est pas juste une colonne que j'aimerais remplacer, mais la ligne entière en fait. Dans mon exemple, la L3 remplace la L2.
Quand tu dis importer le fichier dans excel, ça voudrais dire à chaque fois, pour chaque fichier éxécuter une macro ?
Le problème, c'est que j'ai des centaines de fichiers csv comme ceci, avec des centaines de lignes chacun. C'est pour cela que je voulais passer par VB6 et non VBA.

Pour le ADO, en effet, je ne pourrais que lire et non écrire, sinon faut que je passe par le filesystemobject, mais je ne sais pas comment je peut lire les cellules (y aller ligne par ligne, et dès qu'il y a un doublon, remplacer par celui par celui dont la date est plus récente ?).
J'avoue que c'est pas simple.
Merci encore.
Messages postés
3877
Date d'inscription
mardi 19 mars 2002
Statut
Membre
Dernière intervention
23 août 2018
18
Dans ce que tu dis, je ne vois pas l'utilité de passer par VB6 plutôt que VBA6, à moins qu'il y ait encore confusion entre VB6 et VB d'Excel (VBA6)...

Ce qu'il y a de simple avec Excel, c'est que tu peux importer ton fichier directement dans une feuille, trier les données et supprimer les doublons non-nécessaires dans une simple boucle.

Si tu ne veux pas passer par le copier/coller dans une feuille, il te faudra utiliser des variables String pour stocker ton fichier, utiliser Split pour lire chaque donnée de chaque ligne pour pouvoir comparer les heures, réécrire le fichier après suppression des lignes, ... et j'en oublie sûrement ...

C'est certainement faisable, mais je trouve ça bien compliqué par rapport au copier/coller dans Excel

MPi
Messages postés
61
Date d'inscription
mardi 4 mai 2004
Statut
Membre
Dernière intervention
1 août 2007

Le fichier csv créé est toujours le même et est renommé en fonction de la date du jour. Chaque fois que l'utilisateur lance mon logiciel, des nouvelles données sont rajoutés à la fin du fichier (j'utilise for append as).

Et ce que je voulais faire, c'est éviter des doublons, et cela sans passer par excel.
Mais le soucis, c'est ce qu'il y a dans les colonnes change.
Est-ce qu'il y a un moyen d'inclure dans le fichier csv en question une macro VBA6 qui s'exécute automatiquement lorqu'on ouvre le fichier avec excel (éviter toute manipulation) ?
Messages postés
61
Date d'inscription
mardi 4 mai 2004
Statut
Membre
Dernière intervention
1 août 2007

J'ai trouvé ce code, de Trolix : http://www.vbfrance.com/codes/IMPORTER-EXPORTER-AVEC-EXCEL_3673.aspx.

Y a-t-il moyen d'adapter ton code mortalino directement dans VB6 (et non VBA6) en utilisant "Microsoft Excel 10.0 Object Library" par exemple ?
Messages postés
6786
Date d'inscription
vendredi 16 décembre 2005
Statut
Membre
Dernière intervention
21 décembre 2011
18
Salut,

oui, c'est adaptable.  Je test pas mais en gros :

Private Sub test()
    Dim i As Long, j As Long, DL As Long
   Dim xlApp As New Excel.Application
   Dim xlBook As Excel.WorkBook
   Dim xlSheet As Excel.WorKSheet

Set xlBook = xlApp.WorkBooks.Open("C:\chemin\nomfichier.xls")
Set xlSheet = xlBook.Sheets("Nom Feuille")

For i = 2 To PLV
    DL = PLV
    For j = DL To i + 1 Step -1
        If xlSheet.Cells(i, 3).Value = xlSheet.Cells(j, 3).Value Then
            If xlSheet.Cells(j, 1).Value < xlSheet.Cells(i, 1).Value Then
                xlSheet.Rows(j).Delete
            ElseIf xlSheet.Cells(j, 1).Value > xlSheet.Cells(i, 1).Value Then
                xlSheet.Cells(i, 1).Value = xlSheet.Range(xlSheet.Cells(j, 1), xlSheet.Cells(j, 3)).Value
            Else
                If xlSheet.Cells(j, 2).Value <= xlSheet.Cells(i, 2).Value Then
                    xlSheet.Rows(j).Delete
                Else
                    xlSheet.Range(xlSheet.Cells(j, 1), xlSheet.Cells(j, 3)).Copy
                    xlSheet.Cells(i, 1).PasteSpecial (xlAll)
                    xlSheet.Rows(j).Delete
                End If
            End If
        End If
    Next j
Next i
End Sub

Private Function PLV() As Long
    PLV = xlSheet.Range("C65536").End(xlUp).Row
End Function

Pense à cocher la référence à Excel
@++

<hr width="100%" size="2" />
  --Mortalino--
Le mystérieux chevalier, ~Provençal, le Gaulois~
  
Messages postés
61
Date d'inscription
mardi 4 mai 2004
Statut
Membre
Dernière intervention
1 août 2007

Cette ligne ne passe pas : PLV = xlSheet.Range("C65536").End(xlUp).Row





Il me dit Object Required. Pourtant J'ai pas oublier la référence !?
Messages postés
6786
Date d'inscription
vendredi 16 décembre 2005
Statut
Membre
Dernière intervention
21 décembre 2011
18
Dans
Set xlSheet = xlBook.Sheets("Nom Feuille")

t'as bien changé le nom de la feuille ?

@++

<hr size="2" width="100%" />
  --Mortalino--
Le mystérieux chevalier, ~Provençal, le Gaulois~
  
Messages postés
61
Date d'inscription
mardi 4 mai 2004
Statut
Membre
Dernière intervention
1 août 2007

En fait, mon fichier, c'est un .csv et le "Nom Feuille" correspond au nom du fichier. Peut-être est-ce le CSV qui pose soucis ?
Messages postés
6786
Date d'inscription
vendredi 16 décembre 2005
Statut
Membre
Dernière intervention
21 décembre 2011
18
Si t'as qu'une seule feuille, supprime le Set xlSheet...
Et dans le code, remplace les tous (les xlSheet) par xlBook

Après, je pense pas que le fait que ce soit un CSV pose problème, l'avantage, c'est qu'on peut le traiter comme un XLS

@++

<hr size="2" width="100%" />
  --Mortalino--
Le mystérieux chevalier, ~Provençal, le Gaulois~
  
Messages postés
61
Date d'inscription
mardi 4 mai 2004
Statut
Membre
Dernière intervention
1 août 2007

En fait, c'est plutôt cette ligne qui pose soucis : Set xlBook = xlApp.WorkBooks.Open("C:\chemin\nomfichier.xls")


Il n'y a pas de valeur retournée dans xlBook (runtime error). Par contre xlApp, pas de soucis.
Porrais-tu vérifier si t'y arrive de ton côté.
Je peux t'envoyé mon fichier csv si tu veux.
Merci encore.
Messages postés
6786
Date d'inscription
vendredi 16 décembre 2005
Statut
Membre
Dernière intervention
21 décembre 2011
18
Il faut que tu remplaces dans
xlApp.WorkBooks.Open("C:\chemin\nomfichier.xls")
le chemin et le nom du fichier, style
xlApp.WorkBooks.Open("C:\documents and settings\mortalino\Bureau\Test.csv")

@++

<hr size="2" width="100%" />
  --Mortalino--
Le mystérieux chevalier, ~Provençal, le Gaulois~
  
Messages postés
61
Date d'inscription
mardi 4 mai 2004
Statut
Membre
Dernière intervention
1 août 2007

Quand même je sais que je suis débutant, mais quand même !
L'erreur retournée quand le compilateur arrive sur  PLV = ..... est "Object doesn't support this property or method" due sans doute parce qu'il n'arrive pas à lire le fichier.
J'utilise Excel 2007 (référence Microsoft Object 12.0) ...
Messages postés
6786
Date d'inscription
vendredi 16 décembre 2005
Statut
Membre
Dernière intervention
21 décembre 2011
18
C'est bon j'ai trouvé, je viens de tester avec Excel 2007

   Dim xlSheet As Excel.WorKSheet

enlève le de la procédure, et place le dans les déclarations, au tout début. Sinon, xlSheet n'est accessible que dans la procédure, et pas dans la fonction

@++

<hr size="2" width="100%" />
  --Mortalino--
Le mystérieux chevalier, ~Provençal, le Gaulois~