XL 2016 VBA: Copier des feuilles d'un fichier dans un autre

Aloha

XLDnaute Accro
Bonsoir,

J‘ai besoin d‘une aide en VBA.
Voici de quoi il s‘agit:
J‘ai 2 fichiers:
* le fichier source (fs): il contient 3 feuilles présentant la même structure.
Leur nom: AB, CD, EF
* le fichier destination (fd): il contient 3 feuilles: AB, EF et Modèle

La tâche: copier, feuille par feuille, les données du fs dans la feuille correspondante dans fd, dans la première ligne libre, en se basant sur la colonne A

Lorsqu‘il n‘y a pas encore dans fd une feuille correspondant à une feuille dans fs (dans le cas en espèce la feuille CD), il faut prendre la feuille Modèle, faire une feuille pour la feuille correpondante de fs, et lui donner le même nom que dans fs.

J‘ai enregistré une macro qui fait l‘opération, mais seulement pour une seule feuille de fs, à condition qu‘elle existe déjà dans fd. J‘ai besoin d‘une macro qui copie d’elle-même autant de feuilles qu‘il y en a dans fs.

Dans une deuxième étape il y a plus d‘un fs et fd et la macro doit copier du bon fs dans le bon fd.

L‘emplacement des fichiers (pour que la macro sache les trouver):
fs: D: Exemple:A copier
fd: D: Exemple:Fichiers destination

J‘espère m‘être exprimé d‘une façon compréhensible.

Bonne nuit
Aloha
 

Pièces jointes

  • Fichier cible.xls
    64 KB · Affichages: 53
  • Fichier source.xls
    61.5 KB · Affichages: 45
Dernière édition:

Aloha

XLDnaute Accro
Re,
J'ai du mal à adapter le code à mon fichier réel parce qu'il y a des parties que je ne comprends pas:
Code:
WS.Range(WS.Cells(2, 1), WS.Cells(Rows.Count, 3).End(xlUp)).Copy Cible.Worksheets(WS.Name).Cells(Rows.Count, 1).End(3)(2)

Ce code copie donc depuis la ligne 2 et la colonne 1 jusqu'au nombre de lignes contenant des valeurs et la colonne 3 et ces données sont insérées dans une feuille du FD qui a la même structure.

Dans ma situation réelle je dois copier la plage A5:Y35 du FS dans une plage commençant par A16:Y16.

Je ne comprends pas comment adapter ton code.

Ce que je ne comprends pas non plus c'est que nulle part il y a un Paste après Copy, alors que la copie fonctionne!

Bonne nuit
Aloha
 

Staple1600

XLDnaute Barbatruc
Bonsoir le fil, le forum

Premier réflexe quand on ne comprend pas : appuyer sur la touche F1
ou Ce lien n'existe plus sur le Web
Où l'on peut remarquer qu'on peut copier sans Paste ;)

La demande initiale était
La tâche: copier, feuille par feuille, les données du fs dans la feuille correspondante dans fd, dans la première ligne libre, en se basant sur la colonne
C'est ce que font mes macros dans ce fil.
Ce fil devenant un fil "questions à tiroirs", et comme je n'aime pas les tiroirs, je vais plutôt aller me coucher ;)
 
Dernière édition:

Aloha

XLDnaute Accro
Bonjour,
J‘espère que ta nuit était bien reposante!
J‘ai bien fait ce que tu suggères (d‘ailleurs sur Mac F1 mène autre part), mais comment pourrais-je, alors que ma maîtrise de VBA est bien modeste, trouver les réponses à mes questions, et les mettre en oeuvre, dans un code aussi compliqué que le bout que j‘ai posté?

Merci pour ton aide!
Bonne journée
Aloha
 
Dernière édition:

Aloha

XLDnaute Accro
Bonsoir,
Les différences ne sont pas si grandes. Ce qui est différent, c'est le chemin qui mène à un fichier.
Pour l'instant je suis à l'arrêt avec ce projet parce que le code que j'ai jusqu'ici ne satisfait pas encore mes besoins:
Premièrement il est une solution pour un seul fichier, et deuxièmement je dois encore intégrer du code que j'ai enregistré et qui prépare la feuille pour que les données puissent être copiées: ainsi, il y a deux lignes par jour (les cellules superposées étant reliées entre elles, deux à deux); donc il faut d'abord les délier, trier, et puis encore remplacer les dates livrées par formules par leurs valeurs. Je n'ai pas encore vérifié si j'arrive à intégrer ce code enregistrer sans trop de problèmes.
Bonne soirée
Aloha
 

Staple1600

XLDnaute Barbatruc
Bonsoir le fil, le forum

Oh que si les différences sont grandes!
CreateObject("Shell.Application"). BrowseForFolder
Ne fonctionne pas sous Mac
L'objet Dictionnary
Ne fonctionne pas sous Mac
Toutes les API Windows
Ne fonctionne pas sous Mac
Les expressions régulières (regexp)
Ne fonctionne pas sous Mac
 

Aloha

XLDnaute Accro
Bonsoir,

