FORUM Tom's Hardware » Programmation » VB / VBA / VBS » Dupliquer une feuille et la renommer
 

Dupliquer une feuille et la renommer

Il y a 388 utilisateurs connus et inconnus. Pour voir la liste des connectés connus, cliquez ici
Ajouter une réponse



 Mot :   Pseudo :  
 
Bas de page
Auteur
 Sujet : Dupliquer une feuille et la renommer
 
Plus d'informations

Bonjour à tous les lecteurs,

Je souhaite partir de la feuille "Préparation prochaine Revue" et la dupliquer X fois, sachant que c'est celle-ci que je fais évoluer. Les autres feuilles ne seront que des copies figées d'un instant t.
Une fois dupliquer je souhaite la renommer "Revue X", sachant que le X commence de 0 et s'incrémente à chaque duplication.
Enfin sur la feuille dupliquée, je souhaite mettre la date de la duplication dans la cellule D14 et le n° de la revue dans la cellule B14.

Pour l'instant j'ai écris ce code :

Code :
  1. Private Sub Nvlle_Revue_Click()
  2.     Dim PR As Worksheet
  3.    
  4.     Set PR = Worksheets("Préparation prochaine REVUE" )
  5.  
  6.     PR.Copy Before:=Sheets(4)
  7.     ActiveSheet.Name = "Revue X"
  8.     Worksheets("Revue X" ).Range("D14" ).FormulaR1C1 = "=TODAY()"
  9.     Worksheets("Revue X" ).Range("D14" ).Select
  10.     Selection.Copy
  11.     Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
  12.         :=False, Transpose:=False
  13.     Range("B14" ).FormulaR1C1 = "=+1"
  14. End Sub



Mais le nom de la feuille est toujours Revue X, alors que je souhaiterai qu'il se numérote automatiquement et s'incrémente à chaque nouvelle copie, idem pour le n° de la revue qui est toujours 1 alors que je voudrai qu’il s’incrémente de 1 à chaque nouvelle copie.

J’ai un autre problème, c’est que dès qu’il y a plus de 255 caractères dans une cellule excel met un message d’erreur et tronque les caractères qui sont au-delà.

Merci de bien vouloir me donner un coup de main, si vous avez des pistes à me donner.

Plus d'informations

OUPS ! :pt1cable:
J'ai réussi à simplifier le code :

Code :
  1. Private Sub Nvlle_Revue_Click()
  2.     Dim PR As Worksheet
  3.    
  4.     Set PR = Worksheets("Préparation prochaine REVUE" )
  5.  
  6.     PR.Copy Before:=Sheets(4)
  7.     ActiveSheet.Name = "Revue X"
  8.     Worksheets("Revue X" ).Range("D14" ).Value = Date
  9.     Range("B14" ).FormulaR1C1 = "=+1"
  10. End Sub


Mais j'ai toujours les mêmes questions. :ange:

Plus d'informations

Salut,

Déjà tu connais l'utilisation d'un objet worksheet, donc sert t'en pour connaitre la feuille créé. Ensuite pour nommer ta feuille il faut que tu saches quel est la derniere feuille existante nommer Revue n (n étant un entier)

D'ailleurs il y a t'il une raison profonde à ce que tu copie en 4 eme position ? car si tu veux que ce soit la dernière ca sera plus simple pour trouver la feuille revue avec le plus grand numéro

Code :
  1. 'Création de ta feuille
  2. Dim sh_revue as worksheet
  3. set sh_revue = PR.copy  after:=sheets.count
  4. ' Trouver l'indice existant max
  5. Dim i as long
  6. dim num as long 
  7. num = 0
  8. for i = 1 to sheets.count
  9.     if sheets(i).name like "Revue*" then
  10.         num = mid(sheets(i).name,instr(sheets(i).name,"Revue " )+1)
  11.     end if
  12. next 
  13. if num <> 0 then num = num +1
  14. 'nommage
  15. sh_revue.name = "Revue " & num


---------------
S'il n'y a pas de solution c'est qu'il n'y pas de problème
zeb
Profil : Modérateur libre
Plus d'informations

Très bonne idée Freeman, mais ta ligne 3 ne peut pas fonctionner, la méthode Copy ne renvoie pas un objet sur ce qui a été copié. Oui, je sais Billou n'a pas fini le modèle objet d'Excel :sarcastic:

 

Par contre, créer la feuille en dernier pour être sûr de la connaître est une très bonne idée :

Code :
  1. Dim sh_revue As Worksheet
  2. ' // Création de ta feuille
  3. PR.Copy After:=Sheets.count
  4. Set sh_revue = Sheets(Sheets.Count)
 

Pour la recherche, tu comptes sur l'ordre des feuilles. Je propose un truc légèrement plus compliqué (Deux boucles) :

Code :
  1. Dim b As Boolean
  2. Dim x As Integer
  3. Dim ws As WorkSheet
  4. x = 0
  5. Do
  6.     b = False
  7.     For Each ws In WorkSheets
  8.         If ws.Name = "Revue " & x
  9.             x = x + 1
  10.             b = True
  11.         End If
  12.     Next
  13. Loop While Not b
  14. MsgBox "X=" & x


Message édité par zeb le 07-09-2007 à 14:03:48

---------------
Règlement du forum / Règlement de Programmation / Règlement du Monde de Linux euh, n'y en a pas...
Plus d'informations

MERCI pour vos réponses, je mets en application et je vous tiens au courant...

Plus d'informations

Désolée, mais je n'ai pas tardée à avoir des problèmes et là je pige pas pourquoi.
J'ai une erreur d'exécution 1004 sur la ligne 8

Code :
  1. Private Sub Nvlle_Revue_Click()
  2. Dim PR As Worksheet
  3. Dim sh_revue As Worksheet
  4.  
  5. Set PR = Worksheets("Préparation prochaine REVUE" )
  6.  
  7. 'Création de ta feuille
  8. PR.Copy After:=Sheets.Count
  9. Set sh_revue = Sheets(Sheets.Count)



Sur le fichier de départ j'ai 4 feuilles, chacune étant renommée, est-ce que cela vient de là ?

Pour répondre à Freeman, effectivement je collé en 3ème place pour que la revue la plus récente soit en tête de fichier après le bilan des actions et le bilan économique.
Mais si c'est plus simple de mettre la dernière feuille crée à la fin pas de problème pour moi.

zeb
Profil : Modérateur libre
Plus d'informations

PR.Copy After:=Sheets(Sheets.Count)



C'est plus simple de la créer à emplacement fixe.
Sans doute par habitude, freeman et moi le faisons à la fin, quitte à faire un move après pour la mettre à un autre emplacement.

Si tu le mets toujours avant la feuille 4, après insertion ta nouvelle feuille devient la feuille 4. Donc :

Code :
  1. PR.Copy Before:=Sheets(4)
  2. Set sh_revue = Sheets(4)


---------------
Règlement du forum / Règlement de Programmation / Règlement du Monde de Linux euh, n'y en a pas...
Plus d'informations

Bonjour Zeb et Freeman,

J’ai essayé vos deux solutions.
J’ai très certainement pas fait ce qu’il fallait car dans les 2 cas je bloque.
Pour la solution de Freeman : la 1ère feuille de revue est bien créée et nommée Revue 0, mais la date et n° de la révision sont saisie dans la feuille source au lieu de la feuille créée. Par contre lors de la création de la 2ème feuille j’ai un message d’erreur d’exécution 13 (incompatibilité de type) en ligne 19

Code :
  1. Private Sub Nvlle_Revue_Click()
  2. Dim PR As Worksheet
  3. Dim sh_revue As Worksheet
  4.  
  5. Set PR = Worksheets("Préparation prochaine REVUE" )
  6.  
  7. 'Création de ta feuille
  8. PR.Copy Before:=Sheets(4)
  9. Set sh_revue = Sheets(4)
  10. ' Trouver l'indice existant max
  11. Dim i As Long
  12. Dim num As Long
  13. num = 0
  14. For i = 1 To Sheets.Count
  15.     If Sheets(i).Name Like "Revue*" Then
  16.         num = Mid(Sheets(i).Name, InStr(Sheets(i).Name, "Revue " ) + 1)
  17.     End If
  18. Next
  19. If num <> 0 Then num = num + 1
  20. 'nommage
  21. sh_revue.Name = "Revue " & num
  22.     Range("D14" ).Value = Date
  23.     Range("B14" ).FormulaR1C1 = "=+1"
  24. End Sub



Pour la solution de Zeb : je bloque dès la 1ère boucle de création : erreur d’exécution 13 en ligne 19. J’ai fait un tour dans l’aide, mais je ne vois pas quel est le problème.

Code :
  1. Private Sub Nvlle_Revue_Click()
  2. Dim PR As Worksheet
  3. Dim sh_revue As Worksheet
  4.  
  5. Set PR = Worksheets("Préparation prochaine REVUE" )
  6.  
  7. 'Création de ta feuille
  8. PR.Copy Before:=Sheets(4)
  9. Set sh_revue = Sheets(4)
  10. ' Trouver l'indice existant max
  11. Dim b As Boolean
  12. Dim x As Integer
  13. Dim ws As Worksheets
  14. x = 0
  15. Do
  16.     b = False
  17.     For Each ws In Worksheets
  18.         If ws.Name = "Revue " & 0 Then
  19.             x = x + 1
  20.             b = True
  21.         End If
  22.     Next
  23. Loop While Not b
  24. MsgBox "X=" & x
  25. 'nommage
  26. sh_revue.Name = "Revue " & num
  27.     Range("D14" ).Value = Date
  28.     Range("B14" ).FormulaR1C1 = "=+1"
  29. End Sub



Tout d'abord dans les 2 cas qu'est-ce qui fait que celane fonctionne pas?
Mais surtout qu'elle solution vaut-il mieux adopter dans mon cas, sachant que j'insère finalement la nouvelle feuille en un endroit fixe?

zeb
Profil : Modérateur libre
Plus d'informations

Mea culpa. (J'ai corrigé mon code)

Pour parcourir la collection des feuilles, il faut déclarer une feuille. Donc pour parcourir les Worksheets, il faut déclarer une Worksheet. Ligne 14, au lieu de déclarer UNE feuille, tu déclares une collection.

Ligne 30 : NON, la variable num n'existe pas. C'est X qui existe.
Ligne 32: NON. Ce n'est pas +1 qu'il faut mettre dans la formule de B14, c'est X qu'il faut mettre dans la valeur (value) de B14

Lignes 8 et 9 : Sheets, c'est la collection des feuillles, Worksheets, c'est la collection des feuilles de calcul, Charts, c'est la collection des feuilles de graphiques. Donc :

Sheets = Worksheets U Charts

Soit cohérent et demande-toi si tu gères des feuilles, des feuilles de calculs ou des feuilles de graphiques.

Ligne 31 et 32 : Et si tu précisais de quelle feuille tu parles !
Justement, ligne 9, on t'a fait créer une variable pour référencer la feuille :o


---------------
Règlement du forum / Règlement de Programmation / Règlement du Monde de Linux euh, n'y en a pas...
Plus d'informations

Après correction de tes remarques, j'ai eu quelques problèmes, notamment plantage d'excel.
J'ai donc farfouillé, pour comprendre d'où cela venait.

J'ai donc apporté quelques modifications ; nouveau code :

Code :
  1. Private Sub Nvlle_Revue_Click()
  2. Dim PR As Worksheet
  3. Dim sh_revue As Worksheet
  4.  
  5. Set PR = Worksheets("Préparation prochaine REVUE" )
  6.  
  7. 'Création de ta feuille
  8. PR.Copy After:=Worksheets(3)
  9. Set sh_revue = Worksheets(4)
  10.     sh_revue.Name = "Revue 0"
  11. ' Trouver l'indice existant max
  12. Dim b As Boolean
  13. Dim x As Integer
  14. Dim ws As Worksheet
  15. x = 0
  16. Do
  17.     b = False
  18.     For Each ws In Worksheets
  19.         If ws.Name = "Revue " & 0 Then
  20.             x = x + 1
  21.             b = True
  22.         End If
  23.     Next
  24. Loop While Not b
  25. MsgBox "Création de la revue N°" & x
  26. 'nommage
  27. sh_revue.Name = "Revue " & x
  28.     sh_revue.Range("D14" ).Value = Date
  29.     sh_revue.Range("B14" ).Value = x
  30. End Sub



Avec ce code, la 1ère feuille est créée sous le nom revue 0 et après la question (MsgBox) est renommée en revue 1. Là où cela coince c'est lors de la création de la 2ème feuille, le x proposé est à nouveau 1.

Je me demande donc s'il ne vaut mieux pas laisser le soin à l'utilisateur de saisir le n° du X lors de la message box.
Qu'en pensez-vous ?

zeb
Profil : Modérateur libre
Plus d'informations

Re-mea culpa ... N'importe quoi !!!!!! :pfff:
(J'ai encore modifié mon code :sarcastic: )

 

Bon alors, regarde la ligne 21 de ton code. Ce n'est pas 0 que l'on cherche, c'est forcément x !

 

Lignes 8 et 9, Y'a de l'idée :)
Lignes 31 & 32, Là c'est mieux

 

Fais-moi plaisir, lignes 10, 32, 33, aligne (indente) correctement ton code ;) pour faire biau

 

Ligne 10 : NON. Au premier tour, ça va marcher, quand il n'y aura pas encore de "Revue 0", mais au second tour : PLANTAGE.
C'est à la ligne 31 que tu mets un nouveau nom.


Message édité par zeb le 07-09-2007 à 14:10:05

---------------
Règlement du forum / Règlement de Programmation / Règlement du Monde de Linux euh, n'y en a pas...
Plus d'informations

Alors dans mon idée l'intérêt de placer la dernière revue à la fin permet de largement simplifier la recherche de l'indice max (mais si tu dois faire autrement tanpis...
Ca plante à la 2eme execution car tu veux nommer une 2eme feuille revue 0... de plus il est inutile de lui donner un nom temporaire vu que tu as la variable.

Pour ta recherche de l'indice max je ferai pas comme ca mais plutot :

Code :
  1. Dim lnum as long
  2.     For Each ws In Worksheets
  3.         If ws.Name like "Revue *" Then
  4.             ' on récupère l'indice de la feuille
  5.             lnum = mid(ws.name,instr(ws.name,"Revue " ) +1)
  6.             if lnum > x then x = lnum
  7.         End If
  8.     Next


Message édité par Freeman23 le 07-09-2007 à 14:29:50

---------------
S'il n'y a pas de solution c'est qu'il n'y pas de problème
Plus d'informations

Bon je commençais à craquer car plantage d'excel après avoir supprimé la ligne 10.
Puis j'ai remis la ligne10 et il se trouve que CA MARCHE ! :ouch:

Alors serait-ce parce que la feuille où est implanté le bouton qui lance la macro s'appelle "Préparation prochaine REVUE" et nom "Revue x" ?

Je vous laisse le code final pour avis :

Code :
  1. Private Sub Nvlle_Revue_Click()
  2. Dim PR As Worksheet
  3. Dim sh_revue As Worksheet
  4.  
  5. Set PR = Worksheets("Préparation prochaine REVUE" )
  6.  
  7. 'Création de ta feuille
  8. PR.Copy After:=Worksheets(3)
  9. Set sh_revue = Worksheets(4)
  10. sh_revue.Name = "Revue 0"
  11. ' Trouver l'indice existant max
  12. Dim b As Boolean
  13. Dim x As Integer
  14. Dim ws As Worksheet
  15. x = 0
  16. Do
  17.     b = False
  18.     For Each ws In Worksheets
  19.         If ws.Name = "Revue " & x Then
  20.             x = x + 1
  21.             b = True
  22.         End If
  23.     Next
  24. Loop While Not b
  25. MsgBox "Création de la revue N°" & x
  26. 'nommage
  27. sh_revue.Name = "Revue " & x
  28. sh_revue.Range("D14" ).Value = Date
  29. sh_revue.Range("B14" ).Value = x
  30. End Sub



Merci Zeb pour ta patience et Merci Freeman23 pour ta réponse

Plus d'informations

HO HO ! :sweat:
J'ai parlé trop vite
En fait ca plante à la création de la 3ème feuille où la macro me propose à nouveau le N° 2 pour x et la fiche existe déjà.
Cependant j'ai un problème persisitant. au-delà de 255 caractères, excel tronque ce qui est écrit dans la cellule lors de la duplication. Pour çà, existe-t-il une solution ?

zeb
Profil : Modérateur libre
Plus d'informations

TU VAS NOUS VIRER LA LIGNE 10
(En rouge et en majuscule...)

 

Et non, Excel n'aime pas les chaînes de plus de 255 caractères
Et il tronque effectivement lors de la copie. Donc ce n'est pas comme ça qu'il faut faire... car effectivement, il y a une solution :

 
  • Créer une feuille vierge,
  • Copier les cellules de la feuille source vers les cellules de la nouvelle feuille


Code :
  1. Function PlusGrandNumerotage(Prefix As String)
  2.     Dim ws As Worksheet
  3.     Dim n As Integer
  4.     Dim X As Integer
  5.    
  6.     X = -1
  7.     For Each ws In Worksheets
  8.         If Left(ws.Name, Len(Prefix)) = Prefix Then
  9.             If IsNumeric(Mid(ws.Name, Len(Prefix) + 1)) Then
  10.                 n = CInt(Mid(ws.Name, Len(Prefix) + 1))
  11.                 If n > X Then X = n
  12.             End If
  13.         End If
  14.     Next
  15.     PlusGrandNumerotage = X
  16. End Function
Code :
  1. Sub CopierRevue()
  2.     Dim wsNouvelleRevue As Worksheet
  3.    
  4.     Set wsNouvelleRevue = Worksheets.Add( <avant, après, où tu veux> )
  5.     wsNouvelleRevue.Name = "Revue " & (PlusGrandNumerotage("Revue " ) + 1)
  6.    
  7.     Worksheets("Préparation prochaine REVUE" ).Cells.Copy Destination:=wsNouvelleRevue.Cells(1, 1)
  8. End Sub
 

J'ai fait une fonction pour récupérer le plus grand numérotage. Si au lieu d'avoir des Revue 1, Revue 2, etc, tu as des Feuil1, Feuil2, etc, tu remarqueras que ça marche. Il suffit de donner le bon préfixe :sol:

 

La fonction Add renvoie bien un Worksheet, donc pas de problème. On revient à la première proposition de Freeman.
Dans la focntion de copie, je n'ai pas rempli B14 et D14, débrouille-toi.

 

Afin de profiter pleinement de cette proposition, regarde-la bien et essaie de tout comprendre (quitte à farfouiller ;) )


Message édité par zeb le 07-09-2007 à 16:32:36

---------------
Règlement du forum / Règlement de Programmation / Règlement du Monde de Linux euh, n'y en a pas...
Plus d'informations

C'est logique car ta numérotation dépend de l'ordre des feuilles.

Code :
  1. For Each ws In Worksheets
  2.         If ws.Name = "Revue " & x Then
  3.             x = x + 1
  4.             b = True
  5.         End If
  6.     Next


Par Exemple tu as la feuille "revue 2" à la 4eme et la "revue 1" à la cinquième car tu insères toujours en 4 donc les feuilles seront en ordres inverses.

Le prog trouve la feuille 2 donc il met x à 3.
Puis il trouve la feuille 1 donc il met x à 2.

D'ou ma proposition précédente :

Code :
  1. Dim lnum as long
  2.     For Each ws In Worksheets
  3.         If ws.Name like "Revue *" Then
  4.             ' on récupère l'indice de la feuille
  5.             lnum = clng(mid(ws.name,instr(ws.name,"Revue " ) +1))
  6.             if lnum > x then x = lnum
  7.         End If
  8.     Next
  9.     lnum = lnum +1 ' c'est mieux :P



Dans cet exemple qu'importe la position des feuilles ou l'existence d'une numérotation complète il crééra automatiquement le nom avec l'entier maximum inexistants.

Edit : GRILLED BY ZEB... :D


Message édité par Freeman23 le 07-09-2007 à 16:34:02

---------------
S'il n'y a pas de solution c'est qu'il n'y pas de problème
zeb
Profil : Modérateur libre
Plus d'informations

:D


---------------
Règlement du forum / Règlement de Programmation / Règlement du Monde de Linux euh, n'y en a pas...
Plus d'informations

Merci Freeman23 pour l'explication de l'échec en revue 2 et pour le reste aussi d'ailleurs.
Merci Zeb pour la nouvelle piste surlaquelle tu m'as lancé.
A vous deux, j'ai de quoi travailler ce week-end !!! :cry:
Allez va, je potasse le tout et je vous tiens au courant. A moins que je fasse bronzette ce we et que je m'y remette lundi.... :sol: