以下VBA位将突出显示工作表中包含数据验证错误的所有单元格:
Sub CheckValidation(sht As Worksheet)
Dim cell As Range
Dim rngDV As Range
Dim dvError As Boolean
On Error Resume Next
Set rngDV = sht.UsedRange.SpecialCells(xlCellTypeAllValidation)
On Error GoTo 0
If rngDV Is Nothing Then
sht.ClearCircles
Else
dvError = False
For Each cell In rngDV
If Not cell.Validation.Value Then
dvError = True
Exit For
End If
Next
If dvError Then
sht.CircleInvalid
sht.Activate
Else
sht.ClearCircles
End If
End If
End Sub
但是,“For Each”循环在具有大量数据验证的工作表中运行速度非常慢。
有没有人知道如何避免“For Each”循环,或以某种方式加速?
我原以为以下等同于设置'dvError'的值:
dvError = Not rngDV.Validation.Value
但由于某些原因,即使存在数据验证错误,rngDV.Validation.Value也是如此。
答案 0 :(得分:2)
我的要求略有不同,我希望将用户输入的值限制为有效的日期范围或我使用以下方法解析的文字“ASAP”;
Private Sub Worksheet_Change(ByVal Target As Range)
Dim sErr As String
Dim sProc As String
On Error GoTo ErrHandler
Application.EnableEvents = False
Select Case Target.Column
Case 11
sProc = "Validate Date"
'The value must be a date between "1 Nov 2011" and "30 Jun 2012" or "ASAP"...
If IsDate(Target.Value) Then
If Target.Value < CDate("2011-11-01") _
Or Target.Value > CDate("2012-06-30") Then
Err.Raise vbObjectError + 1
End If
ElseIf LCase(Target.Value) = "asap" Then
Target.Value = "ASAP"
ElseIf Len(Trim(Target.Value)) = 0 Then
Target.Value = vbNullString
Else
Err.Raise vbObjectError + 1
End If
End Select
ErrHandler:
Select Case Err.Number
Case 0
'Nothing to do...
Case vbObjectError + 1
sErr = "The Date must be between ""1 Nov 2011"" and ""30 Jun 2012"" or equal ""ASAP""."
Case Else
sErr = Err.Description
End Select
If Len(Trim(sErr)) > 0 Then
Target.Select
MsgBox sErr, vbInformation + vbOKOnly, sProc
Target.Value = vbNullString
End If
Application.EnableEvents = True
End Sub
答案 1 :(得分:1)
尝试使用4536个包含验证的单元格,你的代码运行得非常快 - 因为你在第一次出现未经验证的单元格时正确地破坏了你的FOR
我尝试通过以下方式在代码的各个点测量时间:
Dim Tick As Variant
Tick = Now()
' ... code
Debug.Print "ValCount", rngDV.Cells.Count ' just to see how many cells are in that range
' ... code
Debug.Print "Pt1", (Now() - Tick) * 86400000 'display milliseconds
' ... code
Debug.Print "Pt2", (Now() - Tick) * 86400000 'display milliseconds
' ... code
Debug.Print "Pt3", (Now() - Tick) * 86400000 'display milliseconds
' etc.
并且有一个不可测量的延迟(当通过F8步进调试器时除外 - 当然)
作为一般提示...试着找出你的代码在哪里很慢,让我们从那里开始。