De toute façon le système tourne sur PC Windows.
Je suis sur Mac parce que mon PC n‘est pas en état de marche pour l‘instant.
Mais si cela devient inévitable pour des raisons d‘incompatibilité je pourrai aller sur le PC de ma femme.
Bonne nuit
Aloha
 

Aloha

XLDnaute Accro
Bonsoir,

Je n'arrive pas à adapter la partie suivante du code que "Staple1600" avait la gentillesse de rédiger:

WS.Range(WS.Cells(2, 1), WS.Cells(Rows.Count, 3).End(xlUp)).Copy Cible.Worksheets(WS.Name).Cells(Rows.Count, 1).End(3)(2)

J'ai fait déjà beaucoup d'essais, mais je n'y arrive pas parce que je ne comprends pas le code totalement.

Ce que je veux faire:
copier les données des cellules A5:Y[dernière rangée qui contient une valeur dans la colonne A] du fichier source
dans le fichier cible dans l'aire A[première ligne dans laquelle la cellule de la colonne A est vide]:Y[première ligne dans laquelle la cellule de la colonne A est vide + nombre de lignes copiées].

Comme mon explication me semble assez indigeste, un exemple:

Copier les données de A5:Y36 du fichier source dans A33:Y64 du fichier cible, la dernière ligne dans laquelle il y a une valeur en A étant la ligne 32.

J'aurais besoin d'un coup de pouce pour cela.
Merci d'avance
 

Staple1600

XLDnaute Barbatruc
Bonsoir le fil, le forum

Pour recopier une plage, il suffit simplement de spécifier la première cellule cible.
Donc pour reprendre ton exemple
Range("A5:Y36").Copy Range("A33")


Dans mon codde que tu cites, les chiifres indiquent des numéros de ligne et de colonnes
Cells(2,1) veut dire Cells(ligne 2, colonne1), soit A2
et End(3)(2) correspond à End(xlUp).Offset(1)

PS: Comme je n'ai pas de Mac sous la main, je ne peux tester que sur PC
Et sur PC, ma macro fonctionnait.
 

Aloha

XLDnaute Accro
Bonjour,

Merci pour la réponse.

Pas de problème; c'est facile à comprendre.

Range("A5:Y36").Copy Range("A33")
Cela ne fonctionne que pour l'exemple où la première ligne est prédéfinie.

End(3)(2) correspond à End(xlUp).Offset(1)
Désolé, j'ai du mal à comprendre cela. Est-ce que ce bout de code définit uniquement la colonne ?
Que signifient les chiffres dans "End(3)(2)"?
"End(xlUp).Offset.1": la première ligne occupée, en partant du bas + 1 ligne pour avoir la première ligne vide?

"WS.Range(WS.Cells(2, 1)": est-il possible de le remplacer par WS.Range("A2")?

Je suis vraiment désolé d'embêter avec cela. Je suis arrivé à adapter tout le code, mais je trébuche sur cette ligne, essentielle bien évidemment.
D'ailleurs, je suis à nouveau sur PC.

Bonne journée
Aloha
 
Dernière édition:

Staple1600

XLDnaute Barbatruc
Bonjour le fil, le forum

@Aloha
Peux-tu poster (dans le message et en le balisant) la dernière version de ton code VBA, stp?

La syntaxe classique VBA est : End(xlUp)
Une version raccourcie possible est : End(3)
Voir cette petite macro de test (à tester sur un classeur vierge)
VB:
Sub test()
Cells.Clear
Range("A1:A5").Formula = "=ROW()"
MsgBox Cells(Rows.Count, 1).End(xlUp).Address
MsgBox Cells(Rows.Count, 1).End(3).Address
End Sub
 
Dernière édition:

Aloha

XLDnaute Accro
Bonjour

Le code:
VB:
Sub Copier()

Dim WS As Worksheet, Cible As Workbook, Source As Workbook

Application.AskToUpdateLinks = False

Set Cible = Application.Workbooks.Open("C:\Users\...\...\....\...\...\[fichier cible variable].xls")

Application.AskToUpdateLinks = False

Set Source = Application.Workbooks.Open("C:\Users\...\...\...\A copier\[fichier source variable].xls")

Application.ScreenUpdating = False

Source.Sheets("Résumé").Visible = True

Source.Sheets(Array("Résumé", "Tableau", "Codes")).Select

ActiveWindow.SelectedSheets.Delete


For Each WS In Source.Worksheets

  If SheetExists(WS.Name, Cible) Then

WS.Range(WS.Cells(2, 1), WS.Cells(Rows.Count, 3).End(xlUp)).Copy Cible.Worksheets(WS.Name).Cells(Rows.Count, 1).End(3)(2)

    Application.CutCopyMode = False

  Else

     Cible.Sheets("Modèle").Visible = True

     Cible.Sheets("Modèle").Copy after:=Cible.Sheets(Cible.Sheets.Count)

     Cible.Sheets("Modèle (2)").Name = WS.Name

    Cible.Sheets("Modèle").Move after:=Cible.Sheets(Cible.Sheets.Count - 1)

    Cible.Sheets("Modèle").Visible = False

