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
    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.
  2. Bonjour,

    Débutante en VBA, je rencontre un petit problème que NightHawk a lui aussi expérimenté.

    J'ai créé un bouton de commande:

    Private Sub CommandButton1_Click()

    Range("Arrivée_de_Vin").Copy
    ActiveCell(1).EntireRow.Select
    Selection.Paste

    End Sub

    Et il ne fonctionne pas. VBA affiche erreur d'exécution 438: Propriété ou méthode non gérée par cet object.
    Le débogueur me montre que l'erreur vient de "Selection.Paste"

    Pouvez-vous m'aider s'il vous plaît...???
    Merci par avance
    1. En fait j'ai trouvé la solution. Je dois remplacer "paste" par "PasteSpecial xlPasteAll"
  3. 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 !!!
    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.
      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
        ...
        
        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.
          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.
            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.
              1. 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 :)
                1. le problème vient de ce qu'il des zones nommées dans
                  les feuilles copiées et que les noms sont identiques
                  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.
                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. 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
                    1. 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 :)
                      1. 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 :)
                        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.
                      2. bonjour
                        je voudrais savoir plus des outils offerts par l'environnement visual basic,leurs puissances et leurs limites
                        Avec mes meilleurs remerciements
                        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
                      3. 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

                        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.
                          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
                        2. 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...
                          • 1
                          • 2