[VBA] Forcer le collage de valeur sur une plage spécifique
Bonjour le forum.
Je souhaiterai forcer l'utilisateur à coller en valeur et ce sur une plage spécifique (qui change selon les classeurs)
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Source As Range)
On Error Resume Next 'sécurité
With Application
If .CutCopyMode Then
.EnableEvents = False
.Calculation = xlManual
.Undo
Selection.PasteSpecial xlPasteValues
.OnUndo "", ""
.OnRepeat "", ""
.Calculation = xlAutomatic
.EnableEvents = True
End If
End With
End SubJ'ai trouvé ce code sur l'internet, source
Problème... la plage de cellules concernée contient déjà un code qui s'exécute au Worksheet_Change, donc le .undo ne fonctionne pas zut !
Le code avec la plage de cellule concernée:
Private Sub Worksheet_Change(ByVal Target As Range)
On Error Resume Next
If Sheets("Calculs").Range("H2") = True Then Exit Sub
For Each cel In Target.Cells
If Not Application.Intersect(cel, Range("B17:B31, D17:D31, F17:F31, H17:H31, J17:J31, L17:L31, N17:N31, P17:P31")) Is Nothing Then
Me.Unprotect
If cel.Value = "" Then
cel.Interior.ColorIndex = -4142
cel.Comment.Delete
Else
cel.Interior.ColorIndex = 2
cel.AddComment
cel.Comment.Text Text:="Valeur figée car rentrée mannuellement"
End If
Me.Protect
End If
Next cel
End SubMerci de votre aide.
Gabin
Bonjour
Je souhaiterai forcer l'utilisateur à coller en valeur et ce sur une plage spécifique (qui change selon les classeurs)
Problème... la plage de cellules concernée contient déjà un code qui s'exécute au Worksheet_Change, donc le .undo ne fonctionne pas zut !
Je n'ai pas bien compris votre souci. Vous pourriez donner un exemple que je reproduise ?
Exemple pour la feuille Capa 30 graph :
Vous collez des valeurs depuis B17 à B31 en une seule fois ou cellule par cellule ?
Lorsque vous copiez, les valeurs viennent d'où ?
Bonjour Dan,
Merci pour tas réactivité
L'utilisateur va coller des valeurs dans le range B17:B31 , D17:D31 , F17:F31 etc..
Je ne sais pas d'où vienne ces valeurs, ni combien il y en auras (Pas obligé de tout remplir ni de haut en bas)
J'aimerai juste par sécurité forcer le collage en VALEUR car j'utilise le format comme indicateur dans mes programme et de plus je compte faire des exports PDF donc niveau esthétique c'est mieux.
J'espère avoir été plus clair
Les valeurs copiées sont le résultat de formules éventuelles ou simplement des valeurs ?
Cette question parce que copier une cellule qui contient une formule et la coller ailleurs ne donne pas le même résultat que s'il s'agit uniquement de valeurs
Là comme je comprends il s'agit d'avoir le bon format final après le collage
Edit : autre question au sujet des codes. Il y a en un dans les feuilles Graph et un dans Thisworkbook. Et il agissent tous les deux. Est-ce que celui de Thisworkbook peut être supprimé ?
Les valeurs copiées seront toujours des valeurs et non des formules.
Le code dans Thisworkbook c'est ce que j'ai essayé de faire donc oui peux être supprimé.
Il n'y à que 3 feuilles qui doivent contenir la fonctionnalité pour coller les valeurs. (j'ai supprimé la 3èeme car trop volumineux)
Mais si on trouve le code qui va dans la feuil Capa 30 Graph j'adapterais pour les autres.
Le code dans Thisworkbook c'est ce que j'ai essayé de faire donc oui peux être supprimé.
ok.
Je ne suis pas sûr que c'est cette solution que vous cherchez mais si vous mettez simplement cette ligne en dessous de la ligne COLORINDEX = 2 de la partie Else
cel.NumberFormat = "0.00"Edit : autre question, le nom des 3 feuilles commence toujours par CAPA ?
le nom des 3 feuilles commence toujours par CAPA ?
En théorie oui, mais l'utilisateur pourrais avoir l'idée de changer ce nom (prévoyons le pire). C'est pour cela qu'il est peut être préférable d'avoir le code dans chaque feuilles ?
si vous mettez simplement cette ligne en dessous de la ligne COLORINDEX = 2 de la partie Else
J'ai testé avec une mise en forme source assez farfelue le résultat n'est pas satisfaisant. Je dois pouvoir résoudre le problème en ajoutant tout les paramétrages cellules dans le code qui permettent de configurer les bordures, polices couleurs etc.. C'est juste un peu fastidieux
Je dois pouvoir résoudre le problème en ajoutant tout les paramétrages cellules dans le code qui permettent de configurer les bordures, polices couleurs etc.. C'est juste un peu fastidieux
Les bordures c'est assez simple à faire
Les couleurs... vous parlez de la couleur de la police de caractère ( bleue ?)
l'utilisateur pourrais avoir l'idée de changer ce nom (prévoyons le pire). C'est pour cela qu'il est peut être préférable d'avoir le code dans chaque feuilles ?
On peut arranger cela au départ en utilisant le codename. C'est votre ficher original qui est posté ?
Les bordures c'est assez simple à faire
Les couleurs... vous parlez de la couleur de la police de caractère ( bleue ?)
Il y a aussi la Police utilisée, la taille est-ce que c'est en Gras, souligné, italiques... J'ai peur que cette piste soit un vrai casse-tête non ? Ou suis-je peut être trop pessimiste envers l'utilisateur qui collera ses données.
en utilisant le codename
Jamais entendu parlé ?
Joint la dernière version de mon fichier complet. à savoir que l'utilisateur pourras dupliquer les feuilles si besoin et qu'elle doivent rester fonctionnelle.
Merci pour votre (ton?) aide Dan
Joint la dernière version de mon fichier complet. à savoir que l'utilisateur pourras dupliquer les feuilles si besoin et qu'elle doivent rester fonctionnelle.
Pourquoi les dupliquer ? On a dit depuis le début que seules 3 feuilles étaient concernées puis on peut interdire l'ajout de feuilles aussi
Il y a aussi la Police utilisée, la taille est-ce que c'est en Gras, souligné, italiques... J'ai peur que cette piste soit un vrai casse-tête non ? Ou suis-je peut être trop pessimiste envers l'utilisateur qui collera ses données.
casse tête ? non c'est quelques lignes en plus
le codename --> Jamais entendu parlé ?
Voyez l'image ci-dessous où j'ai entouré au dessus le codename de la feuille créé par excel, en dessous la codename que vous pouvez modifier uniquement en accédant à l'éditeur VBA (ou par code évidemment)
Du coup si l'utilisateur veut changer le nom de l'onglet, le codename lui, n'est pas modifié
Pourquoi les dupliquer ? On a dit depuis le début que seules 3 feuilles étaient concernées puis on peut interdire l'ajout de feuilles aussi
En fait pas exactement j'ai du mal m'exprimer. Il existe 3 feuilles de 30,60 et 120 valeurs selon le besoin de l'utilisateur. Chaque feuilles peut contenir 4 mesures, si l'utilisateur a besoin de plus il peut copier/coller les feuilles a volonté... *
J'ai compris pour le codename, je ne connaissais pas ca me sera grandement utile par la suite.
Je pense que nous devons trouver un code contenue directement dans la feuille (juste a le copier coller pour les 2 autres feuilles)
Comme cela on règle le problème des feuilles dupliquer.
Je pense que nous devons trouver un code contenue directement dans la feuille (juste a le copier coller pour les 2 autres feuilles)
Comme cela on règle le problème des feuilles dupliquer.
Cela va alourdir le fichier mais bon vous pouvez essayer ce code.
Code à placer dans chaqu'une des 3 feuilles CAPA de votre fichier
Attention que l'instruction Me.protect ne permet pas de dupliquer les feuilles
Private Sub Worksheet_Change(ByVal Target As Range)
Dim Lig As Byte
Dim cel As Range, Plage As Range, c As Range
On Error Resume Next
If Sheets("Calculs").Range("H2") = True Then Exit Sub
For Each c In Range("A17:A" & Range("A" & Rows.Count).End(xlDown).Row)
If Not IsNumeric(Range("A" & c.Row)) Then Lig = c.Row - 1: Exit For
Next c
Set Plage = Union(Range("B17:B" & Lig), Range("D17:D" & Lig), Range("F17:F" & Lig), Range("H17:H" & Lig), Range("J17:J" & Lig), Range("L17:L" & Lig), Range("N17:N" & Lig), Range("P17:P" & Lig))
For Each cel In Plage
If Not Application.Intersect(cel, Plage) Is Nothing Then
Me.Unprotect
If cel.Value = "" Then
cel.Interior.ColorIndex = -4142
cel.Comment.Delete
Else
With cel
.Interior.ColorIndex = 2
.NumberFormat = "0.00"
.BorderAround LineStyle:=xlContinuous
.AddComment
.Comment.Text Text:="Valeur figée car rentrée mannuellement"
With .Font 'police
.Name = "Arial"
.Color = -65536
.Size = 10
End With
End With
End If
End If
Next cel
Me.Protect
End SubCordialement
En effet le code est très lourd. Ne peut-on pas boucler uniquement sur Target ? pas besoin de reformater les cellules inchangées
Sinon le résultat est quasi parfait, il manque juste l'alignement des cellules mais je devrais facilement trouver la propriété sur le net !
EDIT: c'est bon j'ai trouvé avec
.VerticalAlignment = xlVAlignCenter
.HorizontalAlignment = 3
En effet le code est très lourd. Ne peut-on pas boucler uniquement sur Target ? pas besoin de reformater les cellules inchangées
Non là il n'est pas lourd mais quand vous êtes obligé de l'avoir dans chaque feuille parce que l'utilisateur peut ne avoir besoin, cela ne simplifie pas.
Non avec le Target cela ne fonctionne pas sinon je vous l'aurais laissé. L'avantage ici est que l'on n'a pas besoin d'adapter la plage dans chaque feuille. La dernière ligne 31 ou 46 ou autre est déterminée par le code.
Par contre on peut faire en sorte de mettre une partie de code dans un module parce qu'il sera récurrent. Il faut juste repérer le nom de la feuille concernée pour qu'il soit vu dans le code placé dans le module. Si vous voulez je modifie pour vous proposer cette solution.
L'avantage ici est que l'on n'a pas besoin d'adapter la plage dans chaque feuille. La dernière ligne 31 ou 46 ou autre est déterminée par le code.
Oui ca merci beaucoup c'est très pratique.
Non avec le Target cela ne fonctionne pas
J'ai testé à priori tout fonctionne parfaitement pour moi avec
Non là il n'est pas lourd
Sur la feuille 120 valeur, lors de la remise a zéro le programme exécute 480 fois le worksheet change ce qui fait crasher Excel.
Honnêtement la j'ai tout qui fonctionne et j'ai parfaitement ce que je voulais. Je vais clôturer le sujet vous m'avez beaucoup aidé merci
Bon je vous donne tout de même ce que j'ai fait
1. Dans chacune de vos feuilles CAPA, mettez ce code
Private Sub Worksheet_Change(ByVal Target As Range)
Dim Feuille As String
If Sheets("Calculs").Range("H2") = True Then Exit Sub
Feuille = ActiveSheet.Name
Call miseenforme(Feuille)
End Sub2. Dans un module mettez ce code
Sub miseenforme(Feuille As String)
Dim Lig As Byte
Dim cel As Range, Plage As Range, c As Range
With Sheets(Feuille)
For Each c In .Range("A17:A" & Range("A" & Rows.Count).End(xlDown).Row)
If Not IsNumeric(.Range("A" & c.Row)) Then Lig = c.Row - 1: Exit For
Next c
Set Plage = Union(.Range("B17:B" & Lig), .Range("D17:D" & Lig), .Range("F17:F" & Lig), .Range("H17:H" & Lig), .Range("J17:J" & Lig), .Range("L17:L" & Lig), .Range("N17:N" & Lig), .Range("P17:P" & Lig))
On Error Resume Next
For Each cel In Plage
If Not Intersect(cel, Plage) Is Nothing Then
Sheets(Feuille).Unprotect
If cel.Value = "" Then
cel.Interior.ColorIndex = -4142
cel.Comment.Delete
Else
With cel
.Interior.ColorIndex = 2
.NumberFormat = "0.00"
.BorderAround LineStyle:=xlContinuous
.VerticalAlignment = xlVAlignCenter
.HorizontalAlignment = 3
.AddComment
.Comment.Text Text:="Valeur figée car rentrée mannuellement"
With .Font 'police
.Name = "Arial"
.Color = -65536
.Size = 10
End With
End With
End If
Sheets(Feuille).Protect
End If
Next cel
End With
End SubLe code au point 2 sera appelé à chaque modification de votre feuille Capa
Cordialement
Edit : ajouté ligne If not Intersect....
Bonjour Dan,
Merci pour ce code, très épuré et fonctionnel.
Par contre encore une fois, ce code met 1 à 2 sec à s'exécuter.
Je boucle sur Target et je gagne donc beaucoup de temps d'exécution et tout reste parfaitement fonctionnel
Pas la peine de modifier la forme des cellules qui n'ont pas été modifié.
Donc votre code avec la petite modif:
Private Sub Worksheet_Change(ByVal target As Range)
Dim Feuille As String
If Sheets("Calculs").Range("H2") = True Then Exit Sub
Feuille = ActiveSheet.Name
Call Miseenforme(Feuille, target)
End SubSub Miseenforme(Feuille As String, cible As Range)
Dim Lig As Byte
Dim cel As Range, Plage As Range, c As Range
With Sheets(Feuille)
For Each c In .Range("A17:A" & Range("A" & Rows.Count).End(xlDown).Row)
If Not IsNumeric(.Range("A" & c.Row)) Then Lig = c.Row - 1: Exit For
Next c
Set Plage = Union(.Range("B17:B" & Lig), .Range("D17:D" & Lig), .Range("F17:F" & Lig), .Range("H17:H" & Lig), .Range("J17:J" & Lig), .Range("L17:L" & Lig), .Range("N17:N" & Lig), .Range("P17:P" & Lig))
On Error Resume Next
For Each cel In cible
If Not Intersect(cel, Plage) Is Nothing Then
Sheets(Feuille).Unprotect
If cel.Value = "" Then
cel.Interior.ColorIndex = -4142
cel.Comment.Delete
Else
With cel
.Interior.ColorIndex = 2
.NumberFormat = "0.00"
.BorderAround LineStyle:=xlContinuous
.VerticalAlignment = xlVAlignCenter
.HorizontalAlignment = 3
.AddComment
.Comment.Text Text:="Valeur figée car rentrée mannuellement"
With .Font 'police
.Name = "Arial"
.Color = -65536
.Size = 8
End With
End With
End If
Sheets(Feuille).Protect
End If
Next cel
End With
End SubMerci pour votre temps Dan