" J'ai deux événements.
J'ai essayé de copier les deux dans le même Worksheet_Change, mais Excel devient berzerk et plante.
Range 1:
Private Sub Worksheet_Change(ByVal Target As Range) Dim acr As Range Set acr = Range("C9:G9") For Each Cell In acr Cell.Value = LCase(Cell) Next Cell End Sub
4 Réponses :
Comme ça, vous pouvez faire les deux choses dans le même événement
Vous devez ajouter Application.EnableEvents = False
au début pour éviter la condition de concurrence.
Private Sub Worksheet_Change(ByVal Target As Range) Application.EnableEvents = False Dim ccr As Range, acr as Range Set ccr = Range("C6") For Each Cell In ccr Cell.Value = LCase(Cell) Next Cell Set acr = Range("C9:G9") For Each Cell In acr Cell.Value = LCase(Cell) Next Cell Application.EnableEvents = True End Sub
Je vous remercie! Cela le corrige
Le problème principal est que la modification d'une valeur de cellule Cell.Value
déclenchera immédiatement un autre Worksheet_Change
. Vous devez Application.EnableEvents = False
pour éviter cela.
Je recommande également de travailler avec Intersect
pour que le code ne fonctionne que sur les cellules qui sont réellement modifiées.
Private Sub Worksheet_Change(ByVal Target As Range) Dim AffectedRange As Range Set AffectedRange = Intersect(Target, Target.Parent.Range("C6, C9:G9")) Application.EnableEvents = False 'pervent triggering another change event On Error GoTo ERR_HANDLING If Not AffectedRange Is Nothing Then Dim Cel As Range For Each Cel In AffectedRange.Cells Cel.Value = LCase$(Cel.Value) Next Cel End If On Error GoTo 0 'no Exit Sub here! ERR_HANDLING: Application.EnableEvents = True If Err.Number <> 0 Then Err.Raise Err.Number, Err.Source, Err.Description, Err.HelpFile, Err.HelpContext End If End Sub
En plus du commentaire de @Frank Ball, y compris la gestion des erreurs:
Option Explicit Private Sub Worksheet_Change(ByVal Target As Range) Dim AffectedRange As Range Set AffectedRange = Intersect(Target, Target.Parent.Range("C6, C9:G9")) If Not AffectedRange Is Nothing Then Application.EnableEvents = False 'pervent triggering another change event Dim Cel As Range For Each Cel In AffectedRange.Cells Cel.Value = LCase$(Cel.Value) Next Cel Application.EnableEvents = True 'don't forget to re-enable events in the end End If End Sub
Les deux événements Worksheet_Change
sont assez identiques, ils sont une boucle autour d'une plage, renvoyant LCase ()
. Ainsi, c'est une bonne idée de créer un Sub séparé pour lui comme ceci:
Private Sub Worksheet_Change(ByVal Target As Range) If Not Intersect(Target, Range("C6"), Range("C9:G9")) Is Nothing Then Exit Sub Application.EnableEvents = False FixRangeLCase Range("C6") FixRangeLCase Range("C9:G9") Application.EnableEvents = True End Sub
Ensuite, faites-lui référence à l'événement Worksheet_Change. Dans la mesure où l'événement Worksheet_Change
est assez "cher", en cours d'exécution toujours, il est judicieux de ne l'exécuter que lorsqu'une cellule cible spécifique est modifiée et sinon quittez la procédure - If Intersect ( Target, Range ("C6"), Range ("C9: G9")) Is Nothing Then Exit Sub
Le Application.EnableEvents = False
est nécessaire pour désactiver les événements. À la fin, il est remis à Vrai
.
Sub FixRangeLCase(rangeToFix As Range) Dim myCell As Range For Each myCell In rangeToFix myCell.Value2 = LCase(myCell.Value2) Next myCell End Sub
Vous pouvez également utiliser:
Option Explicit Private Sub Worksheet_Change(ByVal Target As Range) Dim rng As Range, cell As Range Application.EnableEvents = False If Not Intersect(Target, Range("C6")) Is Nothing Or Not Intersect(Target, Range("C9:G9")) Is Nothing Then Set rng = Range("C9:G9", "C6") For Each cell In rng cell.Value = LCase(cell.Value) Next End If Application.EnableEvents = True End Sub
Ce n'est pas correct car cela ne change que la cellule cible
Cette Target.Value = LCase (Target.Value)
échoue si Target
est une plage de plusieurs cellules. LCase
ne peut pas gérer un tableau de valeurs Target.Value
.
@newguy ce que vous mentionnez n'est pas un problème ici car seules les cellules Target
ont réellement changé, les autres sont donc déjà en minuscules (et n'ont pas besoin d'être converties à nouveau). • Le problème ici serait qu'il fonctionnerait sur toutes les cellules modifiées, même en dehors de la plage donnée, non seulement sur les cellules de C6, C9: G9
(mais en fait, il échoue car de la raison que j'ai mentionnée ci-dessus).
@Error Lors de l'utilisation de l'événement Worksheet_Change
, gardez toujours à l'esprit que Target
peut être une Range
collée non seulement une seule cellule.
@ Pᴇʜ je crois avoir compris le point et j'ai modifié la réponse. Est-ce correct?
Réponse @newguy modifiée. toutes autres suggestions ou corrections sont les bienvenues!
Mieux vaut ne pas planter parce que Target
est une plage. Mais notez que si, par exemple, seule la cellule C10 est éditée, le rng
complet est converti en minuscules alors que seul C10 a changé et il suffirait de convertir cette cellule uniquement. Pour éviter cela, consultez ma réponse où j'ai utilisé AffectedRange = Intersect (Target, Target.Parent.Range ("C6, C9: G9"))
pour obtenir uniquement les cellules modifiées de la plage souhaitée. Donc tu finirais avec ce que j'ai répondu.
À quoi sert .parent?
Si l'événement est déclenché alors qu'une autre feuille de calcul a le focus, je ne suis pas sûr sur quelle feuille de calcul Range
serait par défaut Target.Parent
donne la feuille de calcul où la plage Target code> se trouve. Cela garantit que
Range ("C6, C9: G9")
pointe vers la même feuille de calcul que celle vers laquelle pointe Target
. Juste pour être sauvé et ne pas laisser Excel décider de quelle feuille je veux dire.
Mettez simplement le code dans un seul événement.
Les réponses fournies sont toutes bonnes sauf qu'elles n'ont pas de gestion des erreurs. Donc, si votre code échoue entre les instructions "Application.EnableEvents = False" et "Application.EnableEvents = True", alors vous venez de quitter Excel est un mauvais état où aucun événement ne se déclenchera. Chaque fois que vous utilisez "Application.EnableEvents", "Application.ScreenUpdating", etc. utilisez toujours la gestion des erreurs pour vous assurer qu'en cas d'échec de votre code, ces types de paramètres sont réinitialisés à ce qu'ils doivent être. Je suis un développeur .NET / C # (VBA = Megablocks, C # = Lego Technic) et la gestion des erreurs est un must.
@FrankBall Bon, en a ajouté un dans ma réponse.