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