VISUAL BASIC prog

Résolu
Bonjour,

je suis complétement novice en VBA
et je voudrais automatiser certaines opérations répétitives...
voila mon but

A l’ouverture d’une feuille Excel :

L’utilisateur sélectionne des feuilles dans le fichier ouvert :

La macro doit Pouvoir réaliser, dans ces feuilles sélectionné un copier coller
- Des valeurs (seulement)
- Des formats des feuilles
- Si possible des photos éventuels ( optionel) => pas trés important

Et sauvegarder ça dans un autre fichier.

J'aimerais bien avoir certaines pistes, si parmis vous ont des idées .. je suis preneur.

Merci d'avance de votre aide :)

21 réponses

Résumé de la discussion

Le sujet porte sur l'automatisation en VBA d'une opération de copie entre feuilles Excel sélectionnées, avec transfert des valeurs (et éventuellement des formats et des images) vers un fichier distinct à enregistrer. Plusieurs répondants recommandent d'abord enregistrer les opérations pour générer un squelette de code, puis d'utiliser PasteSpecial (xlPasteAll ou valeurs) et d'aliaser les feuilles dans une boucle For afin d'éviter les conflits. Des échanges évoquent des soucis de noms de feuilles lors du duplicata et des questions sur la conservation ou la reproduction des zones d'impression et de la mise en page. D'autres échanges soulignent l'intérêt d'aliaser les références et d'utiliser PasteSpecial pour maîtriser les éléments copiés, notamment les zones imprimables et les noms nommés, afin d'éviter les collisions.

