Excel vba代码中的多个工作表更改事件

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

我在合并两个工作表更改事件时遇到问题-我可以从大师那里得到一些建议吗

代码的目的是将给定单元格范围内的任何大写文本转换为小写,但显然我不能有两个事件

我试着将两者复制到同一个工作表中,但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 = 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决定我指的是哪张表。谢谢!这就解决了问题