Excel VBA问题

使用下面的代码来自动调高两列,

Private Sub Worksheet_Change(ByVal Target As Range) If Not (Application.Intersect(Target, Range("C2:C5000", "P3:P5000")) _ Is Nothing) Then With Target Application.EnableEvents = False .Value = UCase(.Value) Application.EnableEvents = True End With End If End Sub 

完美的工作,问题是,如果用户select多个单元格,并命中删除,它错误,然后用户点击结束,function不再起作用。 保护。 运行时错误13,types不匹配。

没有问题,如果单元格是空的,仍然会得到错误。

提前致谢。

@ScottHoltzman的答案解决了当前问题的问题,即将UCASE应用于Array时出现错误。 当Target范围有多个单元格时,它的.Value是一个数组,而UCase不接受数组参数。

您的例程将退出此行( .Value = UCase(.Value) ),并将错过下一行重置Application.EnableEvents = True 。 在那之后,你最终会使用禁用的事件,所以你所有的事件处理例程都将停止工作,而不仅仅是这个(如果你有其他的例程的话)。

为了避免这些情况,好的方法是在事件处理程序中实现适当的error handling,遵循这个结构

 Sub my_Handler() On Error Goto Cleanup Application.EnableEvents = False: Application.ScreenUpdating = False ' etc.. '''''''''''''''''''''''''''''''''' ' ' normal code of the routine here ' '''''''''''''''''''''''''''''''''' Cleanup: if Err.Number <> 0 Then MsgBox Err.Description Application.EnableEvents = True, Application.ScreenUpdating = True ' etc.. End Sub 

把它应用到你的例程中:

 Private Sub Worksheet_Change(ByVal Target As Range) On Error GoTo Cleanup Application.EnableEvents = False: Application.ScreenUpdating = False ' etc.. If Not (Application.Intersect(Target, Range("C2:P5000")) Is Nothing) Then Target.value = UCase(Target.value) End If Cleanup: If Err.Number <> 0 Then msgBox Err.Description Application.EnableEvents = True: Application.ScreenUpdating = True ' etc.. End Sub 

重要的是,不要为所有的例程自动使用这个结构,只能使用Event handlers或者最终的macros来调用GUI。 其他例程通常由这些处理程序或macros调用,因此您可以正常编写它们。

我试图把这个评论的答案,但时间太长,很抱歉.. @ash @ash这一个工作最好的,稍作修改。 谢谢!

 Private Sub Worksheet_Change(ByVal Target As Range) On Error GoTo Cleanup Application.EnableEvents = False: Application.ScreenUpdating = False ' etc.. If Not (Application.Intersect(Target, Range("C2:C5000", "P3:P5000")) Is Nothing) Then Target.Value = UCase(Target.Value) End If Cleanup: If Err.Number <> 0 Then GoTo EndLine EndLine: Application.EnableEvents = True: Application.ScreenUpdating = True ' etc.. End Sub 

执行大写,并删除多个一次没有任何错误,或MsgBox的。

如果他们正在select多个单元格,那么我的想法是,你会想要使用SelectionChangemacros,而不是像这样

 Private Sub Worksheet_SelectionChange(ByVal Target As Range) Dim StartTime As Double Dim SecondsElapsed As Double StartTime = Timer If ((Target.Address = Target.EntireRow.Address Or _ Target.Address = Target.EntireColumn.Address)) Then Exit Sub Application.EnableEvents = False If Not (Application.Intersect(Target, Range("C2:C5000", "P3:P5000")) _ Is Nothing) Then On Error GoTo endItAll For Each aCell In Target.Cells Range(aCell.Address) = UCase(Range(aCell.Address)) Next aCell End If endItAll: Application.EnableEvents = True SecondsElapsed = Round(Timer - StartTime, 2) Debug.Print SecondsElapsed End Sub 

或者你可以把它改回到如下的worksheet_Changemacros,如果用户select多个单元格或者删除单元格而不会导致错误,那么就不会出错。 error handling程序在那里 – 就像在ASH的解决scheme,但我还没有看到它在我的testing需要。

 Private Sub Worksheet_Change(ByVal Target As Range) Application.EnableEvents = False If Not (Application.Intersect(Target, Range("C1:C5000", "D1:D5000")) _ Is Nothing) Then On Error GoTo endItAll For Each aCell In Target.Cells Range(aCell.Address) = UCase(Range(aCell.Address)) Next aCell End If endItAll: Application.EnableEvents = True End Sub 

以这种方式考虑多个单元格:

 Private Sub Worksheet_Change(ByVal Target As Range) If Not (Application.Intersect(Target, Range("C2:C5000", "P3:P5000")) _ Is Nothing) Then Dim rCell as Range Application.EnableEvents = False For each rCell in Target rCell.Value = UCase(rCell.Value) Next Application.EnableEvents = True End If End Sub