WS.Range(WS.Cells(2, 1), WS.Cells(Rows.Count, 3).End(xlUp)).Copy Cible.Worksheets(WS.Name).Cells(Rows.Count, 1).End(3)(2)

    Application.CutCopyMode = False

    Range("E2").Select

    ActiveCell.FormulaR1C1 = WS.Name

  End If

Next WS



Call Trier_les_feuilles

Application.DisplayAlerts = False

Cible.Close True

Source.Close False

End Sub

---------------------------------------------------------------------------------------------------------------------

Sub Trier_les_feuilles()

  Dim i As Integer

  Dim j As Integer

  For i = 1 To Sheets.Count

  For j = 1 To Sheets.Count - 1

  If UCase$(Sheets(j).Name) > UCase$(Sheets(j + 1).Name) Then _

  Sheets(j).Move after:=Sheets(j + 1)

Next j

Next i

End Sub

--------------------------------------------------------------------------------------------------------------------

Function SheetExists(shtName As String, Optional wb As Workbook) As Boolean

Dim sht As Worksheet

If wb Is Nothing Then Set wb = Source

On Error Resume Next

Set sht = wb.Sheets(shtName)

On Error GoTo 0

SheetExists = Not sht Is Nothing

End Function

End Sub

VBA

J'espère que la présentation du code est acceptable!
Quelques explications:

VB:
Set Cible = Application.Workbooks.Open("C:\Users\...\...\....\...\[dossier du service]\[fichier cible variable].xls")

"fichier cible variable" signifie que le fichier source ouvert détermine quel fichier cible sera ouvert:
J'ai x services qui ont chacun son dossier contenant e.a. le fichier cible correspondant. Exemple: le service XY a un dossier qui porte son nom et qui contient e.a. le fichier cible qui s'appelle alors "XY 2017".

VB:
Set Source = Application.Workbooks.Open("C:\Users\...\...\...\A copier\[fichier source variable].xls")

Le fichier source mensuel se trouve, le temps que les données sont copiées dans la base de données, ensemble avec les fichiers mensuels des autres services, dans un dossier provisoire "A copier" pour être déplacés dans le dossier du service après la copie..
Ainsi, le fichier mensuel de janvier du service XY s'appelle "Janvier 2017 XY" et le code doit ouvrir le fichier cible qui se trouve dans le dossier XY (il doit donc déterminer le dossier et le fichier cible d'après le nom du fichier mensuel).

Pour l'instant le code ne fait pas cela, c.-à-d. ouvrir l'un après l'autre les fichiers source qu'il trouve dans "A copier", ouvrir le fichier cible correspondant et copier les données. Pour l'instant il n'ouvre qu'un seul fichier source et un seul fichier cible.
Pour l'instant je dois donc, si je n'arrive pas à résoudre ce problème, prévoir une macro pour chaque service et chaque mois, en adaptant la macro à chaque fois et en les regroupant par mois sur un bouton. Bien évidemment cela fera beaucoup de macros (12 mois * presque 10 services).

J'ai inséré du code enregistré effaçant 3 fiches du fichier source qui ne doivent pas être copiés: Résumé, Codes, Tableau. Je suppose qu'il existe une autre méthode: exclure ces fichier de la copie.

En-dessous de la macro principale il y a encore une macro qui doit trier les feuilles d'après leur nom dans le fichier cible. Comme le code bloque à la ligne opérant la copie je n'arrive jamais jusque-là pour voir s'il fonctionne.

L'aire de copie dans le fichier source et le fichier cible est celle décrite dans mon message précédent.
A noter que la première ligne dans le fichier cible est la ligne 16.
A+
Aloha
 
Dernière édition:

Aloha

XLDnaute Accro
Bonjour,
@"Staple1600":
Je viens seulement d'apercevoir le petit code de test et de le tester.
J'ai compris que ces deux lignes de code:
MsgBox Cells(Rows.Count, 1).End(xlUp).Address
MsgBox Cells(Rows.Count, 1).End(3).Address
donnent le même résultat.
Je comprends bien pourquoi la première ligne donne le résultat, mais je n'arrive pas à comprendre, comment la deuxième peut donner le même résultat. Que signifie le chiffre 3 après "End"?
Salve
Aloha
 

Staple1600

XLDnaute Barbatruc
Bonjour le fil, le forum

Est-ce désormais plus clair?
VB:
Sub Test()
Range("A1,C1,B10") = 1600
a = [B1].End(xlToLeft).Address & vbCrLf
a = a & [B1].End(1).Address & vbCrLf
a = a & [B1].End(xlToRight).Address & vbCrLf
a = a & [B1].End(2).Address & vbCrLf
a = a & [B1].End(xlDown).Address & vbCrLf
a = a & [B1].End(4).Address & vbCrLf
a = a & Cells(Rows.Count, 2).End(xlUp).Address & vbCrLf
a = a & Cells(Rows.Count, 2).End(3).Address
MsgBox a

For i = 1 To 4
MsgBox [B1].End(i).Address
Next
End Sub
 
Dernière édition:

Discussions similaires

Statistiques des forums

Discussions
312 248
Messages
2 086 596
Membres
103 252
dernier inscrit
Ersar