IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

VB.NET Discussion :

Optimisation de code vb.net Excel vers txt


Sujet :

VB.NET

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 6
    Points : 2
    Points
    2
    Par défaut Optimisation de code vb.net Excel vers txt
    bonjour à tous,
    voila, j'ai fais une petite appli qui merge les onglets d'une liste de fichiers excel à la structure identique dans des fichiers textes

    xl1.feuil1 + xl2.feuil1 + ... => txt1
    xl1.feuil2 + xl2.feuil2 + ... => txt2
    xl1.feuil3 + xl2.feuil3 + ... => txt3
    xl1.feuil4 + xl2.feuil4 + ... => txt4


    le programme marche mais met environs 10h pour merger 200 fichiers de 3Mo!!
    chaque feuille excel contient environ 8000 lignes et j'utilise un worksheet.range pour copier les données et un streamwriter.writeline pour les écrire dans le fichier texte.
    je pense que le problème vient de la car il semblerais qu'il n'écrivent qu'une petite trentaine de ligne à la seconde!!!
    voici mon code:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
     
    #Région "Processing"
     
        Private Sub pXLMerger(ByVal strInputDir As String, ByVal stroutputDir As String)
            'variables "classiques"
            Dim iMaxSheet, iCountSheet, iCountRangeLines As Integer
            Dim bFirstFile As Boolean
            Dim strLastRangeCol, strLine As String
     
            'variables "fichier"
            Dim swTxt(4) As StreamWriter
            Dim fiFile As IO.FileInfo
     
            'variables "Excel"
            Dim appXL As New Excel.Application
            Dim xlsInputWorkBook As Excel.Workbook
            Dim xlsInputWorkSheet As Excel.Worksheet
            Dim xlsInputRangeData As Excel.Range
     
     
            'afin de supprimer les entete de colonnes sur les fichiers suivant le premier,
            'un booléen flag le premier fichier
            bFirstFile = True
     
            'initialisation des variables
            strLastRangeCol = ""
            iCountRangeLines = 0
            'lancement d'Excel en background
            appXL.Visible = False
     
            'instanciation des StreamWriter et suppression des fichiers existant
            For i = 1 To 4
                'récupération des info des fichiers textes si existant
                Dim fOutputFile As New FileInfo(stroutputDir & "_" & i & ".txt")
                'suppression des fichiers existants
                If fOutputFile.Exists Then fOutputFile.Delete()
                'instanciation des flux d'ecritures
                swTxt(i) = New StreamWriter(stroutputDir & "_" & i & ".txt", False)
     
            Next
     
            'info sur le répertoire contenant les fichiers
            Dim fExploitFolderExistance As New IO.DirectoryInfo(strInputDir)
            'liste des fichiers excel à 'merger'
            Dim afiFileList As IO.FileInfo() = fExploitFolderExistance.GetFiles("*.xls")
     
     
            'boucle de copie des données 
            For Each fiFile In afiFileList
                'ouverture du fichier xls
                xlsInputWorkBook = appXL.Workbooks.Open(fiFile.FullName)
                'compte le nombre d'onglet du fichier
                iMaxSheet = xlsInputWorkBook.Sheets().Count
                'info pour la pgbar
                iTotalProcessedFiles += 1
     
                'boucle par feuille
                For iCountSheet = 1 To iMaxSheet
     
                    'selection de la feuille à traiter
                    xlsInputWorkSheet = xlsInputWorkBook.Worksheets(iCountSheet)
     
                    'je n'ai pas besoin de copier le contenus des feuilles cachées (d'ailleurs le programme plante si j'essai de copier leur contenus)
                    If xlsInputWorkSheet.Visible = Excel.XlSheetVisibility.xlSheetVisible Then
     
                        'activation de la feuille
                        xlsInputWorkSheet.Activate()
     
                        'ici une sous-routine compte le nombre effectife de ligne et de colonne avec des données
                        'car une propriété telle que xlsInputWorkSheet.Rows.Count me donne 65536 soit le nombre max de lignes d'un fichier
                        'au total ces opérations prennent 2 ou 3 secondes par feuille
                        strLastRangeCol = fColCount(xlsInputWorkSheet)
                        iCountRangeLines = fRowCount(xlsInputWorkSheet)
     
                        'on verifie que la feuille n'est pas vide
                        'getcolumn me retourne "Z" si le nombre de colonne est  = 0 ou 26 (a cause du modulo)
                        If Not ((strLastRangeCol = "Z") And (iCountRangeLines = 0)) Then
     
                            'selon si l'on est entrain de le premier fichier ou les suivants la copie 
                            'ne commence pas à la même ligne
                            If bFirstFile = True Then
                                xlsInputRangeData = xlsInputWorkSheet.Range("A1", strLastRangeCol & iCountRangeLines)
                            Else
                                xlsInputRangeData = xlsInputWorkSheet.Range("A2", strLastRangeCol & iCountRangeLines)
                            End If
     
                            'maintenant on copie les ligne et c'est la que ca prend du temps
                            'je boucle sur chaque ligne du range
                            For i = 1 To xlsInputRangeData.Rows.Count
                                'initialisation de la chaine qui va recevoir la valeur de la ligne
                                strLine = ""
     
                                'ici le boucle sur chaque cellulle du range par colonne
                                For j = 1 To xlsInputRangeData.Columns.Count
     
                                    'incrémentation de la chaine qui sera copiée dans le fichier texte
                                    strLine += xlsInputRangeData(i, j).value & Chr(9)
     
                                Next
     
                                'copie de la chaine dans le fichier texte correspondant
                                swTxt(iCountSheet).WriteLine(strLine.Substring(0, strLine.Length - 1))
                            Next
                        End If
                    End If
     
                Next iCountSheet
     
                'si c'est le premier fichier qui vient d'etre traiter on change le flag
                If bFirstFile = True Then bFirstFile = False
                'une fois le fichier entierement traiter on le ferme
                xlsInputWorkBook.Close()
     
            Next
     
            'une fois tous les fichiers traiter on fermer les flux d'ecriture un par un
            For i = 1 To 4
                swTxt(i).Close()
            Next
     
            'puis on ferme excel (ici ca ne semble pas marché car bien qu'aucune erreur ne remonte,
            'excel.exe reste lister dans le gestionnaire des taches, une idée peut-etre?)
            appXL.Quit()
     
        End Sub
     
     
        'une simple fonction qui revoie une lettre (ou une suite de lettre) quand on lui fournis un chiffre
        Function GetColumn(ByVal aValue As Long) As String
     
            If aValue Mod 26 = 0 Then
                If aValue = 26 Or aValue = 0 Then
                    GetColumn = "Z"
                Else
                    GetColumn = Chr(64 + (aValue \ 26 - 1)) & GetColumn(aValue Mod 26)
                End If
            Else
                If aValue < 26 Then
                    GetColumn = Chr(64 + aValue)
                Else
                    GetColumn = Chr(64 + (aValue \ 26)) & GetColumn(aValue Mod 26)
                End If
     
            End If
        End Function
     
     
        'une fonction qui compte le nombre de lignes effectives d'une feuille excel
        Private Function fRowCount(ByRef xlWorkSheet As Excel.Worksheet) As Long
            Dim bSheetEnd As Boolean
     
            'flag pour la fin du fichier
            'on peut s'en passer mais il permet de continuer de compter si il y a une ligne vide
            bSheetEnd = False
     
            For fRowCount = 1 To 65336
     
                If xlWorkSheet.Range("A" & fRowCount).Value = "" Then
                    If bSheetEnd = False Then
                        bSheetEnd = True
     
                    Else
                        Exit For
                    End If
                End If
            Next
     
            Return fRowCount - 2
     
        End Function
     
        'fonction qui compte le nombre effectif de colonne d'une feuille excel
        Private Function fColCount(ByRef xlWorkSheet As Excel.Worksheet) As String
            Dim bSheetEnd As Boolean
            Dim iColCount As Integer
     
            'idem fRowCount, permet de compte une colonne vide
            bSheetEnd = False
     
            For iColCount = 1 To 65336
                If xlWorkSheet.Cells(1, iColCount).value = "" Then
                    If bSheetEnd = False Then
                        bSheetEnd = True
                    Else
                        Exit For
                    End If
                End If
            Next
     
            Return GetColumn(iColCount - 2)
     
        End Function
     
    #End Region


    Code fonctionnel en fin de thread

  2. #2
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 177
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 177
    Points : 25 125
    Points
    25 125
    Par défaut
    je suppose que strLine est un string, auquel cas je te conseille le stringbuilder, bien plus performant pour de la concaténation

    ensuite pour voir ce qui prend du temps, tu peux utiliser un system.diagnostics.stopwatch

    ensuite selon la partie qui réellement prend du temps on verra comment l'optimiser

  3. #3
    Candidat au Club
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 6
    Points : 2
    Points
    2
    Par défaut
    merci j'essaie ca de suite

  4. #4
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 177
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 177
    Points : 25 125
    Points
    25 125
    Par défaut
    de plus (j'ai pas trop envie de passer du temps à déchiffer le code) il faudrait nous dire comment tu procèdes

    par exemple moi je procéderai comme suit :

    boucle sur chaque fichier excel
    ouverture du fichier
    chargement des données du fichier excel dans une collection
    fermeture du fichier
    fin boucle

    définition d'une collection de stringbuilder

    boucle sur chaque collection
    traitement sur chaque feuille (enfin sur les collections de données associées)
    strinbuilder correspondant.append
    fin boucle

    boucle sur chaque stringbuilder
    system.io.file.appendalltext(fichier,stringbuilder.tostring)
    fin boucle

    ca permet de mieux délimiter chaque chose et chaque traitement, et aussi de voir avec plus de précision ce qui prend du temps (est ce que c'est la lecture dans excel (je vote là dessus), la concaténation, ou l'écriture des fichiers


    il serait peut etre aussi utile de faire du multithreading si tu as plusieurs core

  5. #5
    Candidat au Club
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 6
    Points : 2
    Points
    2
    Par défaut
    j'ai tester le stringbuilder et la string et je suis kifkif au niveau perf
    pour les 2 j'ai entre 100 et 110 lignes écrites à la seconde soit entre 1:15 et 1:20 pour écrire 8100 lignes (pour info je tourne sur un Intel Core 2 Quad Q9550 @ 2.83 GHz avec 4Go de RAM sous XP Pro et Vb.net 2008 Express et mon disque est un Barracuda 7200.11 SATA 3Gb/s NCQ 500GB 16MB Cache qui à 2 mois) et le temps ne semble pas dépendre du type utilisé (des fois la string est plus rapide que le stringbuilder et vice et versa) par contre comme je suis pas familier du stringBuilder je ne l'ai peut-être pas bien utiliser:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
     
    Private Sub pXLMerger(ByVal strInputDir As String, ByVal stroutputDir As String)
            'variables "classiques"
            Dim iMaxSheet, iCountSheet, iCountRangeLines As Integer
            Dim bFirstFile As Boolean
            Dim strLastRangeCol As String
            Dim strLine As New StringBuilder
     
            ...
     
            'maintenant on copie les ligne et c'est la que ca prend du temps
            'je boucle sur chaque ligne du range
            For i = 1 To xlsInputRangeData.Rows.Count
                    'initialisation de la chaine qui va recevoir la valeur de la ligne
                    strLine.Remove(0, strLine.Length)
     
                    'ici le boucle sur chaque cellulle du range par colonne
                    For j = 1 To xlsInputRangeData.Columns.Count
     
                            'incrémentation de la chaine qui sera copiée dans le fichier texte
                         strLine.Append(xlsInputRangeData(i, j).value & Chr(9))
                    Next
     
                    'copie de la chaine dans le fichier texte correspondant en supprimant le dernier caractere (tabulation devenu inutile)
                    swTxt(iCountSheet).WriteLine(strLine.Remove(strLine.Length - 1, 1).ToString)
            Next
     
            ...
    End Sub
    par contre les temps étant très petits, il est difficile de savoir qui prends le plus de temps, mais il semblerais que ce soit l'ecriture (0.01 sec contre 0.00 pour la construction de la chaine)

  6. #6
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 177
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 177
    Points : 25 125
    Points
    25 125
    Par défaut
    on dirait que tu as 4 boucles imbriquées, ma méthode de découpage permet une maintenance plus simple et permet de voir le temps de chaque partie
    parce que si tu fais un stopwatch sur un tour de la plus petite boucle, c'est clair que tu verras pas grand chose

    avec un quad core, le multithread permettrait de diviser le temps par 4

    enfin avoir plusieurs heures de traitement me parrait vraiment énorme, pour un truc dans le genre au dessus de 5min je me poserais des questions ... (certes ca dépend du volume de données, mais tu ne le précises pas ...)

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    444
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 444
    Points : 428
    Points
    428
    Par défaut
    Tu as fait des tests sur ta variable de rowmax pour voir si ça renvoyait bien environ 8000 et pas 65336 ?

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Août 2005
    Messages
    483
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 483
    Points : 309
    Points
    309
    Par défaut
    Bonjour,

    Je débute dans la gestion de fichier excel depuis vb.net.

    Par contre je vois que tu fais une recherche du nombre de ligne et de colonne dans ton fichier.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
     
     
    'une fonction qui compte le nombre de lignes effectives d'une feuille excel
        Private Function fRowCount(ByRef xlWorkSheet As Excel.Worksheet) As Long
            Dim bSheetEnd As Boolean
     
            'flag pour la fin du fichier
            'on peut s'en passer mais il permet de continuer de compter si il y a une ligne vide
            bSheetEnd = False
     
            For fRowCount = 1 To 65336
     
                If xlWorkSheet.Range("A" & fRowCount).Value = "" Then
                    If bSheetEnd = False Then
                        bSheetEnd = True
     
                    Else
                        Exit For
                    End If
                End If
            Next
     
            Return fRowCount - 2
     
        End Function
     
        'fonction qui compte le nombre effectif de colonne d'une feuille excel
        Private Function fColCount(ByRef xlWorkSheet As Excel.Worksheet) As String
            Dim bSheetEnd As Boolean
            Dim iColCount As Integer
     
            'idem fRowCount, permet de compte une colonne vide
            bSheetEnd = False
     
            For iColCount = 1 To 65336
                If xlWorkSheet.Cells(1, iColCount).value = "" Then
                    If bSheetEnd = False Then
                        bSheetEnd = True
                    Else
                        Exit For
                    End If
                End If
            Next
     
            Return GetColumn(iColCount - 2)
     
        End Function
    J'utilise personnellement cette méthode pour le déterminer :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
            Dim range As Excel.Range
            Dim colMax As Integer
            Dim ligneMax As Integer
     
            range = edSheet.UsedRange
            colMax = range.Columns.Count
            ligneMax = range.Rows.Count
    qui me renvoit le nombre de ligne et le nombre de colonne utilisé dans mon fichier excel.

    Je ne sais pas si cette méthode résoudra ton soucis.

    voilà voilà

    ++

  9. #9
    Candidat au Club
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 6
    Points : 2
    Points
    2
    Par défaut
    merci pour vos réponse,
    j'avance plutôt bien.

    @sperot51
    je ne suis pas très familier du multiThreading, je regarderai ca ce weekend sinon volumétrie j'ai 230 fichiers de 3Mo soit 690Mo de fichier à merger

    @ sphynxounet
    oui j'avais bien vérifier que ma variable comptais le nombre effectif de ligne.

    @narutobaka
    merci, je ne connaissais pas usedRange! donc du coup effectivement je n'ai pas besoin de faire un comptage manuel. merci d'ailleurs sont utilisation même après dans le traitement me fait gagné en gros 15s par fichier soit près d'une heure sur le total

  10. #10
    Membre averti
    Profil pro
    Inscrit en
    Août 2005
    Messages
    483
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 483
    Points : 309
    Points
    309
    Par défaut
    bonjour,

    voici ma source pour l'utilisation du range si ça peut aider :

    http://vb.net-informations.com/excel..._worksheet.htm

    Y d'autre élément utile pour la manipulation de fichier excel.

    ++

  11. #11
    Candidat au Club
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 6
    Points : 2
    Points
    2
    Par défaut
    donc finalement ce qui prends Beaucoup de temps (1minute par feuille excel) c'est la copie des données du range vers la stringbuilder.
    pour obtenir ce que j'ai besoin, je n'arrive pas à me passer de cette fichue double boucle qui parse le range cellulle par cellule pour les ajouter au stringbuilder
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
     
     
                For Each xlsInputUsedRange In xlsUsedRangeCol
     
                    iCountRangeCol = xlsInputUsedRange.Columns.Count
                    iCountRangeLines = xlsInputUsedRange.Rows.Count
                    strLastRangeCol = GetColumn(iCountRangeCol)
     
                        'differents test sur la validité du range
                        ...
     
                        'remise à zero de la stringbuilder
                        strLine(iCountSheet).Remove(0, strLine(iCountSheet).Length)
     
                        For i = iFirstLine To iCountRangeLines
                            'initialisation de la chaine qui va recevoir la valeur de la ligne
     
                            'ici le boucle sur chaque cellulle du range par colonne
                            For j = 1 To iCountRangeCol
     
                                'incrémentation de la chaine qui sera copiée dans le fichier texte
                                strLine(iCountSheet).Append(xlsInputUsedRange(i, j).value & Chr(9))
                            Next
     
                            'strLineCollection.Item(iCountSheet).append(xlsInputUsedRange("A" & i, GetColumn(iCountRangeCol) & i).value.ToString)
                            'copie de la chaine dans le fichier texte correspondant
                            strLine(iCountSheet).Remove(strLine(iCountSheet).Length - 1, 1).Append(Chr(13))
     
                        Next
                next
    y a t-il une différence de performance entre l'utilisation d'un tableau et d'une collection?

  12. #12
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 177
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 177
    Points : 25 125
    Points
    25 125
    Par défaut
    le dictionnary est très optimisé, les autres collections sont surtout plus pratique par rapport aux tableaux

    une autre chose à tenter, plutot que de parcourir les cellules du tableau excel, c'est de faire une selection et de faire copier, puis dans ton programme tu récupère ce qu'il y a dans le presse papier
    y a des chances que ca soit plus instantané

  13. #13
    Candidat au Club
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 6
    Points : 2
    Points
    2
    Par défaut
    Citation Envoyé par sperot51 Voir le message
    le dictionnary est très optimisé, les autres collections sont surtout plus pratique par rapport aux tableaux

    une autre chose à tenter, plutot que de parcourir les cellules du tableau excel, c'est de faire une selection et de faire copier, puis dans ton programme tu récupère ce qu'il y a dans le presse papier
    y a des chances que ca soit plus instantané
    bon, je suis vert, le presse papier marche du feu de dieu genre moins de trois minutes! toujours pour 230 fichiers d'environs 3Mo chacun (850 Mo de donnée au départ) et 450 Mo en texte

    Merci encore pour votre aide à tous.

    pour ceux qui repasserais après voici le code qui marche:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
     
        Private Sub pXLMerger(ByVal strInputDir As String, ByVal stroutputDir As String)
     
            'variables "classiques"
            Dim iMaxSheet, iCountSheet, iCountRangeLines, iMinSheet, iCountRangeCol, iFirstLine As Integer
            Dim bFirstFile As Boolean
            Dim strLastRangeCol As String
     
            'variables "fichier"
            Dim fiFile As IO.FileInfo
            Dim swTxt(4) As StreamWriter
     
            'variables "Excel"
            Dim appXL As New Excel.Application
            Dim xlsInputWorkBook As Excel.Workbook
            Dim xlsInputWorkSheet As Excel.Worksheet
     
            'Diag
            Dim swFichier As New Stopwatch
            Dim ts As TimeSpan
            Dim strElapsedTime As String
     
            'afin de supprimer les entete de colonnes sur les fichiers suivant le premier,
            'un booléen flag le premier fichier
            bFirstFile = True
     
            'initialisation des variables
            strLastRangeCol = ""
            iCountRangeLines = 0
            iMinSheet = 10
            'lancement d'Excel en background
            appXL.Visible = False
            appXL.DisplayAlerts = False
     
            For i = 1 To 4
                Dim fOutputFile As New FileInfo(stroutputDir & "_" & i.ToString & ".txt")
                'suppression des fichiers existants
                If fOutputFile.Exists Then fOutputFile.Delete()
                'instanciation des flux d'ecritures
     
                swTxt(i) = New StreamWriter(stroutputDir & "_" & i.ToString & ".txt", False)
            Next
     
            'info sur le répertoire contenant les fichiers
            Dim fExploitFolderExistance As New IO.DirectoryInfo(strInputDir)
            'liste des fichiers excel à 'merger'
            Dim afiFileList As IO.FileInfo() = fExploitFolderExistance.GetFiles("*.xls")
     
            Console.WriteLine("Debut du traitement des fichiers Excel")
            swFichier.Start()
            'boucle de copie des données 
            For Each fiFile In afiFileList
     
                'ouverture du fichier xls
                xlsInputWorkBook = appXL.Workbooks.Open(fiFile.FullName)
                Console.WriteLine("fichier en cours : " & fiFile.Name)
     
                'compte le nombre d'onglet du fichier
                iMaxSheet = xlsInputWorkBook.Sheets().Count
     
                'boucle par feuille
                For iCountSheet = 1 To iMaxSheet
     
                    'selection de la feuille à traiter
                    xlsInputWorkSheet = xlsInputWorkBook.Worksheets(iCountSheet)
     
                    'je n'ai pas besoin de copier le contenus des feuilles cachées (d'ailleurs le programme plante si j'essai de copier leur contenus)
                    If xlsInputWorkSheet.Visible = Excel.XlSheetVisibility.xlSheetVisible Then
                        If iMinSheet > iCountSheet Then iMinSheet = iCountSheet
                        'activation de la feuille
                        xlsInputWorkSheet.Activate()
     
                        'copie et ajout d'un nouveau range à la collection de range
                        Dim xlsInputUsedRange As Excel.Range = xlsInputWorkSheet.UsedRange
     
                        iCountRangeCol = xlsInputUsedRange.Columns.Count
                        iCountRangeLines = xlsInputUsedRange.Rows.Count
                        strLastRangeCol = GetColumn(iCountRangeCol)
     
                        If bFirstFile = True Then
                            iFirstLine = 1
                        Else
                            iFirstLine = 2
                        End If
     
                        xlsInputWorkSheet.Range("A" & iFirstLine.ToString, strLastRangeCol & iCountRangeLines.ToString).Copy()
                        swTxt(iCountSheet).WriteLine(Clipboard.GetText())
                        Clipboard.Clear()
                    End If
     
                Next iCountSheet
     
                'si c'est le premier fichier qui vient d'etre traiter on change le flag
                If bFirstFile = True Then bFirstFile = False
                Clipboard.Clear()
                xlsInputWorkBook.Close(False)
                releaseObject(xlsInputWorkBook)
            Next
     
            'une fois tous les fichiers traiter on fermer les flux d'ecriture un par un
            'For Each swTxt In swTxtCollection
     
            For i = iMinSheet To iCountSheet - 1
                swTxt(i).Close()
            Next
     
            swFichier.Stop()
            ts = swFichier.Elapsed
            swFichier.Reset()
            strElapsedTime = String.Format("{0:00}:{1:00}.{2:000}", ts.Minutes, ts.Seconds, ts.Milliseconds)
            Console.WriteLine("Fin du traitement, durée : " & strElapsedTime)
            releaseObject(swTxt)
            'puis on ferme excel (ici ca ne semble pas marché car bien qu'aucune erreur ne remonte,
            'excel.exe reste lister dans le gestionnaire des taches, une idée peut-etre?)
            appXL.Quit()
            releaseObject(appXL)
            GC.Collect()
     
        End Sub
     
        'une simple fonction qui revoie une lettre (ou une suite de lettre) quand on lui fournis un chiffre
        Function GetColumn(ByVal aValue As Long) As String
     
            If aValue Mod 26 = 0 Then
                If aValue = 26 Or aValue = 0 Then
                    GetColumn = "Z"
                Else
                    GetColumn = Chr(64 + (aValue \ 26 - 1)) & GetColumn(aValue Mod 26)
                End If
            Else
                If aValue < 26 Then
                    GetColumn = Chr(64 + aValue)
                Else
                    GetColumn = Chr(64 + (aValue \ 26)) & GetColumn(aValue Mod 26)
                End If
     
            End If
        End Function
     
        Private Sub releaseObject(ByVal obj As Object)
            Try
                System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
                obj = Nothing
            Catch ex As Exception
                obj = Nothing
            Finally
                GC.Collect()
            End Try
        End Sub

  14. #14
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 177
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 177
    Points : 25 125
    Points
    25 125
    Par défaut
    avec le temps on connait les feintes à tester ^^

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Export tableau Excel vers txt
    Par TheRealMike dans le forum Macros et VBA Excel
    Réponses: 1
    Dernier message: 04/05/2009, 08h53
  2. sortie code sql d'access vers txt
    Par lbar012001 dans le forum Requêtes et SQL.
    Réponses: 4
    Dernier message: 10/04/2009, 14h19
  3. [COM] Traduction d'un code VB COM Excel vers PHP
    Par Copyright83 dans le forum Bibliothèques et frameworks
    Réponses: 2
    Dernier message: 14/10/2008, 10h32
  4. extraction particulière d'excel vers txt
    Par firebomber dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 06/09/2006, 19h56
  5. exportation excel vers txt
    Par actaruss dans le forum Macros et VBA Excel
    Réponses: 11
    Dernier message: 06/09/2006, 09h38

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo