Aide formule à alléger

Résolu
Bonjour,

J'ai une extraction informatique qui me permet d'obtenir des montants par compte, par mois et par service.
Je voudrais afficher les résultats avec une feuille par service (cf fichier joint).

Le problème est que j'ai tellement de services (donc de feuilles à produire) que le rafraîchissement de mes formules recherchev est énormément long... Et ne parlons pas de l'enregistrement.

Auriez-vous une autre méthode pour alléger & accélérer le résultat ? Autre formule ? Macro ?

Pour l'exemple, je n'ai laissé que 5 feuilles.

https://www.cjoint.com/?0AtjSgFqemR

Merci de votre aide.

19 réponses

Résumé de la discussion

Le problème consiste à extraire des montants par compte, par mois et par service et à afficher un fichier par service, ce qui génère un grand nombre de feuilles et entraîne des délais importants lors du recalcul des formules et de l’enregistrement. Une solution proposée est une macro qui répartit les données dans des feuilles dédiées et écrit les dépenses dans la colonne correspondante; l’exécution est mesurée à environ 7 minutes 30 sur une machine, dont une part importante est consacrée à l’enregistrement des classeurs. Une autre approche consiste à générer des fichiers par UF à partir d’un fichier texte volumineux, la macro demandant le mois et l’année puis produisant des fichiers UF_xxx.xls dans un répertoire dédié pour éviter l’ouverture massive dans Excel. Pour les volumes importants, l’usage d’une base Access est évoqué : importer le fichier texte comme table liée et exploiter des requêtes pour découper par pôle et réorganiser les UF, afin de contourner les limites d’Excel.

