Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Excel VBA问题_Vba_Excel - Fatal编程技术网

Excel VBA问题

Excel VBA问题,vba,excel,Vba,Excel,使用以下代码自动设置上两列 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 .V

使用以下代码自动设置上两列

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
工作正常,问题是,如果用户选择多个单元格并点击delete,则会出错,然后用户点击End,该函数将不再工作。受保护的。运行时错误13,类型不匹配

不管单元格是否为空,仍然会得到错误


提前感谢。

以这种方式说明多个单元格:

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

@ScottHoltzman的答案解决了当前问题的问题,即当您将
UCASE
应用于
数组时会出现错误。当
目标
区域有多个单元格时,其
为数组,且
UCase
不接受数组参数

例程将退出此行(
.Value=UCase(.Value)
),并将错过重置
应用程序的下一行。EnableEvents=True
。在此之后,您将在禁用事件的情况下工作,因此所有事件处理例程都将停止工作,而不仅仅是这一个(如果您有其他此类例程)

为了避免这些情况,最好的方法是按照以下结构在事件处理程序中实现适当的错误处理

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
Sub my_Handler()
关于错误转到清理
Application.EnableEvents=False:Application.ScreenUpdate=False'等。。
''''''''''''''''''''''''''''''''''
'
'这里是例行程序的正常代码
'
''''''''''''''''''''''''''''''''''
清理:
如果错误号为0,则MsgBox错误说明
Application.EnableEvents=True、Application.ScreenUpdate=True等。。
端接头
要将其应用到日常工作中,请执行以下操作:

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
Private子工作表\u更改(ByVal目标作为范围)
关于错误转到清理
Application.EnableEvents=False:Application.ScreenUpdate=False'等。。
如果不是(Application.Intersect(目标,范围(“C2:P5000”))什么都不是),那么
Target.value=UCase(Target.value)
如果结束
清理:
如果错误号为0,则msgBox错误说明
Application.EnableEvents=True:Application.ScreenUpdate=True'等。。
端接头

重要的是,不要对所有例程自动使用此结构,只有
事件处理程序
或最终从GUI调用的宏。其他例程通常从这些处理程序或宏中调用,因此您可以正常编写它们。

如果它们选择多个单元格,那么我的想法是您应该使用SelectionChange宏,如下所示

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
或者,您可以将其更改回工作表\u change宏,如下所示,如果用户选择多个单元格或删除单元格而不导致错误,则不会出错。错误处理程序就在那里——就像在A.S.H.的解决方案中一样,但我还没有看到在我的测试中需要它

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

我试着把这句话放在对答案的评论中,但是太长了,很抱歉。。 @a-s-h@a.s.h 这一个工作得最好,稍加修改。谢谢

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
Private子工作表\u更改(ByVal目标作为范围)
关于错误转到清理
Application.EnableEvents=False:Application.ScreenUpdate=False'等。。
如果不是(Application.Intersect(目标,范围(“C2:C5000”,“P3:P5000”))为空),则
Target.Value=UCase(Target.Value)
如果结束
清理:
如果错误号为0,则转到终点线
结束行:
Application.EnableEvents=True:Application.ScreenUpdate=True'等。。
端接头

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

使用这些代码会在rCell.Value=UCase(.Value)行中获取“无效或不合格的引用。如果我将其更改为UCase(Target.Value),最后出现了相同的类型不匹配错误。@BenLogan-我编辑过。我忘记放置rCell.Value。这样做的同时,在大量删除(比如说50行)之后,用户必须等待Excel完成它的操作(在50个选定的单元格中迭代)。这需要多长时间?删除行不会触发“工作表更改”子例程。@Ben Logan,我已将“工作表更改”代码更改为忽略删除行时的反应,这样用户删除行时就不会损失时间。我选择了1000行,耗时.03秒,删除整行不需要任何时间。删除在同一时间从每一列中删除500个单词根本不需要任何时间。但是选择这1000个单词需要0.05秒。Ben,我的回答唯一的区别是你放弃了显示错误消息。虽然这偶尔是可以的,但我不建议在一般情况下使用它,因为我建议使用“常规”“错误处理机制,重要的是在出现问题时通知用户,否则他可能认为一切正常,最终会错过一些工作。除此之外,可以从代码中删除
EndLine
行及其上方的行,它们不起任何作用。:)