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

Macros et VBA Excel Discussion :

Problème programme de concaténation de classeurs excel


Sujet :

Macros et VBA Excel

  1. #1
    Nouveau candidat au Club
    Inscrit en
    Juillet 2011
    Messages
    1
    Détails du profil
    Informations forums :
    Inscription : Juillet 2011
    Messages : 1
    Par défaut Problème programme de concaténation de classeurs excel
    Bonjour,

    Dans le cadre d'un projet, je dois concaténer des fichiers présents dans un dossier. Chacun des fichiers contient une entête de 8 lignes qui doit donc être récupérée une seule fois et doit etre mise au début du fichier final. Les fichiers sont ensuite constitués de differentes données temporelles, la première case indiquant la date et l'heure précise de la donnée (sous la forme DD/MM/AAAA HH:mm:SS). Une difficultée supplémentaire est que les classeurs se recoupent : certaines données sont présentes sur plusieurs classeurs et doivent donc être supprimées afin de ne les faire apparaitre qu'une seule fois sur le fichier final.

    J'ai donc travaillé à corriger les petites erreurs qui empechaient le programme de fonctionner mais je suis face à une erreur que je n'arrive absolument plus à résoudre : le programme ne plus sauvegarder mon classeur final avec la commande save (ou même dès que j'ai un .activate).
    L'erreur qui m'est retournée est "Erreur d'execution '-21472210 (800401a8)'
    Erreur Automation" sur le premier Wk.Activate de la procédure Remplissage_fichier_final.

    Je vous mets mon code, pour que vous puissiez voir comment mon programme procède : Dans un premier temps, je recense l'ensemble des fichiers présents dans le dossier. Puis j'ouvre chacun des fichiers, je copie les lignes une à une afin de supprimer les lignes portant sur un mauvais jour. Enfin je trie les données par ordre chronologique et je supprime les lignes en double.

    Une petite info qui peut aider aussi : je suis sous excel 2010

    Merci d'avance !


    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
     
     
    Option Explicit
    Dim adresse As String 'Adresse du dossier où sont les fichiers
    Dim date_jour As Date 'Date du jour que l'on traite
    Dim ligne_courante As Long 'Numéro de la prochaine ligne sur laquelle on peut écrire sur le fichier final
    Dim nom_fichier_final As String 'Nom du fichier final
    Dim Wk As Workbook 'Objet classeur représentant le fichier final
    Dim noms_fichiers(1 To 250) As String 'Tableau où sont indiqués tous les noms des classeurs présents dans le dossier "adresse"
     
    Sub Importation()
     
        'Permet de ne pas afficher les alertes
        Application.DisplayAlerts = False
     
        'Récupération des données sur le classeur actuel
        adresse = Cells(10, 2).Value 'de la forme C:\Users\
        date_jour = Format(Cells(16, 2), "dd/mm/yyyy")
        nom_fichier_final = Cells(15, 2).Value
     
        'Initialisation des variables
        ligne_courante = 9              '8 lignes d'entête donc prochaine ligne où les données peuvent être écrites est la n°9
     
        'Création des variables limitées à la procédure
        Dim Derniere_ligne_fichier_concatene As Long            'Numéro de la dernière ligne du fichier final
        Dim j As Integer, i As Integer                          'Variables d'itérations
        Dim numero_fichier As Integer                           'Numéro de fichier dans le dossier (indice du tableau noms_fichiers dans lequel le nom du fichier est indiqué)
        numero_fichier = 1
     
        'Récupération de tous les noms de fichiers présents dans le dossier et mémorisation dans le tableau noms_fichiers 
    noms_fichiers(numero_fichier) = Dir(adresse)
        While noms_fichiers(numero_fichier) <> ""
     
           If noms_fichiers(numero_fichier) <> nom_fichier_final & ".*" Then  'Pour éviter de prendre en compte le fichier final comme un fichier à concaténer si le programme a déja été appliqué au dossier
                numero_fichier = numero_fichier + 1
                noms_fichiers(numero_fichier) = Dir
     
            Else
                noms_fichiers(numero_fichier) = Dir
     
            End If
        Wend
     
        'Création d 'un classeur, identification avec l'objet Wk et sauvegarde
        Set Wk = Workbooks.Add
        Wk.SaveAs (adresse & nom_fichier_final)
     
        'Appel de la fonction permettant de remplir le fichier final
        For i = 1 To numero_fichier - 1
     
            If i = 1 Then
     
                Call Remplissage_fichier_final(i, True)
     
            Else
     
                Call Remplissage_fichier_final(i, False)
     
            End If
     
        Next i
     
        'Copie dans l'entete du fichier final de la date du jour
        Wk.Activate
        Cells(2, 3) = date_jour
     
        'Comptage du nombre de ligne du fichier final
     
         Derniere_ligne_fichier_concatene = Application.WorksheetFunction.CountA(Range("A:A")) + 3
     
        'Trie des données par ordre chronologique
        Range("A9:J" & Derniere_ligne_fichier_concatene).Select
        ActiveSheet.Sort.SortFields.Clear
        ActiveSheet.Sort.SortFields.Add Key:=Range("A9:A" & Derniere_ligne_fichier_concatene), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
        With ActiveSheet.Sort
            .SetRange Range("A8:J" & Derniere_ligne_fichier_concatene)
            .Header = xlYes
            .MatchCase = False
            .Orientation = xlTopToBottom
            .SortMethod = xlPinYin
            .Apply
        End With
     
        'Suppression des lignes en double    
        For j = Derniere_ligne_fichier_concatene To 10 Step -1
            If CDec(CDate(Cells(j, 1))) = CDec(CDate(Cells(j - 1, 1))) Then
                Rows(j).Select
                Selection.EntireRow.Delete
            End If
        Next j
     
     
     
        For i = 9 To Derniere_ligne_fichier_concatene
     
            'Reconversion du format de date dans le bon sens...
            If Day(Cells(i, 1)) < 13 Then
               Cells(i, 1) = Format(Cells(i, 1), "dd/mm/yyyy hh:mm:ss")
            End If
     
        Next i
     
        Wk.Save
        Wk.Close
     
        'Réactivation des alertes
        Application.DisplayAlerts = True
     
        MsgBox ("La concaténation est terminée. Le fichier est dans le dossier renseigné")
     
    End Sub
     
    Sub Remplissage_fichier_final(i As Integer, bool As Boolean)
     
        'Création des variables locales
        Dim Derniere_ligne As Integer
        Dim l As Integer, j As Integer, k As Integer
     
        'Création d 'un classeur, identification avec le fichier à concaténer
        Dim Wk_valeurs As Workbook
        Set Wk_valeurs = Workbooks.Open(adresse & noms_fichiers(i))
     
        'Comptage du nombre de ligne du fichier à concatener
        Derniere_ligne = Application.WorksheetFunction.CountA(Range("A:A")) + 3
     
        'Copie de l'entête dans le cas où c'est le premier fichier à traiter
        If bool = True Then 
     
            Wk_valeurs.Activate
            Rows("1:8").Select
            Selection.Copy
            Wk.Activate
            Range("A1").Select
            ActiveSheet.Paste
     
        End If
     
     
        'Copie de la prochaine ligne à ajouter dans le fichier final
        For l = 9 To Derniere_ligne
            Wk_valeurs.Activate
            Dim ligne(1 To 10) As Variant
     
            'Problème avec les dates donc obligé de changer le format de la date en fonction du numéro du jour ...
            If Day(Cells(l, 1)) < 13 Then
                ligne(1) = Format(Cells(l, 1), "mm/dd/yyyy hh:mm:ss")
            Else
                ligne(1) = Format(Cells(l, 1), "dd/mm/yyyy hh:mm:ss")
            End If
     
     
            For j = 2 To 10
                ligne(j) = Cells(l, j)
            Next j
     
            'Copie de la ligne dans le fichier final 
            Wk.Activate
            If Int(CDec(CDate(ligne(1)))) = CDec(CDate(date_jour)) Then 'le fichier ne doit contenir que des données du même jour donc suppression de toutes les données concernant un jour different 
                For k = 1 To 10
                    Cells(ligne_courante, k) = ligne(k)
                Next k
     
                ligne_courante = ligne_courante + 1
     
            End If
     
        Next l
     
        Wk_valeurs.Close
        Wk.Activate
        Wk.Save
     
    End Sub

  2. #2
    Membre chevronné
    Profil pro
    Inscrit en
    Juillet 2011
    Messages
    141
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2011
    Messages : 141
    Par défaut
    Bonjour Flo333,
    L'absence de réponse jusqu'à maintenant montre la complexité du code à cause de la longueur de la procédure Importation() même s'il existe un premier niveau de découpage avec la procédure Remplissage_fichier_final().

    Comme le code fourni ne peut pas être testé, on ne peut proposer que des conseils généraux.

    1. Structurer en procédures plus courtes

    Il faudrait se ramener à une trentaine de lignes par procédure alors qu'Importation() fait plus de 100 lignes rendant impossible une vision globale de la portée des variables sans scroller, d'où les bugs.

    2. Avoir une gestion d'erreur

    Gérer les erreurs à l'ouverture et à la sauvegarde des classeurs par :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    On Error Resume Next
    Set Wk_valeurs = Workbooks.Open(adresse & noms_fichiers(indFile)) 
    If Err.Number <> 0 Then Warning "9000: Cannot open " + adresse & noms_fichiers(indFile)
    On Error Goto 0
    Voir la procédure Warning "1000: message d'erreur"

    3. Décrire les feuilles avec des constantes

    Dans le lien sur Warning(), vous constaterez comment avec des constantes, on peut décrire chaque feuille Excel afin d'éviter d'avoir des constantes numériques ou littérales dans le code telles que :
    Si l'entête passe un jour à 9 lignes, il faudra tout réécrire dans le code à plusieurs endroits.
    Si vous définissez des constantes, vous n'aurez qu'à les mettre à jour à un endroit unique.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ligne_courante = 9 '8 lignes d'entête donc prochaine ligne où les données peuvent être écrites est la n°9
    devient :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ligne_courante = rowDataFirst
    si on a défini la constante
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Public Const rowDataFirst = 9 ' Commentaire expliquant cette constante.
    Cela permettrait d'expliquer l'étrange + 3 dans :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Derniere_ligne = Application.WorksheetFunction.CountA(Range("A:A")) + 3
    4. Portée des variables locales

    Regroupez la déclaration des variables locales sur les lignes qui suivent la déclaration de la procédure et non à la première utilisation de la variable locale.
    Cela améliore la lisibilité du code quand on sépare les déclarations du code proprement dit.

    5. Convention de nommage

    Trouvez des noms de variables explicites :
    devient
    Comme ce booléen se déduit de l'indice de n° fichier indFile, le test devient simplement :
    Cela va économiser le passage de paramètre du booléen "bool" et 9 lignes de codes lors de l'appel y compris les lignes vides.

    Il y a un contraste frappant entre certaines variables à rallonge telles que :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Dim Derniere_ligne_fichier_concatene As Long
    et les variables sur une seule lettre suivant l'ordre alphabétique i, j, k, l, ...
    C'est une source de bug potentiel avec risque de confondre i, l et 1. Essayons de substituer l'indice i partout dans le code. Ce sera plus difficile et plus long.

    S'il s'agit d'un indice de rangée, appelez la variable indRow.
    S'il s'agit d'un indice de colonne, appelez la variable indCol.
    S'il s'agit d'un indice de fichier, appelez la variable indFile et non pas i.
    Cela permettra de substituer les noms des variables si vous les préférez en français.

    On ne peut pas avoir un wk sur seulement deux lettres par rapport à Wk_valeurs alors que l'on a des wkSource à concaténer dans un wkTarget. Nommer les variables en terme de source ou de cible ou alternativement d'entrée ou de sortie est plus lisible que de parler de "_valeurs" ou de fichier final s'il s'agit du classeur cible résultant de la concaténation.

    Il faut immédiatement pouvoir contrôler visuellement s'il y a un bug d'indice à la lecture séquentielle des variables d'indices dans Cells(indRow, colHeader) ou Cells(rowHeader, indCol) avec les constantes décrivant l'entête commençant par le mot-clé "row" si c'est une rangée et "col" si c'est une colonne.

    6. Tableaux des noms des classeurs à concaténer

    Lors du parcours du répertoire des classeurs, il n'y a aucun test pour savoir si le nombre des noms de fichiers dépasse la borne maximum du tableau (array) des noms de fichiers arrFilename(1 To nbrMaxFilename) avec la constante nbrMaxFilename à définir :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Public Const nbrMaxFilename = 250
    Le bug pourrait se localiser dans le remplissage de ce tableau :

    Isoler l'extrait de code dans une fonction retournant le nombre de fichiers trouvés :
    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
    Function ScanFolderXls(ByVal adresse As String, ByVal nom_fichier_final As String) As Integer
    Dim numero_fichier As Integer
     
        numero_fichier = 1
        noms_fichiers(numero_fichier) = Dir(adresse)
        While noms_fichiers(numero_fichier) <> ""
            'Pour éviter de prendre en compte le fichier final comme un fichier à concaténer si le programme a déja été appliqué au dossier
            If noms_fichiers(numero_fichier) <> nom_fichier_final & ".*" Then
                numero_fichier = numero_fichier + 1
                noms_fichiers(numero_fichier) = Dir
            Else
                noms_fichiers(numero_fichier) = Dir
            End If
        Wend
        ScanFolderXls = numero_fichier
    End Function
    Le test du nom du fichier courant avec nom_fichier_final concaténé avec le joker ".*" pourrait être douteux car on compare avec le caractère "." suivi du caractère unique étoile et non pas une extension générique de joker d'autant plus qu'on s'attendrait à ne parcourir que les fichiers ayant l'extension *.xls

    Réécrire cette procédure sur la base suivante :
    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
    Option Explicit
     
    Function ScanFolderXls(ByVal strPath As String, ByVal strFileExclude As String) As Integer
    Dim nbrFile As Integer, strFilename As String
     
        nbrFile = 0
        strFilename = Dir(strPath) ' *.xls ?
        While strFilename <> ""
            ' si le programme a déja été appliqué au dossier, éviter le fichier final
            If strFilename <> strFileExclude Then ' Test à mettre au point
                nbrFile = nbrFile + 1
                arrFilename(nbrFile) = strFilename
            End If
            strFilename = Dir
        Wend
        ScanFolderXls = nbrFile
    End Function
    7. Contexte du bug

    Citation Envoyé par Flo333 Voir le message
    L'erreur qui m'est retournée est "Erreur d'execution '-21472210 (800401a8)'
    Erreur Automation" sur le premier Wk.Activate de la procédure Remplissage_fichier_final.
    Comme on ne peut pas déboguer à distance, il faut être encore plus précis sur le contexte du bug.
    N° de ligne de code, valeur de l'indice de boucle indFile, nom du classeur à concaténer courant. Est-ce le premier fichier ? Nom du classeur final résultant, etc.
    ___________

    Si la discussion est résolue, vous pouvez cliquer sur le bouton

    En bas de ce message s'il vous a apporté des éléments de réponse pertinents, pensez également à voter en cliquant sur le bouton vert ci-dessous.

Discussions similaires

  1. [XL-2010] Problème de taille d'un classeur Excel
    Par juju05 dans le forum Excel
    Réponses: 1
    Dernier message: 07/09/2012, 15h44
  2. Problème lors de la création automatique d'un classeur excel
    Par petiteabeille64 dans le forum Macros et VBA Excel
    Réponses: 6
    Dernier message: 15/04/2008, 16h45
  3. Problème d'ouverture de classeur Excel
    Par k_boy dans le forum Delphi
    Réponses: 2
    Dernier message: 21/07/2007, 13h12
  4. Problème d'ouverture d'un classeur Excel
    Par BM42 dans le forum VB 6 et antérieur
    Réponses: 12
    Dernier message: 21/11/2006, 09h43
  5. [Excel] Problème d'enregistrement d'un classeur
    Par Geache dans le forum Excel
    Réponses: 3
    Dernier message: 28/03/2006, 20h39

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