Bobot (l’IA à votre service)
  1. Bonjour

    A tester sans filtre

    Sub test()
    Application.ScreenUpdating = False
    Nlig = Feuil7.Range("A" & Rows.Count).End(xlUp).Row
       For L = 2 To Nlig
          Uf = Feuil7.Range("F" & L).Value
          Depense = Feuil7.Range("E" & L).Value
          Mois = Feuil7.Range("D" & L).Value
          Compte = Feuil7.Range("B" & L).Text
          Col = Mois + 2
          Sheets("UF " & Uf).Select
             For L1 = 8 To 239
                If Range("A" & L1).Text = Compte Then
                   Cells(L1, Col).Value = Depense
                End If
             Next
       Next
    End Sub
    


    A+
    Maurice
    1
    1. Modérateur
      Salut Maurice, et bonne année.

      Le souci de ton code est multiple... Pas très français cette tournure...

      1- Elle ne fait pas la somme des dépenses,
      2- Elle est basée sur le fichier xls transmis qui ne contient pas toutes les données (87457 lignes dans le fichier txt)
      3- elle nécessite d'ajouter au classeur 252 feuilles, une par UF...
      4- il faudrait également pouvoir choisir le mois pour n'établir, par exemple les UF pour les dépenses relatives au 1er trimestre, ou antérieures à septembre...
      0
    2. Merci Maurice !
      C'est carrément presque ça ! :) Trop top.
      Juste, je constate que sur ma feuille "3310", il me met chiffres attendus sur la feuille "3314".
      Et les autres feuilles restent vierge.
      Aussi au début, il me mettait un code d'erreur objet non trouvé. J'ai changé Feuil7 par Feuil1 parce que bizarrement (je ne sais pas pourquoi) ma feuille "Données" la Feuil1 quand on regarde l'écran VBA.
      0
  2. Modérateur
    Voici mon fichier test.
    Il vous faut l'enregistrer et disposer, sur le même ordi, du fichier .txt (celui de 87457 lignes...) correspondant à l'extraction.

    Mode d'emploi :
    > Taper Alt+F8
    > Choisir : Principale
    > Cliquer sur Exécuter

    La macro va vous demander, dans l'ordre :
    > le mois choisi
    > l'année choisie
    > la sélection du fichier texte

    Résultats visibles :
    > Dans le répertoire ou vous avez enregistré ce fichier excel
    > va apparaitre un sous répertoire nommé par exemple :
    > UF's 10 2014 21_01_2015 12_05
    ==> 10 = mois choisi
    ==> 2014 = année choisie
    ==> 21_01_2015 12_05 = date et heure du lancement de la macro (21/01/2015 12:05)
    > dedans vous trouverez tous les fichiers UF nommés par exemple :
    > UF_3211 10_2014.xls
    ==> 3211 = numéro de l'UF

    Durée d'exécution :
    > 7 minutes 30 sur ma machine
    > dont plus de 5 minutes juste pour les enregistrements des 231 classeurs

    Amélioration possible : (dire si intéressé...)
    > possibilité d'ajouter des comptes dans la feuille UF

    1
    1. Alors là chapeau ! C'est sacrément balaise ! En plus chez moi, ça tourne en 3 minutes!
      Enorme merci !
      Je vais travailler sur ça maintenant !
      0
    2. Modérateur
      @thibaut_francoisAmélioration possible : (dire si intéressé...)
      > possibilité d'ajouter des comptes dans la feuille UF
      j'ajoute :
      > envoi par mail de chaque fichier en auto... Pour cela, il te suffirai d'ajouter l'adresse mail de chaque destinataire en colonne Q au regard des références d'UF.

      J'attends ta réponse sur ces deux points.

      Tout ceci pour te faciliter la vie, tu n'aurais qu'à lancer la macro, aller boire un café et en revenant le boulot de quelques heures serait terminé...

      PS : ne pas nous donner la liste des e-mails. Garde ça secret. Dis juste si t'es intéressé...
      0
    3. @pijakuLes 2 évolutions peuvent être très intéressantes oui. La nomenclature comptable pouvant évoluer chaque 1er de l'an...

      Comment s'articulerait la production de l'envoi des mails ? Je créerais une liste en .txt et la macro s'en nourrirait ?
      Ça peut être super pratique oui.

      J'aurai une 3ème idée d'évolution. Penses-tu possible de créer un "récapitulatif" par pôle ? C'est à dire que la macro créé un fichier excel par pôle avec les UF qui le compose (1 fichier excel avec autant de feuille que d'Uf qui le compose... à partir du fichier structure que j'avais mis).
      0
    4. Modérateur
      @thibaut_francoisBonjour,
      '<== c'est important chaque matin, si si.


      La nomenclature comptable pouvant évoluer chaque 1er de l'an...
      Oui, par exemple. Ou les chefs de pôle qui décideraient du jour au lendemain d'avoir les données du compte 602x1 figurant dans le fichier txt mais pas dans la feuille UF...
      Dans ce cas, les modifications devront intervenir selon certaines règles :
      Dans la feuille UF, en colonne A.
      Conserver le même type de structure.
      Dans cette colonne A on ne devra retrouver que :
      - des cellules comportant les n° de compte
      - des cellules vides.
      Rien d'autre.
      Les cellules vides correspondent aux lignes des totaux et sous-toto, les cellules avec n° correspondent aux lignes des dépenses des-dits comptes.
      Pas, non plus, de fusion de cellules. En VBA cela ne fait que foutre la m**, euh, mettre la pagaille.

      Comment s'articulerait la production de l'envoi des mails ?
      Comme je te l'ai dit hier. Il te suffirait d'inscrire l'adresse mail du destinataire en regard de chaque numéro d'UF, dans la colonne Q...
      Ça peut être super pratique oui. Ben tu m'étonnes! 250 mails à envoyer, même en 30 secondes par mail ça fait tout de même 2 heures... Même si la macro mets 3 heures à tout envoyer, tu peux faire autre chose pendant ce temps. Une manucure ou une séance d'UV dans la machine à IRM par exemple ;-).

      Penses-tu possible de créer un "récapitulatif" par pôle ?
      Sans aucun souci.
      En plus des fichiers UF, créer, en fonction de la structure, un fichier Récap comprenant tous les UF d'un pôle. C'est bien cela?

      Cela risque de me prendre du temps, donc sans nouvelles de moi d'ici mardi ou mercredi, ne t'inquiète pas hein? A moins que d'ici ce soir une plage se libère pour ça. Sinon, une petite relance en début de semaine prochaine, au cas ou.
      0
    5. Excuse moi... ... ... Bonjour ^^
      J'étais dans la suite de la discussion :)

      OK pour tout ! Le mailing et les nouveaux comptes.

      Pour le "récap" c'est bien cela. En soit ça fait 7 fichiers dits de pôle.

      Merci à toi, et passe un bon week-end !
      0
  3. Bonjour,

    En passant par les macros, on peut en effet reproduire le même résultat (qui plus est cela enlèverait les formules dans les cellules). Mais avant de se lancer dans un long code vba, je préférerais connaître vos attentes précises sur le résultat, que ce soit dans le contenu ou dans la forme (feuilles bien distinctes? toutes affichées simultanément ou alors créer un bouton pour n'afficher que celle correspondant à une réf? etc.).

    J'insiste, mais quitte à passer aux macros, autant en utiliser des fonctionnalités dépassant celles des formules classiques plutôt que de se contenter d'une traduction de formules.
    0
    1. L'idée du document consiste à remettre le plus rapidement possible toutes les feuilles du classeur lorsque je remets à jour mon extraction informatique.
      La feuille "Données" est tout simplement un copier-coller de l'extraction de mon logiciel. L'extraction peut-être soit de type .txt ou .xls en fonction de mon choix.
      Dans l'exemple, je colle mes extractions dans la feuille "Données" pour que les 5 autres feuilles se remettent à jour automatiquement.
      Après, je ne connais pas la portée informatique des macros. Peut-être effectivement qu'on pourrait aller plus loin dans la fonctionnalité... Mais ne maîtrisant pas, je n'ai pas plus d'idée sur ce que je pourrais en attendre...
      0
    2. "Remettre le plus rapidement possibles toutes les feuilles"

      Tu veux dire que tu as besoin de toutes les feuilles actualisées en même temps dans des onglets différents ?
      Quel est le but ? Les consulter ? Les copier/coller ? Les archiver sans plus d'utilisation ? Les imprimer ? (...)?

      Pour reformuler mon conseil, il ne s'agit pas de faire le document à partir de ce qu'Excel permet de faire (macros ou pas) mais au contraire de d'abord choisir ce que tu souhaites et ensuite opter pour la solution adéquate (Excel ? Si oui macros?).
      0
    3. @Theo.ROui d'actualiser toutes les feuilles en même temps.
      Ce document est envoyé à différents gestionnaires dans les services pour qu'ils puissent suivre les évolutions de leurs dépenses par service (chaque feuille = un service).
      Aujourd'hui il est présenté comme ça car c'était la demande des gestionnaires justement de l'avoir sous cette forme.
      Moi qui le prépare, je mets plus de temps à attendre le rafraîchissement des formules et l'enregistrement du document, qu'à sortir l'extraction globale informatiquement.
      J'ai une macro (trouver sur internet) qui me permet de copier-coller toutes les valeurs en un clic avant la diffusion.
      0
    4. Ok très bien.

      On peut essayer de programmer en VBA une macro qui permettent de remplir chaque onglet à partir d'un bouton d'actualisation. A voir si le traitement via Macro est plus rapide que par formule..

      Je commence à regarder tes formules dans le détail.
      0
    5. Merci
      0
  4. Contributeur
    Bonjour

    par formule, ça va être difficile d'alléger. Il faudra passer en VBA et vous allez sans problème trouver quelqu'un pour vous aider. (Je ne suis pas spécialiste)
    Deux remarques toutefois pour aider celui qui va plancher sur le sujet

    1°) en attendant,vous pouvez simplifier la formule à partir d'excel 2007:

    =SIERREUR(RECHERCHEV(CONCATENER($A$1;C$7;$A8);Données!$A$1:$E$26094;7;0));0)

    2°) votre formule renverra toujours 0, le code étant obligatoirement faux car il va chercher la valeur dans la 7° colonne (;7) d'un champ qui n'en a que 6 (A:E) ???

    crdlmnt

    0
    1. Ah pardon.

      Pour l'exemple, j'ai retiré 2 colonnes 'plus sensibles' dans la feuille de "Données" sans penser à remettre la bonne correspondance dans ma recherchev.
      Normalement, ma somme est bien en ;7; mais effectivement dans l'exemple, elle est en ;5;

      Je laisse également volontairement une zone de recherche plus vaste en nombre de lignes (26094 dans l'exemple), car en fonction du mois ou de l'exercice dont j'extrais les données, j'ai un plus grand nombre de lignes.

      Merci pour la simplification. Je n'avais jamais utilisé la formule SIERREUR.
      0
      1. Contributeur
        Bonjour à tous,

        Effectivement, c'est du Vba... usine à gaz

        Tu m'inquiètes car tu as écris
        Pour l'exemple, j'ai retiré 2 colonnes 'plus sensibles'
        et
        tu parles d'exercices mais dans ta feuille UF, tu es toujours en 2014...

        Merci d'^tre précis (je ne recommence jamais un code lorsque il est répondu: "Ca marche pas.En fait dans la réalité, cela se présente pas comme dans mon exemple...")
        0
        1. Contributeur
          1°analyse

          chaque résultat d'une UF est envoyé à son responsable:
          Il serait peut-^tre + judicieux et rapide d'envoyer 1 classeur/uf à sin responsable plut^t qu'un classeur énorme à tout le monde surtout qu'un classeur "énorme" risque d'^tre "corompu" et ne plus fonctionner
          0
        2. @michel_mPourquoi ne pas donner son n° de réf à chaque service (ex: 3310) qu'il suffirait de rentrer en A1.

          Ainsi, de ton côté, tu te contentes de faire l'extraction avant d'envoyer le doc qui ne comprendrait que deux feuilles (celle de données et celle vierge qui se remplit quand on met la ref)

          Non?
          0
        3. Oui plus sensible dans le sens où il y avait des noms et libellés professionnels.
          0
        4. @thibaut_francoisJe suis dans un centre hospitalier. Et le découpage se fait par pôle. Un pôle est composé de services. A chaque service, on attribue un N° d'UF (unité fonctionnelle ex : 3310). Quand j'envoie le document au gestionnaire du pôle X, il lui faut l'ensemble des services de son pôle. Ce qui peut représenter 20 à 30 services.
          Et du coup, c'est pas simple...
          0
        5. @thibaut_francoisTheo.R, ça peut être une solution en effet !
          0
      2. Modérateur
        Bonjour tout le monde,
        Mes meilleurs voeux à tous,

        Je me joindrais bien à votre collège de VBA'ïstes, si vous le permettez, le challenge à relever étant intéressant.

        Ma question du jour ira tout droit au demandeur thibaut_françois.
        Ton fichier originale comporte 7 colonnes, peux tu nous en donner les intitulés et savoir à quoi elles correspondent?
        Exemple :
        Colonne A : NOMS
        Colonne B : Prénoms
        etc...
        Puisque tu ne connais pas le VBA, ce sera plus facile de te "délivrer" un code fonctionnel du premier coup...
        0
        1. Les 2 colonnes suivantes sont le nom du service et le nom du site.
          Les intitulés exactes de l'extraction sont "Libellé Uf" et "Site".
          0
        2. Modérateur
          @thibaut_francoisUn truc que je n'ai pas pigé... Désolé.
          S'il s'agit d'une extraction informatique, que se passe t'il à chaque extraction?
          Tu obtiens un fichier excel qui comporte les données de l'année en cours ou qui cumule sur plusieurs années?
          0
        3. @pijakuJ'ai la possibilité de choisir l'année et les mois.
          Pour une année complète, avec tous les pôles, j'ai un fichier .txt de 87437 lignes. Et donc je ne peux plus l'ouvrir sous excel.
          Quand je rafraîchis la requête informatique, j'enregistre le résultat sur un fichier .txt (toujours le même)
          Et ce que je fais, c'est une importation du fichier .txt dans access (sous forme de table attachée), qui me permet de redécouper par pôle (par une requête sélective).
          0
        4. Modérateur
          @thibaut_francois j'ai un fichier .txt de 87437 lignes. Et donc je ne peux plus l'ouvrir sous excel.
          Tu aurais pu le dire plus tôt...

          Peut-on avoir accès à ce fichier txt?
          0
      3. Contributeur
        Bonjour

        Confirmation?

        1 UF n'appartient qu' à 1 seul p^le sur 1 seul site ?

        mensuellement, mois un code champ d'une Uf est utilisé qu'une fois ?

        je serai absent à partir de vendredipour au moins 6 jours, donc merci de réagir rapidement

        2 phases proposées ???
        1/construction des classeurs annuels par pole et par site soit 2 classeurs avec chacun ses UF

        2/pour chaque UF , sélection des lignes de cette UF par SQL et répartition des dépenses
        l'UF donnant le classeur
        les classeurs dans le m^me répertoire

        Version Excel ???
        Michel
        0
        1. Oui une UF n'appartient qu'à 1 site et qu'à 1 pôle.
          Mais un pôle est composé d'Uf des 2 sites. On dit que le pôle est multi-site.

          Par contre, je ne comprends pas ta demande question "mensuellement, mois un code champ d'une Uf est utilisé qu'une fois ? "
          0
        2. Oui version excel
          0
        3. @thibaut_francoisJe suppose qu'il voulait savoir QUELLE version excel ^^
          0
        4. @Theo.RHa ^^ 2003 pardon
          0
      4. Contributeur
        OK, ca avance...mais peut-^tre un probleme + tard car on ne peut tester que sur 1 pole 0004 et un site A (UF 3310 à 3315)

        on verra !
        0
        1. Je suis obligé de découper mon extraction informatique par pôle, à cause des limites excel malheureusement (60 000 lignes).
          Pour une année complète, avec tous les pôles, j'ai un fichier .txt de 87437 lignes. Et donc je ne peux plus l'ouvrir sous excel.
          0
      5. Contributeur
        Super-chiant ces discussions dans tous les coins !!! :-((

        Ainsi j'apprend en reparcourant pour la N°ième fois l'historique que les données sont importées sur Access
        donc^pour simplifier peut-^tre le problème, il es facile de faire des requ^tes dans Access avec soirt le domaine-site soit l'uf
        faudrait donc voir cette base
        mais, par pitié, pourquoi distiller les informations au compte-gouttes ? :-(((
        ET MERCI d'ENVOYER ENFIN UNE FEILLE DE DONNES CONFORME A LA REALITE COMME DEMANDE(colonne "Site rempli A B C...)

        ca sent l'abandon du suivi pour moi...

        Michel
        0
        1. Désolé Michel, mais pour ma défense, la discussion est partie plus loin que ma demande initiale... qui en fin de compte était de remplacer ma formule recherchev par une macro pour alléger mon fichier excel.
          Apparemment, je pars de tellement loin par rapport aux capacités d'exécution que le fil de la discussion a un peu dérivé...
          Peux-tu en rester à ton dernier message du 20 janv. 2015 à 15:36 stp ? Ca m'aiderait vachement.
          0
      6. Modérateur
        Bonjour,

        Effectivement, ça part dans tous les sens, alors je pense qu'une petite récap serait la bienvenue.

        Tu disposes d'un fichier txt, suite à une extraction d'un logiciel x (qui ne fait pas partie de la suite Microsoft office).
        Ce fichier txt comprends 8 colonnes qui sont, dans l'ordre (et toujours dans cet ordre?)
        Lettre
        Compte
        Exercice
        Mois
        Uf
        Depense
        Pole
        Site


        Toi, à partir du fichier txt, tu dois remplir une feuille par UF avec les sommes de leurs dépenses rangées par mois et par compte puis envoyer le tout à chaacun des responsables.

        Ce que peut faire la macro selon le mois choisi :
        - créer un répertoire dans ton ordi pour les sauvegardes,
        - Remplir une feuille par UF avec toutes les colonnes complétées jusqu'au mois choisi,
        - Enregistrer cette feuille comme nouveau classeur dans le répertoire créé.

        Subsidiaire : La macro peut également envoyer, par mail, le classeur composé d'une feuille (l'UF concerné) à chacun des destinataires.

        Est ce exact?

        ps : n'oublie pas ma question en gras ainsi que le subsidiaire si intéressé.
        0
        1. C'est tout à fait ça. Et toujours dans cet ordre.
          Pas besoin du subsidiaire... Toute la 1ère partie, ça serait déjà top.
          0
      7. Contributeur
        Bonjour,
        au 38° message, on ne sait toujours pas ce qu'on doit faire (N poles avec N sites et N uf ? )avec toujours une livraison incomplète (données) malgré plusieurs demandes.
        Bref, un manque total de sérieux...
        0
        1. Modérateur
          Il me reste trois/quatre trucs à modifier et à tester ma macro avant livraison mais....
          Il ne faut pas mettre de côté l'idée de Michel qui consiste à passer par Access. Cette méthode permettra, à mon avis, de rester fiable dans le temps et l'évolution de tes fichiers.

          A titre d'exemple, ma macro se base sur ton fichier Excel, et notamment sur la liste des comptes fournis dans la feuille UF. Pour l'instant, elle ne permet pas l'ajout, dans cette feuille UF, d'un nouveau compte. Cela peut effectivement se produire et donc rendre ma macro inopérante.
          0
          1. Ok. Je vois ce que tu veux dire.
            0
          2. Modérateur
            @thibaut_francoisAutre point important (ô combien)...
            Apparemment, selon mes calculs (qui sont bien souvent très approximatifs), ma macro nécessite au moins 3Go de mémoire RAM sur le pc...
            0
          3. @pijakuC'est bon de ce côté.
            0
          4. Modérateur
            @thibaut_francoisOui, mais NON!
            Une macro qui nécessite autant de RAM et qui n'est pas évolutive n'est bonne qu'à être jetée aux orties.
            Si j'en suis arrivé à un tel résultat c'est uniquement à cause de ma fainéantise et de l'option facilité que j'ai choisi initialement.

            Je n'ai plus qu'à revoir mon travail avant de te rendre ma copie.

            En tout cas, j'espère avoir une bonne note ;-)
            0
        2. Modérateur
          Bonjour,

          Un nouveau problème se pose aujourd'hui.....

          Dans le fichier txt que tu as transmis, tous les comptes listés dans la feuille UF de ton classeur ne sont pas représentés. Ce n'est effectivement pas grave dans ce sens.
          Par contre, dans ta feuille UF, il manque des numéros de compte présents dans ton fichier txt...
          Est ce normal???

          En voici la liste :
          https://www.cjoint.com/c/EAwlwep2ba3
          0
          1. Modérateur
            Autre souci, dans le fichier structure.xls que tu donnes précédemment, il y a 252 UF répertoriés.
            Or, dans le fichier txt que tu nous transmet, il y en a 362...
            110 UF de plus, c'est pas rien... ça représente 1/3 de fichiers en plus, ou en moins...
            0
          2. Contributeur
            Bon courage, Frank !
            moi je laisse tomber vu l'attitude négligente de ce monsieur...
            0
          3. Modérateur
            @michel_mSalut Michel,

            moi je laisse tomber vu l'attitude négligente de ce monsieur...
            Je ne pense pas qu'il s'agisse de négligence mais plutôt de méconnaissance.
            - méconnaisse des possibilités offertes par VBA,
            - méconnaisse du logiciel Access.

            Je vais donc continuer, ma solution étant aujourd'hui en phase de tests.
            Cependant, les tests sont compromis par mes deux questionnements du jour.

            C'est toutefois dommage, mais je comprends ton abandon, de ne pas pouvoir comparer les méthodes.
            Notamment la méthode via SQL (que je ne maîtrise pas du tout) m'aurait intéressé.
            Celle d'une extraction d'access via requête aurait sans doute été idéale pour le demandeur.

            Pour info, lors du premier test de ma macro, j'obtiens des temps relativement longs 7 minutes 30 pour obtenir les 365 fichiers (un par UF) demandés... C'est long, peut être trop long.

            Enfin, à voir...
            0
          4. @pijakuLe document demandé est à destination des chefs pôles. On lui met donc à disposition les comptes sur lesquels le pôle à la main... sur lesquelles ils sont réellement responsables de l'état des dépenses. C'est pour ça que le document est restrictif au niveau des comptes et que tous n'apparaissent pas.
            Il en est de même pour les Uf. Certaines Uf sont purement comptables. Elles ne concernent pas les pôles.
            Ne tient pas compte des Uf et des comptes non répertoriés.
            Merci pijaku.
            0
        3. Bonjour

          modif de la macro
          mettre le Uf en string

          Sub test()
          Dim Uf As String
          Dim Compte As String
          Application.ScreenUpdating = False
          Nlig = Feuil7.Range("A" & Rows.Count).End(xlUp).Row
             For L = 2 To Nlig
                Uf = Feuil7.Range("F" & L).Text
                Depense = Feuil7.Range("E" & L).Value
                Mois = Feuil7.Range("D" & L).Value
                Compte = Feuil7.Range("B" & L).Text
                Col = Mois + 2
                Sheets("UF " & Uf).Select
                   For L1 = 8 To 239
                      If Range("A" & L1).Text = Compte Then
                         Cells(L1, Col).Value = Depense
                      End If
                   Next
             Next
          End Sub
          


          voila tu a du boulot avec toutes les reponses

          A+
          Maurice
          0
          1. Huum, même problématique Maurice.
            Sur ma feuille "3310", il me met toujours les chiffres attendus sur la feuille "3314".
            Et les autres feuilles restent vierge.s
            0
        4. Bonjour

          A bon
          regarde sur mon modele si ca va mieux

          http://cjoint.com/?3AxrRu8wVbD

          A+
          Maurice
          0
          1. J'ai collé ton VBA dans ton fichier joint. Mais toujours pareil Maurice.
            Sorry
            0
        5. Modérateur
          Bonjour,

          Je suis en train de tester la version finale, avec envoi automatique des emails.
          Déjà, premier constat, c'est long....

          Ensuite, au vu du nombre et de la taille des fichiers à joindre aux mails, nous risquons de nous heurter aux capacités maximales de ta boîte mail.
          Peux tu me dire combien est la limite de "poids" des fichiers que tu peux envoyer et recevoir, pour un mail?
          0
          1. Réponse tardive, désolé.
            Capacité max de 15Mo. Après je bloque et je dois faire du nettoyage pour envoyer de nouveau mail.
            0
        6. Modérateur
          Bon.

          Il va te falloir tester, retester et reretester, mais ce fichier à l'air fonctionnel...

          Le fichier : exemple

          !!! ATTENTION !!! : Avant la première utilisation, il faut activer la référence "Microsoft Outlook XX.0 Object Library"
          Dans l'éditeur VBA: Faire Menu Outils / Reference / Cocher "Microsoft Outlook XX.0 Object Library"

          Le code :

          Option Explicit
          'Il faut activer la référence "Microsoft Outlook XX.0 Object Library"
          
          'Déclaration des variables de portée "modulaire" (utilisées dans plusieurs fonctions)
          Dim DonneesGlobales() As Variant
          Dim DicoUfTxt As Object
          Dim DicoCptes As Object
          Dim DicoUfFeuil As Object
          Dim DicoPoles As Object
          Dim Sommes() As Double
          Dim CodeErreur As Byte
          Dim Temps, TpsMails
          
          '********************************************************************************************************************************************
          
          Sub Principale()
          'Sub servant à lancer toutes les fonctions, dans l'ordre.
          Dim Elem As Variant
          Dim Chemin As String, Racine As String, ChemTxt As String, Recap As String
          Dim Mois As Integer, Annee As Integer
          Dim Nb As Long
          Dim AppOutlk As New Outlook.Application
          
              'Vérifie, avant de lancer le bouzin, qu'Outlook est ouvert
              Set AppOutlk = New Outlook.Application
              If AppOutlk.Explorers.Count = 0 Then
                  MsgBox "Merci d'ouvrir votre messagerie Outlook.": Exit Sub
              End If
              
              Application.ScreenUpdating = False
              'Initialisation des variables
              If InitVariables(ThisWorkbook, Chemin, Racine, ChemTxt, Mois, Annee) = False Then MsgBox MsgErreur, vbInformation: Exit Sub
              'Création du répertoire (ex : UF's  10 2014 21_01_2015 12_05) ou stocker tous les fichiers (ex : UF_3211 10_2014.xls)
              If CreationRepertoire(Chemin) = False Then MsgBox MsgErreur(Chemin), vbInformation: Exit Sub
              'collecte les données du fichier txt
              DonneesGlobales = CollectDonnees(ChemTxt)
              If CodeErreur > 0 Then MsgBox MsgErreur, vbInformation: Exit Sub
              'boucle sur tous les UF
              For Each Elem In DicoUfTxt.Keys
                  'Dimensionnement de la variable tableau Sommes
                  Sommes = DimSommes(DicoCptes.Count)
                  If CodeErreur > 0 Then MsgBox MsgErreur, vbInformation: Exit Sub
                  'calcule la somme de l'UF en cours, par compte, pour le mois et l'année donnée
                  If CalculSommesParComptes(Elem, Mois, Annee) = False Then MsgBox MsgErreur, vbInformation: Exit Sub
                  'efface les données de la feuille UF
                  If ClearRange(QuelRange(Sheets("UF"))) = False Then MsgBox MsgErreur, vbInformation: Exit Sub
                  'remplit la feuille UF
                  If RempliUF(Sheets("UF")) = False Then MsgBox MsgErreur, vbInformation: Exit Sub
                  'Crée, enregistre et ferme le classeur (ex : UF_3211 10_2014.xls)
                  If CreeClasseurs(Sheets("UF"), Chemin, Elem, Mois, Annee, ThisWorkbook, CStr(Split(DicoUfFeuil(Elem), "¤")(0))) = False Then MsgBox MsgErreur("UF " & Elem & " " & Mois & " " & Annee), vbInformation: Exit Sub
              Next
              If EnvoiMails(ThisWorkbook.Name, Chemin, Mois, Annee) = False Then MsgBox MsgErreur, vbInformation
              Application.ScreenUpdating = True
              
          End Sub
          
          '********************************************************************************************************************************************
          
          Function InitVariables(Wbk As Workbook, Chem As String, Rac As String, RacTxt As String, intMois As Integer, intAnnee As Integer) As Boolean
          'Initialise les variables (entre parenthèses, leurs noms dans les paramètres de la fonction) :
              '- Chemin (Chem) : accès complet au répertoire qui sera créé pour stocker les fichiers UF's
              '- Racine (Rac) : accès complet au répertoire de ce classeur (pour y créer le sous-répertoire Chemin)
              '- RacineTxt (RacTxt) : chemin complet d'accès au fichier txt
              '- Mois (intMois) : Mois maxi
              '- Annee (intAnnee) : Année choisie
          Dim Sep As String, maVar As Variant, Cpt As Integer
          
              On Error GoTo Fin
              CodeErreur = 0
              Sep = Application.International(xlDecimalSeparator)
              Cpt = 0
              Do
                  Cpt = Cpt + 1
                  If Cpt = 4 Then GoTo Fin
                  maVar = Application.InputBox("Mois (saisir un nombre entre 1 et 12) : ", "Saisie du mois", Type:=1)
                  If maVar < 1 Or maVar > 12 Then
                      MsgBox "Saisir un nombre entre 1 et 12."
                  ElseIf InStr(maVar, Sep) > 0 Then
                      MsgBox "Saisir un nombre entier."
                  Else
                      intMois = maVar
                      Exit Do
                  End If
              Loop
              Cpt = 0
              Do
                  Cpt = Cpt + 1
                  If Cpt = 4 Then GoTo Fin
                  maVar = Application.InputBox("Année (saisir un nombre entre 1900 et 2100) : ", "Saisie de l'année", Type:=1)
                  If maVar < 1900 Or maVar > 2100 Then
                      MsgBox "Saisir un nombre entre 1900 et 2100."
                  ElseIf InStr(maVar, Sep) > 0 Then
                      MsgBox "Saisir un nombre entier."
                  Else
                      intAnnee = maVar
                      Exit Do
                  End If
              Loop
              MsgBox "La prochaine boîte de dialogue vous invite à choisir le fichier txt à importer."
              RacTxt = Application.GetOpenFilename("Fichiers txt, *.txt")
              If RacTxt = "Faux" Then GoTo Fin
              With Wbk
                  Rac = .Path & "\"
              End With
              Chem = Rac & "UF's " & intMois & " " & intAnnee & " " & Format(Now, "dd_mm_yyyy hh_mm")
              InitVariables = True: Exit Function
          Fin:
              InitVariables = False: CodeErreur = 1
          End Function
          
          '********************************************************************************************************************************************
          
          Function CreationRepertoire(Chem As String) As Boolean
          'Fonction créant le répertoire de sauvegarde des fichiers UF's
          
              On Error GoTo Fin
              If Dir(Chem, 16) = "" Then MkDir Chem
              CreationRepertoire = True: Exit Function
          Fin:
              CreationRepertoire = False: CodeErreur = 2
          End Function
          
          '********************************************************************************************************************************************
          
          Function CollectDonnees(ChemFicTxt As String) As Variant()
          'Fonction qui va lister les infos contenues dans le fichier txt
              '- toutes les données des 6 premières colonnes (DonneesGlobales)
                  'DonneesGlobales(1, x) = lettre
                  'DonneesGlobales(2, x) = N° de compte
                  'DonneesGlobales(3, x) = Exercice (Année)
                  'DonneesGlobales(4, x) = Mois
                  'DonneesGlobales(5, x) = Réf d'UF
                  'DonneesGlobales(6, x) = Dépense
              '- les numéros des comptes (DicoCptes)
              '- les références des UF dans le ,fichier txt (DicoUfTxt)
              '- les références des UF "utiles" dans la Feuil1 (DicoUfFeuil)
          Dim Ligne As String, TbTemp(), Tb()
          Dim num As Long, i As Long, j As Long, Cpt As Integer, DL As Long
          
              On Error GoTo Fin
              Set DicoCptes = CreateObject("Scripting.Dictionary")
              Set DicoUfTxt = CreateObject("Scripting.Dictionary")
              Set DicoUfFeuil = CreateObject("Scripting.Dictionary")
              DL = Sheets("Feuil1").Range("P" & Rows.Count).End(xlUp).Row
              Tb = Sheets("Feuil1").Range("O2:Q" & DL).Value
              For i = LBound(Tb) To UBound(Tb)
                  DicoUfFeuil(CStr(Tb(i, 2))) = Tb(i, 1) & "¤" & Tb(i, 3)
              Next i
              'permet de retrouver le 1er numéro libre de désignation d'un fichier
              num = FreeFile
              'ouvre le fichier en lecture
              Open ChemFicTxt For Input As #num
              'boucle tant que l'on n'a pas atteint la fin du fichier
              While Not EOF(1)
                  Line Input #1, Ligne
                  If Left(Ligne, 6) <> "Lettre" Then
                      Ligne = Replace(Ligne, Chr(160), "")
                      j = j + 1
                      ReDim Preserve TbTemp(1 To 6, 1 To j)
                      For i = 1 To 6
                          TbTemp(i, j) = Split(Ligne, Chr(9))(i - 1)
                      Next i
                      If TbTemp(6, j) = "" Then TbTemp(6, j) = 0
                      If Not DicoCptes.exists(CLng(TbTemp(2, j))) Then
                          Cpt = Cpt + 1
                          DicoCptes(CLng(TbTemp(2, j))) = Cpt
                      End If
                      If DicoUfFeuil.exists(CStr(TbTemp(5, j))) Then DicoUfTxt(TbTemp(5, j)) = ""
                  End If
              Wend
              Close #num
              CollectDonnees = TbTemp: Exit Function
          Fin:
              CodeErreur = 3
          End Function
          
          '********************************************************************************************************************************************
          
          Function DimSommes(maxi As Long) As Double()
          'Dimensionne la variable Sommes()
              'cette variable va permettre de stocker les sommes des dépenses de chaque compte
          Dim TbTemp() As Double
          
              Erase Sommes
              On Error GoTo Fin
              ReDim Preserve TbTemp(1 To maxi, 1 To 12)
              'La variable Sommes va se présenter comme ceci :
                  'Sommes(Compteur, Mois) ou compteur = DicoCptes(Numéro_Du_Compte)
              DimSommes = TbTemp
              Exit Function
          Fin:
              CodeErreur = 4
          End Function
          
          '********************************************************************************************************************************************
          
          Function CalculSommesParComptes(UF As Variant, Mois As Integer, Annee As Integer) As Boolean
          'remplit la variable Sommes() en calculant les sommes des dépenses :
              '- jusqu'au mois choisi,
              '- en évitant les années différentes de celle choisie
          Dim i As Long
          
              On Error GoTo Fin
              For i = 1 To UBound(DonneesGlobales, 2)
                  'Vérification si l'année (DonneesGlobales(i, 3)) égale à l'année choisie
                  If CInt(DonneesGlobales(3, i)) = Annee Then
                      'Vérification si mois (DonneesGlobales(i, 4)) inférieur ou égal au mois choisi
                      If CInt(DonneesGlobales(4, i)) <= Mois Then
                          'Calcul la somme et la stocke dans la variable Sommes()
                              'DonneesGlobales(i, 5) = Numéro d'UF
                              'DonneesGlobales(i, 2) = Numéro de compte
                              'DonneesGlobales(i, 4) = Mois
                              'DonneesGlobales(i, 6) = dépense
                              'Rappel :
                                  'La variable Sommes va se présenter comme ceci :
                                  'Sommes(Compteur, Mois) ou compteur = DicoCptes(Numéro_Du_Compte)
                          'si c'est le bon UF
                          If DonneesGlobales(5, i) = UF Then Sommes(DicoCptes(CLng(DonneesGlobales(2, i))), DonneesGlobales(4, i)) = Sommes(DicoCptes(CLng(DonneesGlobales(2, i))), DonneesGlobales(4, i)) + DonneesGlobales(6, i)
                      End If
                  End If
              Next i
              CalculSommesParComptes = True
              Exit Function
          Fin:
              CalculSommesParComptes = False: CodeErreur = 5
          End Function
          
          '********************************************************************************************************************************************
          
          Function QuelRange(Wsh As Worksheet) As Range
          'Sélection de la plage de cellule, dans la feuille UF, à effacer
          'en fonction de la colonne A (si contient n° de compte)
          Dim DL As Long, Lig As Long, strRange As String
          
              On Error GoTo Fin
              With Wsh
                  DL = .Range("A" & Rows.Count).End(xlUp).Row
                  Set QuelRange = .Range("C8:N8")
                  For Lig = 9 To DL
                      If .Cells(Lig, 1) <> "" And IsNumeric(.Cells(Lig, 1)) Then Set QuelRange = Union(QuelRange, .Range("C" & Lig & ":N" & Lig))
                  Next Lig
              End With
              If QuelRange Is Nothing Then GoTo Fin
              Exit Function
          Fin:
              CodeErreur = 6
          End Function
          
          '********************************************************************************************************************************************
          
          Function ClearRange(Rng As Range) As Boolean
          'Efface la plage de cellules sélectionnée dans la fonction QuelRange
          
              On Error GoTo Fin
              Rng.ClearContents
              ClearRange = True: Exit Function
          Fin:
              ClearRange = False: CodeErreur = 7
          End Function
          
          '********************************************************************************************************************************************
          
          Function RempliUF(Sh As Worksheet) As Boolean
          'Remplit la feuille UF des données recueillies dans la variables Sommes()
          Dim Lig As Long, DLigUF As Long, Col As Integer
          
              On Error GoTo Fin
              With Sh
                  DLigUF = .Range("A" & Rows.Count).End(xlUp).Row
                  For Lig = 8 To DLigUF
                      If .Cells(Lig, 1) <> "" Then
                          For Col = 3 To 14
                              'If Sommes(DicoCptes(.Cells(Lig, 1)), Col - 2) = "" Then Codes(.Cells(Lig, 1), Col - 2) = 0
                              If Not DicoCptes.exists(CLng(.Cells(Lig, 1))) Then
                                  Exit For
                              Else
                                  .Cells(Lig, Col) = Sommes(DicoCptes(CLng(.Cells(Lig, 1))), Col - 2)
                              End If
                          Next Col
                      End If
                  Next Lig
              End With
              RempliUF = True: Exit Function
          Fin:
              RempliUF = False: CodeErreur = 8
          End Function
          
          '********************************************************************************************************************************************
          
          Function CreeClasseurs(Sh As Worksheet, Chem As String, Element As Variant, intMois As Integer, intAnnee As Integer, WbkSource As Workbook, NomRecap As String) As Boolean
          'Fonction qui va :
              '- Copier la feuille UF dans un nouveau classeur
              '- Renommer cette feuille en : UF xxxx ou xxxx est le numéro d'UF
              '- enregistrer sous ce nouveau classeur (exemple de nom : UF_3211 10_2014.xls)
              '- copier cette feuille dans le classeur "récap" par pole.
                  '- si ce classeur récap n'est pas créé alors on le créé
              '- fermer ce classeur
              '- Activer le classeur de la macro pour continuer avec un autre UF
          Dim WbkUF As Workbook, WbkRecap As Workbook
          
              On Error GoTo Fin
              With Sh
                  .Copy
              End With
              Set WbkUF = ActiveWorkbook
              With ActiveSheet
                  .Name = "UF_" & Element
                  WbkUF.SaveAs Chem & "\UF_" & Element & " " & intMois & "_" & intAnnee & ".xls"
                  On Error GoTo 0
                  On Error GoTo NewClassRecap
                  .Copy After:=Workbooks(NomRecap).Sheets(Sheets.Count)
                  On Error GoTo 0
                  On Error GoTo Fin
                  WbkUF.Close
              End With
              WbkSource.Activate
              CreeClasseurs = True: Exit Function
              
          NewClassRecap:
              With ActiveSheet
                  .Copy
                  ActiveWorkbook.SaveAs Chem & "\" & NomRecap & ".xls"
              End With
              WbkUF.Close
              WbkSource.Activate
              CreeClasseurs = True: Exit Function
          Fin:
              CreeClasseurs = False: CodeErreur = 9
          End Function
          
          '********************************************************************************************************************************************
          
          Function EnvoiMails(NomFic As String, Chem As String, Mois As Integer, Annee As Integer) As Boolean
          'Source : http://forum.excel-pratique.com/cours-astuces/excel-outlook-envoi-mail-t29003.html
              Dim ObjOutlook As New Outlook.Application
              Dim oBjMail
              Dim Nom_Fichier As String, Destinataire As String
              Dim Wb As Workbook, Ws As Worksheet
          
              On Error GoTo Fin
              Set ObjOutlook = New Outlook.Application
              For Each Wb In Application.Workbooks
                  If Wb.Name <> NomFic Then
                      With Wb
                          .Activate
                          .Save
                      End With
                      Set oBjMail = ObjOutlook.CreateItem(olMailItem)
                      Nom_Fichier = Chem & "\" & Wb.Name
                      Destinataire = Split(DicoUfFeuil(Right(ActiveSheet.Name, 4)), "¤")(1)
                      If Nom_Fichier = "" Then EnvoiMails = False: Exit Function
                      With oBjMail
                          .To = Destinataire
                          .Subject = "Fichiers UF, extraction de " & Mois & " " & Annee          ' l'objet du mail
                          .Body = "Bonjour," & vbCrLf & vbCrLf & "Veuillez trouver ci-joint les fichiers UF vous concernant." & vbCrLf & vbCrLf & "Cordialement."  'le corps du mail ..son contenu
                          .Attachments.Add Nom_Fichier
                          For Each Ws In Wb.Worksheets
                              Nom_Fichier = Chem & "\" & Ws.Name & " " & Mois & "_" & Annee & ".xls"
                              .Attachments.Add Nom_Fichier
                          Next
                          .Send
                      End With
                      Wb.Close
                  End If
              Next
              Set oBjMail = Nothing
              Set ObjOutlook = Nothing
              EnvoiMails = True: Exit Function
          Fin:
              Set oBjMail = Nothing
              Set ObjOutlook = Nothing
              EnvoiMails = False: CodeErreur = 10
          End Function
          
          '********************************************************************************************************************************************
          
          Function MsgErreur(Optional Msg As String) As String
          'Fonction de traitement des différentes erreurs possibles ou imaginaires
              'En cas d'erreur, revenir sur le forum avec le numéro d'erreur ET le message complet
          
              Application.ScreenUpdating = True
              Select Case CodeErreur
                  Case 1: MsgErreur = "Erreur n° 1 : " & vbCrLf & "Fonction InitVariables"
                  Case 2: MsgErreur = "Erreur n° 2 : " & vbCrLf & "Fonction CreationRepertoire" & vbCrLf & Msg
                  Case 3: MsgErreur = "Erreur n° 3 : " & vbCrLf & "Fonction CollectDonnees"
                  Case 4: MsgErreur = "Erreur n° 4 : " & vbCrLf & "Fonction DimSommes, vérifier Mémoire et/ou variable maxi (DicoCptes.Count)"
                  Case 5: MsgErreur = "Erreur n° 5 : " & vbCrLf & "Fonction CalculSommesParComptes. Problème dans les données initiales (exemple : montant dépense = """")."
                  Case 6: MsgErreur = "Erreur n° 6 : " & vbCrLf & "Fonction QuelRange"
                  Case 7: MsgErreur = "Erreur n° 7 : " & vbCrLf & "Fonction ClearRange"
                  Case 8: MsgErreur = "Erreur n° 8 : " & vbCrLf & "Fonction RempliUF"
                  Case 9: MsgErreur = "Erreur n° 9 : " & vbCrLf & "Fonction CreeClasseurs" & vbCrLf & Msg
                  Case 10: MsgErreur = "Erreur n° 10 : " & vbCrLf & "Fonction EnvoiMails"
                  Case Else: MsgErreur = "Erreur inconnue." & vbCrLf & "Voir ça avec le forum, ça va pas être simple..."
              End Select
          End Function
          
          0
          1. Bonjour,

            Hé béh ^^ Je regarde demain dès mon arrivée au boulot.

            Merciiiii
            0
          2. @thibaut_francoisPIouf Piouf Piouf ! Ca déglingue !
            Merci merci

            Juste une chose. Est-il possible de ne pas laisser ouvert les récap des pôles. De faire comme pour les fichiers UF, c'est à dire qu'ils s'enregistrent et se ferment.

            J'ai eu une erreur sur le mailing. Mais je referai un test demain sur mon adresse perso pour voir.
            0
          3. Modérateur
            @thibaut_francoisBonjour,

            Est-il possible de ne pas laisser ouvert les récap des pôles.
            Chez moi, la macro se déroule ainsi :
            Durant l'exécution, et ceci afin de ne pas avoir à ouvrir et fermer les fichiers recap à chaque fichier UF, les récap's restent ouverts. Lors de l'envoi des e-mails ils se ferment alors successivement.

            Donc...

            Par contre, je vais modifier sensiblement le déroulement de la macro pour qu'elle fasse ceci :
            sur la feuille 3 boutons :
            - Créer Récap's = Va créer les x fichiers recap
            - Créer UF's = Va créer les fichiers UF à partir des récaps
            - Envoyer mails = ben euh... envoi des mails

            Cela permettra de répartir le temps d'exécution qui est très long et de pouvoir reprendre n'importe ou en cas de plantage...

            Mais pas tout de suite...
            0
          4. Ha ok ! C'est peut-être parce le mail n'a pas fonctionné que les fichiers récap sont restés ouverts.

            Très bonne idée les 3 étapes !

            J'suis arrêté 3 jours pour une bonne gastro. Je serai au boulot que lundi. ^^
            0
        7. Pija ?
          0
          1. Modérateur
            Bonjour,
            Oui?
            0
          2. @pijakuBonjour pija.

            Je croyais que tu allais proposé une nouvelle version de la macro dans ton dernier message ^^

            Ou j'ai peut être mal compris ?
            0
          3. Modérateur
            @thibaut_francoisNon non, tu avais bien compris.
            Mais ça c'était avant...
            Avant qu'un virus virulent et sournois s'en prenne à tous mes fichiers...
            Je reviendrais sur ton sujet en début de semaine prochaine lorsque j'aurais réussi à éradiquer le bouzin et surtout récupéré 15 ans de boulot...
            N'hésite pas à me relancer si tu n'as pas de news d'ici mardi.
            a+
            bon week end
            0
          4. @pijakuRooo mince! La galère! J'espère que tu vas récupérer le max!
            Bon week-end
            0
          5. Modérateur
            Salut,

            Finalement je n'ai fait que 2 boutons. Le second était vraiment inutile.
            Voici le fichier : https://www.cjoint.com/c/EBqjAONkpdA
            je n'ai pas pu tester ne disposant pas du fichier txt.
            0