我有一个包含多个工作表更改事件的工作表。不幸的是,由于它们我得到了一些内存错误。我想知道是否有人可以查看这段代码片段并让我知道它是否可以更有效地编写?
当且仅当单元格K4 ="基于事件的"此工作表更改事件调用另一个宏。并且以下每个单元格中都包含一些内容:J12:J15,M12:M14。如果单元格J12:J15,M12:M14已填入并且K4更改为"基于事件"
,我可以调用宏Private Sub Worksheet_Change(ByVal Target As Range)
If Range("J12") <> "" And _
Range("J13") <> "" And _
Range("J14") <> "" And _
Range("J15") <> "" And _
Range("M12") <> "" And _
Range("M13") <> "" And _
Range("M14") <> "" Then
Dim ZRange As Range
Set ZRange = Range("K4")
If ZRange = "Event Based" Then
If Union(Target, ZRange).Address = ZRange.Address Then
Application.EnableEvents = False
Call EventBasedYes
Application.EnableEvents = True
End If
End If
End If
我的问题是,我为每个单独的单元格编写了不同的工作表更改事件。如果K4 =&#34;基于事件&#34;和J13:J15中有一些东西,然后数据被添加到J12
If Range("K4") = "Event Based" And _
Range("J13") <> "" And _
Range("J14") <> "" And _
Range("J15") <> "" And _
Range("M12") <> "" And _
Range("M13") <> "" And _
Range("M14") <> "" Then
Dim FRange As Range
Set FRange = Range("J12")
If FRange <> "" Then
If Union(Target, FRange).Address = FRange.Address Then
Application.EnableEvents = False
Call EventBasedYes
Application.EnableEvents = True
End If
End If
End If
我不知道如何编写一个事件,以便如果所有单元格都被填充,则调用宏,这样如果清除了任何一个单元格,则会调用一个名为EventBasedNo的宏。对不起,我对VBA代码不是很熟悉。我确定有办法做到这一点。
答案 0 :(得分:1)
One thing you could do would be to not execute a lot of tests on cell values unless you know that there is a possibility that you are going to need to do that test.
So your current code says:
If Range("J12") <> "" And _
Range("J13") <> "" And _
Range("J14") <> "" And _
Range("J15") <> "" And _
Range("M12") <> "" And _
Range("M13") <> "" And _
Range("M14") <> "" Then
Dim ZRange As Range
Set ZRange = Range("K4")
If ZRange = "Event Based" Then
If Union(Target, ZRange).Address = ZRange.Address Then
Application.EnableEvents = False
Call EventBasedYes
Application.EnableEvents = True
End If
End If
End If
which means that you are looking up the values of J12
, J13
, J14
, J15
, M12
, M13
, M14
and K4
, and then deciding whether the worksheet change happened in a cell you are interested in.
By moving the test regarding Target
's location earlier, you can save those lookups:
If Not Application.Intersect(Target, Range("K4")) Is Nothing Then
If Range("J12") <> "" And _
Range("J13") <> "" And _
Range("J14") <> "" And _
Range("J15") <> "" And _
Range("M12") <> "" And _
Range("M13") <> "" And _
Range("M14") <> "" Then
Dim ZRange As Range
Set ZRange = Range("K4")
If ZRange = "Event Based" Then
Application.EnableEvents = False
Call EventBasedYes
Application.EnableEvents = True
End If
End If
End If
If a lot of the cells you are checking are likely to be part of the Target
of a single Worksheet_Change event then you may be better off testing for all the cells you are interested in first, i.e. using something like:
If Not Application.Intersect(Target, Range("K4,J12,X47")) Is Nothing Then
and then storing the values of the cells that you are frequently referring to in variables (or a Variant array if they are in a contiguous block?) so that you can refer to the variables multiple times rather than have to access the cell itself multiple times.
P.S. Union(Target, ZRange).Address = ZRange.Address
is equivalent to Target.Address = ZRange.Address
. Is it intentional that your code only fires if a single cell is changed (i.e. you don't want the code to run if cells K2:K6 are changed in a single event, only if K4 is changed by itself)? My proposed change uses an Intersect
, which will run if the changed range includes the cell you are interested in, so you should change that back if you don't want that to happen.
I think I understand what you are trying to do. Perhaps the following code will do all your tests at once:
If Not Application.Intersect(Target, Range("K4,J12:J15,M12:M14")) Is Nothing Then
Application.EnableEvents = False
If Range("J12").Value <> "" And _
Range("J13").Value <> "" And _
Range("J14").Value <> "" And _
Range("J15").Value <> "" And _
Range("M12").Value <> "" And _
Range("M13").Value <> "" And _
Range("M14").Value <> "" And _
Range("K4").Value = "Event Based" Then
Call EventBasedYes
Else
Call EventBasedNo
End If
Application.EnableEvents = True
End If