Excel vba代码中的多个工作表更改事件
我在合并两个工作表更改事件时遇到问题-我可以从大师那里得到一些建议吗 代码的目的是将给定单元格范围内的任何大写文本转换为小写,但显然我不能有两个事件 我试着将两者复制到同一个工作表中,但Excel出现错误并崩溃 范围1:Excel vba代码中的多个工作表更改事件,excel,vba,Excel,Vba,我在合并两个工作表更改事件时遇到问题-我可以从大师那里得到一些建议吗 代码的目的是将给定单元格范围内的任何大写文本转换为小写,但显然我不能有两个事件 我试着将两者复制到同一个工作表中,但Excel出现错误并崩溃 范围1: Private Sub Worksheet_Change(ByVal Target As Range) Dim ccr As Range Set ccr = Range("C6") For Each Cell In ccr Cell.Value
Private Sub Worksheet_Change(ByVal Target As Range)
Dim ccr As Range
Set ccr = Range("C6")
For Each Cell In ccr
Cell.Value = LCase(Cell)
Next Cell
End Sub
范围2:
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
非常感谢像这样,你可以在同一事件中同时做这两件事 您必须在开始时添加
Application.EnableEvents=False
,以避免竞争条件
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
主要问题是更改单元格值
cell.value
会立即触发另一个工作表\u Change
。您需要Application.EnableEvents=False
来防止这种情况
我还建议使用Intersect
,这样代码只在实际更改的单元格上运行
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
除了@Frank Ball的评论,包括错误处理:
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
Private子工作表\u更改(ByVal目标作为范围)
变暗影响范围作为范围
Set AffectedRange=Intersect(Target,Target.Parent.Range(“C6,C9:G9”))
Application.EnableEvents=False“异常触发另一个更改事件”
关于错误转到错误处理
如果不受影响,那么范围什么都不是
暗淡的Cel As范围
对于受影响范围内的每个细胞
Cel.Value=LCase$(Cel.Value)
下一个细胞
如果结束
错误转到0
“这里没有出口潜艇!
错误处理:
Application.EnableEvents=True
如果错误号为0,则
Err.Raise Err.Number、Err.Source、Err.Description、Err.HelpFile、Err.HelpContext
如果结束
端接头
这两个工作表\u Change
事件完全相同,它们是一个范围内的循环,返回LCase()
。因此,最好为其制作一个单独的子组件,如下所示:
Sub FixRangeLCase(rangeToFix As Range)
Dim myCell As Range
For Each myCell In rangeToFix
myCell.Value2 = LCase(myCell.Value2)
Next myCell
End Sub
然后,将工作表更改事件提交给它。由于工作表\u Change
事件非常“昂贵”,因此始终运行,最好仅在特定目标单元格更改时运行,否则退出过程-如果Intersect(Target,Range(“C6”)、Range(“C9:G9”))为空,则退出Sub
禁用事件需要Application.EnableEvents=False
。最后,它被设置回True
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
您还可以使用:
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
只需将代码放在一个事件中即可。提供的答案都很好,只是没有错误处理。因此,如果您的代码在“Application.EnableEvents=False”和“Application.EnableEvents=True”语句之间失败,那么您刚刚离开的Excel是一个不好的状态,不会触发任何事件。无论何时使用“Application.EnableEvents”、“Application.ScreenUpdate”等,都要使用错误处理,以确保在代码失败时,这些设置会恢复到需要的状态。我是.NET/C#开发者(VBA=Megablocks,C#=Lego Technic),错误处理是必须的。@FrankBall Right,在我的答案中添加了一个。这不对,因为它只会更改目标单元格。如果
target
是多个单元格的范围,则此target.Value=LCase(target.Value)
失败LCase
无法处理值数组Target。Value
@newguy您提到的在这里不是问题,因为只有Target
单元格实际发生了更改,因此其他单元格已经是小写(不需要再次转换)。•这里的问题是,即使在给定范围之外,它也会在所有更改的单元格上运行,而不仅仅是在C6、C9:G9
中的单元格上运行(但实际上,由于我上面提到的原因,它失败了)。更好的意思是,不会因为目标
在某个范围内而崩溃。但请注意,如果仅编辑eg单元格C10,则完整的rng
将转换为小写,而仅更改C10,仅转换此单元格即可。为了防止出现这种情况,请参见我的答案,其中我使用了AffectedRange=Intersect(Target,Target.Parent.Range(“C6,C9:G9”))
仅获取所需范围的更改单元格。因此,您将以我的回答结束。如果事件是在另一个工作表有焦点时触发的,我不确定哪个工作表Range
将默认Target。Parent
将给出范围Target
所在的工作表。因此,这确保范围(“C6,C9:G9”)
指向与目标所指向的工作表相同的工作表。只是为了保存,不要让Excel决定我指的是哪张表。谢谢!这就解决了问题