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 :

Gestion de gros fichier : Espace de chaine insuffisant avec fonction Space/Get/Replace/Split


Sujet :

Macros et VBA Excel

  1. #1
    Membre à l'essai
    Inscrit en
    Juillet 2007
    Messages
    18
    Détails du profil
    Informations forums :
    Inscription : Juillet 2007
    Messages : 18
    Points : 10
    Points
    10
    Par défaut Gestion de gros fichier : Espace de chaine insuffisant avec fonction Space/Get/Replace/Split
    Bonjour,

    Pour info je travaille sur Excel 2010.

    J'ai des soucis avec la gestion de la mémoire pour mettre un fichier texte en mémoire via VBA, ainsi que pour utiliser des fonctions telles que Space / Get / Replace / Split
    Je souhaite mettre en mémoire dans une variable string un fichier important (>50Mo) et le manipuler ensuite pour l'éclater en ligne puis en cellule
    J'utilise pour cela une fonction qui contient le code suivant :

    La variable filecontent est déclaré en global parce qu'utilisé dans plusieurs fonctions / procédures

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    szFileName = LB_File_Path.Caption
    f = FreeFile
    Open szFileName For Binary Access Read As #f
    fileContent = Space(LOF(f))
    Get #f, , fileContent
    Or je plante avec l'erreur 14 "Espace de chaine insuffisant" sur la fonction "Space", ceci de manière aléatoire (en fonction de la mémoire dispo sur mon PC je suppose...)
    Je peux avoir également la même erreur sur la fonction "Get" / Replace / Split sachant que j'ai besoin de ces fonctions ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    fileContent = Replace(fileContent, vbLf, vbCrLf)
    Y'a t-il une autre manière de mettre un fichier en mémoire ? La fait de découper le fichier en plusieurs morceaux ne changeant rien ...

  2. #2
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2013
    Messages
    3 617
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Alimentation

    Informations forums :
    Inscription : Mai 2013
    Messages : 3 617
    Points : 5 912
    Points
    5 912
    Par défaut
    Bonjour,

    Ça pourrait être dû à la mémoire dont dispose ton PC, je pense.
    Et peut-être la vitesse de ton disque dur pour le "swapping" (?)
    Combien de RAM a ton PC ?
    MPi²

  3. #3
    Membre à l'essai
    Inscrit en
    Juillet 2007
    Messages
    18
    Détails du profil
    Informations forums :
    Inscription : Juillet 2007
    Messages : 18
    Points : 10
    Points
    10
    Par défaut
    Bin certainement la mémoire du pc est en cause (4Go de ram), d'autant plus qu'elle est occupé par d'autres fichiers excel ouverts, d'autres applications etc ...

    Quand j'ouvre la première fois la macro, les fonctions marchent, mais il suffit que la fasse tourner plusieurs fois pour que le problème apparaisse, sur quand j'extrais les données du fichier et qu'elle sont stockée dans une feuille excel (~71000 lignes dans ce cas précis) cela a tendance à saturer la mémoire d'excel et le fichier passe l'étape du Space et du Get mais j'ai une erreur 7 "Mémoire insuffisante" avec la fonction Split ...

    Quand je catch l'erreur en mode débug je vois bien la mémoire disponible qui n'est pas à 0, ca veut dire qu'il lui en reste encore sous le capot, je pense à une limitation au niveau d'excel mais je sais pas ou ...

    Le truc c'est que la macro excel que je développe (dans le cadre professionnel) est utilisé par de multiples personnes avec des configurations différentes et certainement un nombre plus ou moins important de fichier excel / autres applications démarrée.

    Il me faut un moyen de ne plus avoir ce problème de mémoire peu importe les processes lancés en même temps, je ne peux pas demander aux utilisateurs de ma macro de fermer les applications en cours ou d'arrêter et redémarrer excel systématiquement ... :/

  4. #4
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2013
    Messages
    3 617
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Alimentation

    Informations forums :
    Inscription : Mai 2013
    Messages : 3 617
    Points : 5 912
    Points
    5 912
    Par défaut
    Tu pourrais peut-être ouvrir (lire) le fichier en plusieurs parties ?
    Plutôt que d'utiliser LOF, il te faudrait utiliser un plus petit "buffer".

    Ou encore lire ligne par ligne, mais je ne sais pas trop le temps que ça pourrait prendre...
    Je n'ai pas vraiment de fichier aussi gros sous la main pour tester.

    Windows ne laissera jamais aller la mémoire à 0.
    Il va plutôt passer par du swapping sur le disque dur et ce dernier pourrait aussi être en cause s'il est trop lent pour le traitement...
    MPi²

  5. #5
    Expert éminent sénior
    Avatar de Marc-L
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    9 468
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2013
    Messages : 9 468
    Points : 18 677
    Points
    18 677
    Par défaut




    Bonjour, bonjour !

    J'utilise souvent l'import direct en mémoire mais vraiment direct comme par exemple dans cette discussion lignes n°4 & 5…

    C'est parce que la vitesse de la lumière est plus rapide que celle du son que tant de gens paressent brillants avant d'avoir l'air con ! (Thomas Boishardy)

  6. #6
    Membre à l'essai
    Inscrit en
    Juillet 2007
    Messages
    18
    Détails du profil
    Informations forums :
    Inscription : Juillet 2007
    Messages : 18
    Points : 10
    Points
    10
    Par défaut
    Merci pour ta suggestion Marc, mais l'instruction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    fileContent = Input(LOF(f), f)
    plante aussi avec de gros fichier.

    Ce que je fait fait, c'est que je charge un première fois le fichier , pas de problème:
    Chargement du fichier en mémoire
    Split dans un tableau (Par ligne vbLf ou VbCrLf)
    Séparation, pour chaque ligne, suivant des critères de position/longeur dans un autre tableau
    Recopie de ce tableau dans une feuille Excel (~28000 lignes)

    Je lance cette macro une deuxième fois, ca passe encore (au préalable les 28000 lignes sont supprimées de le feuille)
    mais genre au bout de la troisième, la macro plante sur l'instruction Input avec l'erreur 14
    Puis, j'attends un peu et la l'instruction Input passe mais c'est l'instruction Split qui plante erreur 7

    Le code du split est le suivant :
    Comme je ne sais pas de quel manière je vais recvoir les fichiers (Dos ou Unix) le caractère de retour chariot peut changer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    T_File() = Split(fileContent, vbCrLf)
    If UBound(T_File()) = 0 Then                                        
        T_File() = Split(fileContent, vbLf)                              
    End If
    Le fichier que je test est en mode Unix (caractère VbLf) et le split plante quand j'essaie le split avec VbCrLf => Il met tout le contenu du fichier dans T_File(0) => Erreur 7

  7. #7
    Invité
    Invité(e)
    Par défaut
    bonjour,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    fileContent = Space(LOF(f))
    tu Bufferise sur la totalité de ton fichier, ne peux tu pas bufferiser sur une valeur plus petite et lire ton fichier en plusieurs fois?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    While EOF(f) = False
    fileContent = Space(1024)
    Get #f, , fileContent
    Wend
    mais là il faut revérifier si la dernière ligne de ton buffer n'est pas coupé avec la première du buffer suivant!
    Dernière modification par Invité ; 29/09/2014 à 12h43.

  8. #8
    Membre à l'essai
    Inscrit en
    Juillet 2007
    Messages
    18
    Détails du profil
    Informations forums :
    Inscription : Juillet 2007
    Messages : 18
    Points : 10
    Points
    10
    Par défaut
    Bonjour rdurupt,

    le truc c'est que je dois travailler avec une variable contenant l'intégralité du fichier, pour l'utilisation des fonction split en particulier.
    En effet ma macro est censé traiter des fichiers contenant des lignes de longueur différentes (potentiellement sans retour chariot)

    Avant j'avais le code suivant :
    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
    VarString = ""
    f = FreeFile
    Open szFileName For Binary Access Read As #f
        ' préallocation d'un buffer
     
        taille = Round(LOF(f) / 5)
        VarString = String(taille, " ")
     
        ' lecture complète du fichier
        While Len(Buffer) < LOF(f)
     
            If Len(Buffer) + Len(VarString) > LOF(f) Then
                VarString = String(LOF(f) - Len(Buffer), " ")
            End If
            Get #f, , VarString
            Buffer = Buffer + VarString
            t = Len(Buffer)
        PctDone = Len(Buffer) / LOF(f)
        With UserForm1                                                  '*** User form1
            .FrameProgress.Caption = Format(PctDone, "0%")              '*** User form1
            .LabelProgress.Width = PctDone * (.FrameProgress.Width)     '*** User form1
        End With
        DoEvents
     
        Wend
    Close #f
     
    fileContent = Buffer
    Par cette methode, je mettais le fichier en mémoire petit à petit mais avec des gros fichier, l'instruction "Buffer = Buffer + VarString" plantait pour la même erreur (mémoire insuffisante)
    J'ai utilisé cette methode car quand je le recopiais en entier, j'avais l'erreur 14 et je voulais voir à partir de quelle taille de fichier j'avais une erreur.
    Il s'avère que la variable t est systématiquement égale à 63507160 octets...

  9. #9
    Membre actif
    Homme Profil pro
    Consultant fonctionnel
    Inscrit en
    Septembre 2009
    Messages
    114
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Consultant fonctionnel

    Informations forums :
    Inscription : Septembre 2009
    Messages : 114
    Points : 254
    Points
    254
    Par défaut
    Le traitement est relancé plusieurs fois parce que tu ouvres plusieurs fichiers différents?
    Une manière détournée de résoudre ton problème serait de vérifier si le fichier n'a pas déjà été chargé en mémoire et de réutiliser la variable déjà chargée (T_File en l'occurrence).

  10. #10
    Invité
    Invité(e)
    Par défaut
    pour l'instant je ne sais pas ce qui empêche de fractionner ton fichier; le split fonctionne! la dernière ligne peut poser problème alors tu traite tes ligne moins 1
    puis tu récupère ta dernière ligne avec ton buffeur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    txt=T_File(UBound(T_File)) & buffeur
    T_File= split(txt,vbcrlf)
    à la fin tu traitement du fichier il te resteras bien sur la dernière ligne à traiter!

  11. #11
    Expert éminent sénior Avatar de Menhir
    Homme Profil pro
    Ingénieur
    Inscrit en
    Juin 2007
    Messages
    16 037
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 16 037
    Points : 32 866
    Points
    32 866
    Par défaut
    Tu ne pourrais pas envoyer ton texte dans un document Word (en instruction VBA Excel) ?
    Ca te permettrait d'avoir (presque) autant d'espace que tu veux et de nombreuses fonctions de manipulation de texte.
    Merci de cliquer sur pour chaque message ayant aidé puis sur pour clore cette discussion.

  12. #12
    Membre à l'essai
    Inscrit en
    Juillet 2007
    Messages
    18
    Détails du profil
    Informations forums :
    Inscription : Juillet 2007
    Messages : 18
    Points : 10
    Points
    10
    Par défaut
    @TiJean2910, en fait je lui faisait recharger plusieurs fois le même fichier pour provoquer l'erreur, ce n'est pas un cas d'utilisation réel mais juste un test

    @rdurupt : j'avoue ne pas bien comprendre ton algo dans sa totalité :/, comment tu initialises le tableau T_File ?
    Pourrais tu me donner l'algo complet ?

    @Menhir : Je n'ai jamais pensé à ça ^^, après qu'en est il des performances ? Tu as des instructions à me donner en exemple ?

  13. #13
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2013
    Messages
    3 617
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Alimentation

    Informations forums :
    Inscription : Mai 2013
    Messages : 3 617
    Points : 5 912
    Points
    5 912
    Par défaut
    Si tu ouvres ton fichier directement dans Excel, ne peux-tu pas utiliser la fonction Convertir pour modifier ton fichier comme voulu ?
    MPi²

  14. #14
    Membre à l'essai
    Inscrit en
    Juillet 2007
    Messages
    18
    Détails du profil
    Informations forums :
    Inscription : Juillet 2007
    Messages : 18
    Points : 10
    Points
    10
    Par défaut
    Citation Envoyé par parmi Voir le message
    Si tu ouvres ton fichier directement dans Excel, ne peux-tu pas utiliser la fonction Convertir pour modifier ton fichier comme voulu ?
    Ce n'est malheureusement pas aussi simple que ca étant donné que la macro doit marcher avec des fichiers contenant du format IBM Packé, donc exclusivement lisible en Hexadécimal...
    La position/longueur des différents "champs" de chaque ligne varie en fonction du fichier traité etc ...

  15. #15
    Expert éminent sénior Avatar de Menhir
    Homme Profil pro
    Ingénieur
    Inscrit en
    Juin 2007
    Messages
    16 037
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 16 037
    Points : 32 866
    Points
    32 866
    Par défaut
    Citation Envoyé par stimp4ck Voir le message
    @Menhir : Je n'ai jamais pensé à ça ^^, après qu'en est il des performances ? Tu as des instructions à me donner en exemple ?
    Il faut que tu charges les bibliothèques d'objet Word. Dans l'éditeur VBA :
    Outils > Préférence > Coches "Microsoft Word Object Library"
    Ensuite, tu pourras utiliser les objets Word (entre autres Document et ses membres) ce qui te permettra de faire ce que tu souhaites.
    Je sais qu'il existe aussi des éditeurs de texte qui ont des bibliothèques d'objets utilisables avec VBA mais je n'en ai jamais utilisé. Peut-être que ça pourrait traiter ton problème de manière plus légère que Word.
    Merci de cliquer sur pour chaque message ayant aidé puis sur pour clore cette discussion.

  16. #16
    Invité
    Invité(e)
    Par défaut
    après il faut adapter à ce que tu veux faire!
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    Sub test()
    T_File = Array("")
    txt =""
    While EOF(f) = False 'Fin de fichier?
        fileContent = Space(1024) 'Buffer 1Ko
        Get #f, , fileContent 'lecture 1Ko
        txt = T_File(UBound(T_File)) & fileContent 'reprise de la dernière ligne
         T_File = Split(Replace(txt, vbLf, vbCrLf), vbCrLf) 'Action Split
        ActiveSheet.Range("A1:A" & UBound(T_File) - 1) = T_File 'Sauvegarde dans Excel perdre en compte de la dernière cellule Excel pas comme moi
    Wend
    ActiveSheet.Range("A1") = T_File(UBound(T_File)) 'comme je ne traite jamais la dernière ligne du tableau!
    End Sub

  17. #17
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2013
    Messages
    3 617
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Alimentation

    Informations forums :
    Inscription : Mai 2013
    Messages : 3 617
    Points : 5 912
    Points
    5 912
    Par défaut
    J'ai fait un test en Binary avec un fichier de 60 megs et ça plante
    Erreur 14: espace chaîne insuffisant.

    J'ai refait un test en Input comme mentionné par Marc-L et ça ne plante pas
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
        FF = FreeFile
        Open Chemin & Fichier For Input As #FF
            strTemp = Input(LOF(FF), #FF)
        Close #FF
     
        strTemp = Replace(strTemp, vbCrLf, vbLf)
        strTemp = Replace(strTemp, vbLf, vbCrLf)
    MPi²

  18. #18
    Membre à l'essai
    Inscrit en
    Juillet 2007
    Messages
    18
    Détails du profil
    Informations forums :
    Inscription : Juillet 2007
    Messages : 18
    Points : 10
    Points
    10
    Par défaut
    @rdurupt : La définition de la variable T_File pose problème (Incompatibilité de type), défini comme tableau de chaine, cela plante à l'initialisation avec l'instruction T_File = Array("")
    Et si je le déclare en variant, la fonction split pose le même soucis ...

    Dernièrement en vidant la mémoire grâce a des Erase en fin de programme j'arrive à faire passer des fichier de 70/80Mo plusieurs fois de suite Par contre dès que le fichier est plus gros cela ne fonctionne pas et ce dès la première tentative ...

    @Menhir : Je vais essayer ton idée

    @Parmi : J'essaie maintenant avec un fichier plus gros et cela ne fonctionne même pas avec l'instruction Input ...

    Je ne comprend pas que de telles limitations existent sur des machines actuelles ...
    J'ai l'impression que vouloir mettre dans une seule variable de chaine autant de caractère dépasse la limite d'un emplacement mémoire qu'on soit en 32 ou 64K

    Je devrait peut être repenser à mon algo afin de découper le fichier ou lire petit à petit, tout en traitant ... dommage la mise en mémoire me paraissait la plus rapide des méthodes ...

  19. #19
    Expert éminent sénior
    Avatar de Marc-L
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    9 468
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2013
    Messages : 9 468
    Points : 18 677
    Points
    18 677
    Par défaut





    Regarder l'aide du type de données String


    C'est parce que la vitesse de la lumière est plus rapide que celle du son que tant de gens paressent brillants avant d'avoir l'air con ! (Thomas Boishardy)

  20. #20
    Membre à l'essai
    Inscrit en
    Juillet 2007
    Messages
    18
    Détails du profil
    Informations forums :
    Inscription : Juillet 2007
    Messages : 18
    Points : 10
    Points
    10
    Par défaut
    Justement :
    Les chaînes de longueur variable peuvent contenir environ 2 milliards (2^31) de caractères.

    Je suis loin des 2 milliards de caractère avec un fichier de 100Mo ...

Discussions similaires

  1. [Python 2.X] gestion de gros fichier
    Par vincenlnx dans le forum Général Python
    Réponses: 10
    Dernier message: 22/11/2014, 15h42
  2. gestion de gros fichiers en C++
    Par buzzkaido dans le forum C++
    Réponses: 6
    Dernier message: 07/08/2012, 12h16
  3. Gestion de gros fichiers
    Par bpy1401 dans le forum Android
    Réponses: 10
    Dernier message: 03/07/2012, 13h40
  4. Gestion des (gros) fichiers
    Par schneed dans le forum C++Builder
    Réponses: 1
    Dernier message: 23/02/2009, 20h05
  5. [Composants texte] Gestion de gros fichiers
    Par sozie9372 dans le forum Interfaces Graphiques en Java
    Réponses: 8
    Dernier message: 22/05/2006, 11h03

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