Copier plage d'un classeur à un autre
Bonjour au forum,
Je rencontre un problème avec ce code me permettant de copier une plage de cellule d'un classeur à un autre :
Sub Copy()
ChDrive "O"
ChDir "O:\chemin\DONNEES BRUTES"
Workbooks.Open Filename:=Application.GetOpenFilename 'on sélectionne le fichier qui comporte les données à copier
ActiveSheet.Range("A3:G400").Copy
Windows("fichier ou coller.xlsm").Activate
With ActiveSheet
.Unprotect "mdp"
.Range("A11").PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
.Protect "mdp", DrawingObjects:=True, Contents:=True, Scenarios:= _
False, AllowFormattingCells:=True, AllowSorting:=True, AllowFiltering:= _
True, AllowUsingPivotTables:=True
.Range("A11").Select
End With
End Sub
J'ai une fois sur deux une erreur sur la méthode .Pastespecial, et je ne comprends pas pourquoi...
Quelqu'un aurait une idée ?
Merci d'avance !
Bonsoir,
Il faudrait épurer ton code de tous les éléments inutiles, et qualifier plus précisément... Il suffit que la feuille active ne soit pas celle que tu penses...
Cordialement.
Bonsoir MFerrand,
Je ne vois pas vraiment quel bout de code est inutile malheureusement... Ni d’ailleurs comment qualifier plus précisément !
Eh bien !
ActiveSheet.Range("A3:G400").Copy
Cette commande présuppose que le classeur que tu ouvres ne contient qu'une feuille... Mais même dans ce cas, une désignation plus précise de la feuille me semble préférable... (et on ne sait jamais, tu pourrais ajouter une feuille sans penser à ta macro...)
Windows("fichier ou coller.xlsm").Activate
With ActiveSheet
Je déconseille l'utilisation de l'objet Window pour autre chose que des questions d'affichage, on est plus sûr de ce qu'on fait avec les composants sur lesquels on agit : Workbook, Worksheet, Range...
Ici encore ActiveSheet présuppose que la feuille était antérieurement active et le redeviendra, voire qu'on a lancé la macro à partir de cette feuille, mais présupposer ne garantit pas une fiabilité absolue à long terme, cibler l'objet précis qu'on vise est toujours mieux...
Et évidemment le faire sans activer évite une opération parasite qui prend du temps et sera donc plus rapide.
.Range("A11").PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
Comme d'hab. !
.Range("A11").PasteSpecial xlPasteValues
suffisait, le reste est du superflu...
J'ajoute que si l'opération est un collage valeurs on n'a aucun intérêt au copier-coller, une affectation de valeurs sur le mode :
PlageCible.Value = PlageSource.Value
sera infiniment plus rapide.
Cordialement.
Merci pour ta réponse MFerrand
Cette commande présuppose que le classeur que tu ouvres ne contient qu'une feuille... Mais même dans ce cas, une désignation plus précise de la feuille me semble préférable... (et on ne sait jamais, tu pourrais ajouter une feuille sans penser à ta macro...)
Le classeur que j'ouvre contient une seule feuille dont le nom change mensuellement (c'est un export d'un logiciel tiers), exemple : "janvier_Ana.xls"
C'est pourquoi je ne peux pas, du moins avec mes compétences, demander la copie en utilisant un nom de feuille spécifique.
Je déconseille l'utilisation de l'objet Window pour autre chose que des questions d'affichage, on est plus sûr de ce qu'on fait avec les composants sur lesquels on agit : Workbook, Worksheet, Range...
Je devrais donc simplement remplacer le :
Windows("fichier ou coller.xlsm").Activate
par :
Workbook("fichier ou coller.xlsm").Activate
?
Ici encore ActiveSheet présuppose que la feuille était antérieurement active et le redeviendra, voire qu'on a lancé la macro à partir de cette feuille, mais présupposer ne garantit pas une fiabilité absolue à long terme, cibler l'objet précis qu'on vise est toujours mieux...
Et évidemment le faire sans activer évite une opération parasite qui prend du temps et sera donc plus rapide.
J'ai effectivement crée un bouton sur chaque feuille de mon fichier de destination (importation mensuelle, tu l'auras certainement compris
suffisait, le reste est du superflu...
Effectivement...
J'ajoute que si l'opération est un collage valeurs on n'a aucun intérêt au copier-coller, une affectation de valeurs sur le mode :
CODE : TOUT SÉLECTIONNER
PlageCible.Value = PlageSource.Value
sera infiniment plus rapide.
J'ai testé cela mais sans succès...
Merci pour ton aide
Bonjour,
Worksheets(1)
cible très bien la feuille sans faire appel à son nom.
Il ne s'agit pas par ailleurs d'activer la fenêtre ou le classeur, mais de l'utiliser sans avoir à l'activer...
Tu peux également avec une variable Range lui affecter au départ la plage cible, ce qui évite diverses répétitions.
J'ai testé cela mais sans succès...
Comment donc l'as-tu testé ?
Ma suggestion :
Sub Copy()
Dim PlgC As Range
ChDrive "O"
ChDir "O:\chemin\DONNEES BRUTES"
With ActiveSheet
Set PlgC = .Range("A11:G408")
.Unprotect "mdp"
End With
With Workbooks.Open(Application.GetOpenFilename)
PlgC.Value = .Worksheets(1).Range("A3:G400").Value
.Close False
End With
PlgC.Worksheet.Protect "mdp", True, True, False, AllowFormattingCells:=True, _
AllowSorting:=True, AllowFiltering:=True, AllowUsingPivotTables:=True
End Sub
Avec une variable Range pour la plage cible et une mise sous bloc With du classeur source à l'ouverture, on opère directement... Noter que l'on peut pointer à partir d'une plage la feuille qui la contient.
Cordialement.
Bonjour MFerrand,
Comme d'habitude, tu me sors une belle épine du pied... !
Worksheets(1) cible très bien la feuille sans faire appel à son nom.
Je ne connaissais pas cette subtilité qui va beaucoup m'aider, merci beaucoup !
Comment donc l'as-tu testé ?
Probablement mal, je ne me souviens plus exactement, mais je sais que j'ai eu des difficultés pour coder "Cette plage dans ce classeur = cette plage dans cet autre classeur". Je n'ai pas encore cet automatisme d'utiliser "Set"...
Merci beaucoup pour ton aide MFerrand, et une excellente semaine à toi !