Bobot (l’IA à votre service)
  1. Hello nighthawk,

    Avant d'automatiser, essaie d'enregistrer à la main les opérations que tu veux réaliser.
    Pour ça, utilise l'enregistreur de macro d'Excel, en faisant : Outils/Macro/Nouvelle macro... L'analyse du code généré est très instructive quand on débute en VBA.
    Ensuite, allège ton code et généralise ce qui est particulier.
    Si tu n'y arrives pas, copie ici le code généré, ce sera encore ce qui permettra le mieux de piger ce que tu veux faire
    2
    1. salut Armojax,
      je suis étudiant en stage dans un établissemnet publique je dois creer des module de recheche de miuse a jours et des feuille de rendu de document en utilisant access et vba le probleme c'est que je suis totalement debutant en vba.

      et je ne sat pas par ou commencé.

      es ce que tu pourrais m'aider.

      merci.
      0
  2. Bonjour nighthawk,

    Ta boucle For... devrait ressembler à ça :
    For I = 1 To Nbr
        FicSource.Sheets(NomFeuille(I)).Cells.Copy
        F = F + 1
        If F > Worksheets.Count Then
            Sheets.Add after:=Sheets(Worksheets.Count)
        End If
        Sheets("Feuil" & F).Select
        ActiveSheet.Paste
        Cells.Select
        Application.CutCopyMode = False
        Selection.Copy
        Selection.PasteSpecial Paste:=xlPasteValues
        With ActiveSheet
            .Cells.Copy
            .Name = NomFeuille(I)
            .PageSetup.PrintArea = FicSource.Sheets(NomFeuille(I)).PageSetup.PrintArea
        End With
    Next
    Bonne journée.
    Ajx.
    1
    1. voici ce j'ai obtenu ...

      j'ai quelque soucis :

      1 : la partie
      For Each feuille In Selection.Sheets

      j'ai une erreur sur feuille = >" Erreur d’exécution ‘438’
      Propriété ou méthode non géré par cet objet. " pb sur mot feuille

      je sais pas comment lui dire que c la ou les feuille(s) sélectionné du classeur qu'il faut qu'il prenne en compte.

      2 : je ne sais pas comment faut il lui indiquer qu'il faut qu'il garde la mise en page d'origine.

      3 : comment pouvoir également copier les images du document?

      Sub cut_paste()
      
      Application.ScreenUpdating = False 'désactive la mise à jour de l'écran (accélère l'application)
      
      'For Each feuille In Selection.Sheets
         ' feuille.Activate
      
          Cells.Select
          Selection.Copy
          Workbooks.Add
          Selection.PasteSpecial Paste:=xlValues, Operation:=xlNone, SkipBlanks:= _
              False, Transpose:=False
          Selection.PasteSpecial Paste:=xlFormats, Operation:=xlNone, SkipBlanks:= _
              False, Transpose:=False
          Application.CutCopyMode = False
          ChDir "D:\Download"
      
      'Next feuille
      
      
          ActiveWorkbook.SaveAs Filename:="D:\Download\Classeur1.xls", FileFormat:= _
              xlNormal, Password:="", WriteResPassword:="", ReadOnlyRecommended:=False _
              , CreateBackup:=False
      
      Application.ScreenUpdating = True 'désactive la mise à jour de l'écran (accélère l'application)
      
      End Sub


      merci de votre aide! :)
      0
      1. Hello nighthawk,

        Débutant ? C'est pas mal du tout !

        En fait, la principale difficulté vient de la sélection multiple des feuilles.
        Pour la désigner, il faut utiliser la propriété "SelectedSheets" de la fenêtre.

        Ensuite, on ne peut pas continuer le travail en laissant toutes ces feuilles sélectionnées, car quand on veut copier les feuilles, Excel n'apprécie pas quand il y a une sélection multiple en cours.
        Pour les désélectionner, il faut en activer une qui ne l'est pas. D'où la boucle qui les active toutes les unes après les autres. Il y a plus élégant, mais c'est moins simple.

        On sort le "Workbooks.Add" de la boucle. Sinon, on créerait un nouveau classeur à chaque fois. Ce n'est sans doute pas ce que tu veux.

        Pour éviter de tomber en panne de feuilles dans le nouveau classeur, on les crée dynamiquement si besoin.

        Je n'ai pas testé la sauvegarde du classeur nouveau, qui me paraît correcte.

        Voilà donc une proposition :
        Sub cut_paste()
        
            Application.ScreenUpdating = False
        
            Dim I               As Integer  ' indice pour boucles For
            Dim F               As Integer  ' pour ajout de feuilles si besoin
            Dim Nbr             As Integer  ' nombre de feuilles à copier
            Dim NomFeuille(255) As String   ' noms stockés en table
            
            ' Stockage en table des feuilles à copier
            Nbr = 0
            For Each feuille In ThisWorkbook.Windows(1).SelectedSheets
                Nbr = Nbr + 1
                NomFeuille(Nbr) = feuille.Name
            Next
            
            ' Désactivation de la sélection multiple
            For Each feuille In Worksheets
                feuille.Activate
            Next
            
            ' Ajout nouveau classeur
            Workbooks.Add
            
            ' Boucle de copie
            F = 0
            For I = 1 To Nbr
                ThisWorkbook.Sheets(NomFeuille(I)).Cells.Copy
                F = F + 1
                If F > Worksheets.Count Then
                    Sheets.Add after:=Sheets(Worksheets.Count)
                End If
                Sheets("Feuil" & F).Select
                ActiveSheet.Paste
            Next
        
            ' Sauvegarde du nouveau classeur
            ActiveWorkbook.SaveAs Filename:="D:\Download\Classeur1.xls", FileFormat:= _
                xlNormal, Password:="", WriteResPassword:="", ReadOnlyRecommended:=False _
                , CreateBackup:=False
        
            Application.ScreenUpdating = True
        
        End Sub


        P.S. Comme tu copies tes feuilles entièrement, Excel conserve toutes les mises en forme et les images...
        0
        1. Re,

          Je m'aperçois que j'ai oublié la question du collage des valeurs.
          La copie de la feuille entière copiera tout, y compris les formules si tu en as. Donc, une fois que tu as fait la copie d'une feuille dans le nouveau classeur, copie-la tant que tu l'as sous la main, et fais un collage spécial des valeurs. Toutes les formules de la feuille seront remplacées par les valeurs.

          A+. Ajx.
          0
          1. salut Armojax,
            j'ai testé et retesté ta solution , en essayant de changer des trucs.. mais sans grand succés : voici ce que ça donne :

            Lorsque je ne sélectionne qu'une seule feuille du classeur :
            Il ne me conserve pas la mise en page ( rien que qd je vais ds les options d’impréssion : c plus la meme chose), les images : c bon, il me les copie bien.
            Par contre, il ne me copie pas les valeurs, et me garde en « mémoire » les fonctions que j’ai pu utiliser

            Si je sélectionne 2 feuilles :

            j'ai cette erreur :
            "l'indice n'appartient pas à la sélection"
            a ce niveau là de ton code :
            Sheets("Feuil" & F).Select


            Et la chose la plus chiante : qd je choisis plus de 3 ou 4 feuilles il me met le message suivant :

            Une formule ou une feuille que vous voulez déplacer contient déjà le nom ‘E’ qui existe déjà sur la feuille de destination.
            Voulez vous utiliser cette version de nom ?
            Pr utiliser la version du nom existante cliquez sur oui
            Pr renommer la page etc…. Cliquez sur non


            Après avoir appuié sur entré au moins un bonne trentaine de fois : voir plus, il me copie bien les feuilles mais tjs avec les formules …. ( mais ce qui est bien c qu’il ne me met pas d’erreur si je dépasse 3 feuilles sur mon classeur d’origine) en effet, j’ai pu lire qu’Excel ne créait que 3 feuilles et qu’il fallait utiliser une fonction comme « Application.SheetsInNewWorkbook=..."
            Mais je connais pas du tout la syntaxe.

            je deviens fou...
            en fait, ce que j'avais fait : ça gardait les valeurs et le format, mais pas les images et la mise en page, en plus si je sélectionnais plus de 3 feuilles ça me mettait une erreur du genre pas assez de place etc...

            aurais tu une idée?
            merci d'avance
            0
        2. Rebonjour nighthawk,

          Je ne comprends pas trop ce qui ne fonctionne pas chez toi. Je t'envoie une version légèrement modifiée. Je l'ai testée avec des générations de feuilles, des images, des formules, des mises en forme...

          Les modifications que j'ai faites :

          - la version précédente supposait que ta macro se trouvait dans le classeur source. Cette nouvelle version est faite pour travailler sur le classeur source. Donc, il faut ouvrir le classeur qui contient la macro, puis le classeur source, sélectionner les feuilles à extraire, et lancer la macro tout en laissant le classeur source comme classeur actif.

          - j'ai rajouté le remplacement des formules par les valeurs.

          Si ça ne fonctionne toujours pas, dis-moi quelle version d'Excel tu as.

          Ajx.
          Sub cut_paste()
          
              Application.ScreenUpdating = False
          
              Dim I               As Integer  ' indice pour boucles For
              Dim F               As Integer  ' pour ajout de feuilles si besoin
              Dim Nbr             As Integer  ' nombre de feuilles à copier
              Dim NomFeuille(255) As String   ' noms stockés en table
              Dim FicSource       As Workbook ' classeur source
              
              Set FicSource = ActiveWorkbook
              
              ' Stockage en table des feuilles à copier
              Nbr = 0
              For Each feuille In FicSource.Windows(1).SelectedSheets
                  Nbr = Nbr + 1
                  NomFeuille(Nbr) = feuille.Name
              Next
              
              ' Désactivation de la sélection multiple
              For Each feuille In Worksheets
                  feuille.Activate
              Next
              
              ' Ajout nouveau classeur
              Workbooks.Add
              
              ' Boucle de copie
              F = 0
              For I = 1 To Nbr
                  FicSource.Sheets(NomFeuille(I)).Cells.Copy
                  F = F + 1
                  If F > Worksheets.Count Then
                      Sheets.Add after:=Sheets(Worksheets.Count)
                  End If
                  Sheets("Feuil" & F).Select
                  ActiveSheet.Paste
                  Cells.Select
                  Application.CutCopyMode = False
                  Selection.Copy
                  Selection.PasteSpecial Paste:=xlPasteValues
                  ActiveSheet.Cells.Copy
                  Cells(1, 1).Select
              Next
          
              ' Sauvegarde du nouveau classeur
              ActiveWorkbook.SaveAs Filename:="D:\Download\Classeur1.xls", FileFormat:= _
                  xlNormal
          
              Application.ScreenUpdating = True
          
          End Sub

          0
          1. bonjour
            je voudrais savoir plus des outils offerts par l'environnement visual basic,leurs puissances et leurs limites
            Avec mes meilleurs remerciements
            0
            1. Bonjour Rémi,

              Je peux te faire une réponse partielle, car je n'utilise pas Visual Basic (VB) mais seulement VBA (Visual basic pour Applications).
              Tu peux d'abord aller voir sur ce lien, qui donne d'excellentes pistes.

              http://www.commentcamarche.net/faq/631-%5BVisual-Basic%5D-Liens-utiles

              VBA s'utilise avec les produits de la suite Microsoft, et en pratique principalement (mais pas exclusivement) avec Excel. On peut le conseiller à un utilisateur d'Excel, pour les facilités d'automatisation de tâches personnalisées. Il faut savoir que ce n'est pas portable.

              Si l'usage doit être plus général, il vaut mieux se tourner vers d'autres langages plus adaptés. Dans ce cas, voir aussi :

              http://www.commentcamarche.net/faq/457-Comment-d%E9buter-quel-langage

              Armojax
              0
          2. hello Armojax

            merci de ton aide, j'ai fais des tests, ça marche pas mal, sauf comme je t'ai dit : lorsque je dépasse 4 feuilles sélectionnées par mes soins, il m'affiche le message

            Une formule ou une feuille que vous voulez déplacer contient déjà le nom ‘E’ qui existe déjà sur la feuille de destination.
            Voulez vous utiliser cette version de nom ?
            Pr utiliser la version du nom existante cliquez sur oui
            Pr renommer la page etc…. Cliquez sur non


            si non, nikel

            une question, je peux récupérer le nom des feuilles du document d'origine, pour renommer les feuilles du nouveau document ?
            si oui, vois tu la manière de procéder?

            merci d'avance :)
            0
            1. Hello nighthawk,

              Ça me chagrine, ton message bizarre, je ne vois pas ce qui le provoque. Je n'arrive pas à le reproduire chez moi... Il faudrait dérouler au pas à pas pour voir à quel moment précis ça se produit...

              Pour conserver le nom des feuilles d'origine, il suffit que tu rajoutes la ligne :
              ActiveSheet.Name = NomFeuille(I)
              derrière : ActiveSheet.Cells.Copy
              juste avant le Next.

              Bonne chance.
              Ajx.
              0
          3. re Armojax

            bon pr l'erreur bizarre: j'ai abandonné : je vois pas ce qui fait ça (il m'a retourné le cerveau), c déja trés bien :)
            merci pr le nom des feuilles c bien ce qu'il fallait

            Une question :

            j'aimerais récupérer dans le nouveau document qui est crée que les zones d'impréssions dans les feuilles sélectionnées
            (et si jamais on a pas défini des zones d'impréssions dans ces feuilles: on copie tout dans le nouveau document...)

            je présume qu'on doit remplacer
            ActiveSheet.Cells.Copy

            par un code plus approrié qui ne va copier que les zones d'impréssion défini par le type, si c'est pas le cas on copie tout

            (je me répéte, parceque je sais pas si tu vois ce que je veux dire ou pas? )

            merci :)
            0
            1. re Armojax

              j'essai de chercher .. mais éveidement c faux : dc déja est ce que ceci pourrait etre une piste? ce que j'ai rajouté par rapport au code existant se trouve en italique

              ' Boucle de copie
              F = 0
              For I = 1 To Nbr

              Set feuille = ActiveSheet.PageSetup
              zoneimpression = feuille.PrintArea

              FicSource.Sheets(NomFeuille(I).zoneimpression).Cells.Copy


              F = F + 1
              If F > Worksheets.Count Then
              Sheets.Add after:=Sheets(Worksheets.Count)
              End If
              Sheets("Feuil" & F).Select
              ActiveSheet.Paste
              Cells.Select
              Application.CutCopyMode = False
              Selection.Copy
              Selection.PasteSpecial Paste:=xlPasteValues
              ActiveSheet.Cells.Copy
              Cells(1, 1).Select
              Next

              merci de ton aide
              0
              1. le problème vient de ce qu'il des zones nommées dans
                les feuilles copiées et que les noms sont identiques
                0
                1. Tu dois avoir raison, random, ça doit être ça...
                  Mais je n'arrive pas à le reproduire, même avec des zones nommées portant le nom des feuilles et même aussi le nom du classeur... Alors ?
                  PB de version d'Excel ?
                  Merci en tout cas.
                  Ajx.
                  0
              2. bonjour Armojax

                ta solution marche merci (lors que je veux imprimer , il ne me "prend" que la partie défini par les zones d'impréssions ).

                Mais il y a une chose que je comprends pas! :(
                Normalement la mise en page est également copié, Or quand je veux imprimer le document ce n'est pas la meme disposition:

                je m'explique : un exemple:
                -Sur le document d'origine, la zone d'impréssion défini est un tableau.
                quand je veux l'imprimer, il se met en paysage

                -Sur le document copié, le meme tableau se met en portrait (ce qui fait qu'il est coupé).

                on devrait pas avoir la meme mise en page?

                Question 2 :
                Est ce qu'il moyen de ne copier que les zones d'impréssions définis dans le document d'origine, s'il y en a pas de défini, on copie tout le document.

                merci pr tes lumières :)
                0
                1. Bonjour NightHawk,

                  Dans la macro, remplace :
                  With ActiveSheet
                      .Cells.Copy
                      .Name = NomFeuille(I)
                      .PageSetup.PrintArea = FicSource.Sheets(NomFeuille(I)).PageSetup.PrintArea
                  End With
                  par
                  With ActiveSheet
                      .Cells.Copy
                      .Name = NomFeuille(I)
                  End With
                  With ActiveSheet.PageSetup
                      .PrintArea = FicSource.Sheets(NomFeuille(I)).PageSetup.PrintArea
                      .Orientation = FicSource.Sheets(NomFeuille(I)).Orientation
                  End With
                  1) Normalement, la macro définit la même zone d'impression dans les deux classeurs. Si celle du classeur source est vide, elle l'est aussi dans le classeur de destination. Dans ce cas, Excel copie la totalité des informations contenues dans la feuille.

                  2) Définir une zone d'impression délimite les données qui seront imprimées. C'est différent de la mise en page, qui se paramètre à part. J'ai ajouté la recopie du format (Portrait ou paysage).

                  3) Il se peut que tu aies envie de recopier encore d'autres paramètres. Entraîne-toi à les découvrir tout seul : lance l'enregistreur de macro, et modifie les paramètres. Puis arrête l'enregistreur. Dans le projet VBA, tu as la macro et tu vois quels sont les paramètres modifiables.

                  Bon week-end de Pâques.
                  Ajx.
                  0
                  1. Bonjour Armojax

                    "Entraîne-toi à les découvrir tout seul : lance l'enregistreur de macro, et modifie les paramètres"

                    c'est ce que j'avais essayé de faire pour l'orrientation :)
                    mais sans succés :(

                    j'avais une erreur
                    "Propriété ou méthode non gérée par cet objet"
                    à la ligne
                    .Orientation = FicSource.Sheets(NomFeuille(I)).Orientation


                    j'ai cherché et j'ai trouvé l'erreur
                    .Orientation = FicSource.Sheets(NomFeuille(I)).PageSetup.Orientation

                    tu avais juste oublié PageSetup :)

                    pr ton n°1.
                    je voulais ne pouvoir copier que le contenu de la zone d'impréssion
                    cad : On défini sur la feuille qui contient un tableau + du texte
                    on défini comme zone d'impréssion que le tableau

                    moi je ne veux pouvoir récupérer que le tableau, si je n'avais pas défini la zone d'impréssion, j'aimerais bien récupérer le tableau + texte de la feuille.
                    pr l'instant grace a toi, je récupére les zones d'impréssions plus ce qu'il y a autour (sauf lorsque je réalisé une impréssion : ce qui est normal)

                    merci pr ton aide.
                    0
                    1. Bonjour

                      tjs pas d'idée? :)

                      merci
                      0
                      1. NightHawk,

                        Côté idées, ça va. Mais je n'ai pas passé tout mon W.E. pascal devant mon ordi...

                        Tu vas devoir casser quelques petites choses dans la macro, car la cible se déplace au fur et à mesure qu'on lance les fléchettes.
                        C'est une chose de recopier intégralement une feuille en reconduisant la zone d'impression, et c'en est une autre de ne copier que ce qui est contenu dans la zone d'impression.

                        Quand on recopie toute une feuille, Excel ne fait pas de détail, il reconduit tout : formats, valeurs, formules, largeur des colonnes, hauteur des lignes, images... En revanche, quand on ne copie qu'une plage de cellules – ce qui est le cas de la zone d'impression– il faut préciser certaines choses dans un collage spécial. Quant aux images, elles sont copiées ou non, selon la part de recouvrement par rapport à la plage.

                        Donc, récupère ta zone d'impression, et distingue 2 cas :
                        - Zone vide (PageSetup.PrintArea = "") : copie toute la feuille
                        - Zone existante : copie avec un collage spécial dans lequel tu précises ce que tu veux copier.

                        Restent 2 questions :
                        - Dans la nouvelle feuille, soit tu définis la zone d'impression au même endroit que dans la feuille source, soit tu la ramènes dans le coin supérieur gauche de la feuille
                        - Si tu veux copier aussi les images, soit tu les inclus intégralement dans la zone d'impression, soit tu les colle avec des instructions supplémentaires, en indiquant l'endroit où tu veux les mettre. Pour ça, tu récupères les coordonnées du coin supérieur gauche, par exemple, avec :
                        Sheets("Nomfeuille").ChartObjects(n°).Left (abscisse)
                        Sheets("Nomfeuille").ChartObjects(n°).Top (ordonnée)

                        Bon courage et bonne semaine.
                        Armojax.
                        0
                        1. Bonjour

                          merci pour tes conseils Armojax...

                          j'aurais un tite question sur la syntaxe a appliquer pour réaliser ceci :

                          lorsque j'ai dans mo document des colonnes cachées : ne pas les copier (ou bien les cacher automatiquement aprés les avoir copier )

                          je sais c'est avec cela qu'on sait que c'est caché ou pas

                          Worksheets("Sheet1").Columns("C").Hidden = True


                          Mais je ne vois pas du tout la syntaxe qu'il faut intregré dans ton code :( :

                          ...
                          Nbr = 0
                              For Each feuille In FicSource.Windows(1).SelectedSheets
                                  Nbr = Nbr + 1
                                  NomFeuille(Nbr) = feuille.Name
                              Next
                          
                              For Each feuille In Worksheets
                                  feuille.Activate
                              Next
                              
                              Workbooks.Add
                              
                              F = 0
                          
                           For I = 1 To Nbr
                                  FicSource.Sheets(NomFeuille(I)).Cells.Copy
                                  F = F + 1
                          
                                  If F > Worksheets.Count Then
                                      Sheets.Add after:=Sheets(Worksheets.Count)
                                  End If
                          
                          
                                  Sheets("Feuil" & F).Select
                                  ActiveSheet.Paste
                                  Cells.Select
                                  Application.CutCopyMode = False
                                  Selection.Copy
                                  Selection.PasteSpecial Paste:=xlPasteValues
                          
                              With ActiveSheet
                                  .Cells.Copy
                                  .Name = NomFeuille(I)
                              End With
                          
                              With ActiveSheet.PageSetup
                                  .PrintArea = FicSource.Sheets(NomFeuille(I)).PageSetup.PrintArea
                                  .Orientation = FicSource.Sheets(NomFeuille(I)).PageSetup.Orientation
                                 
                              End With
                              Next
                          ...
                          
                          0
                          1. Hello NightHawk,

                            Si tu utilises souvent "FicSource.Sheets(NomFeuille(I)), tu as intérêt à lui donner un alias, pour alléger :
                            Dim FF As Worksheet en début de procédure,
                            et tu places
                            Set FF=FicSource.Sheets(NomFeuille(I)) après chaque nouvelle valeur de I dans ta boucle.

                            Donc, si tu recopies toute une feuille, tu peux écrire :
                            For N = 1 To 256
                                ActiveSheet.Columns(N).Hidden = FF.Columns(N).Hidden
                            Next

                            Armojax.
                            0
                            1. Bonjour, j'ai vraiment besoin d'aide !!! je dois d'éveloper visual basic, le probleme c'est que je coince la !!!
                              Quelle est la commende a taper pour que sur excel en tapent un numero de commanden automatiquement excel va chercher les résultat dan dotre fichier
                              J'espere que je me suis bien exprimer !!!!
                              Aider moi !!!
                              0
                              • 1
                              • 2