我的VBA代码存在一些问题,其目的是:
我目前的代码是:
Private Sub Worksheet_Change(ByVal Target As Excel.Range)
Dim blnUnlockedAllCells As Boolean
If Target.Column = 11 And Target.Value <> "X" Then
Exit Sub
ElseIf Target.Column = 11 And Target.Value = "X" Then
ThisRow = Target.Row
If Target.Value <> "" Then
Range("L" & ThisRow).Value = Now
End If
End If
If Target.Value <> "X" Then Exit Sub
Const RangeToLock As String = "K8:K1000"
If Target.Cells.Count > 1 Then Exit Sub
If Not blnUnlockedAllCells Then
Me.Cells.Locked = False
On Error Resume Next
Me.Range(CStr(RangeToLock)).SpecialCells(2).Locked = True
On Error GoTo 0
blnUnlockedAllCells = True
Me.Protect Password:="PWD", userinterfaceonly:=True
End If
If Not Application.Intersect(Target, Me.Range(CStr(RangeToLock))) Is Nothing Then
If Len(Target) Then Target.Locked = True
End If
End Sub
似乎锁定RangeToLock中所有非空白的单元格而不是等于“X”的单元格。
任何帮助将不胜感激,我完全接受有关如何处理上述任何内容的其他建议。
由于
答案 0 :(得分:0)
根据您的描述,我猜测您过度思考了这一点。
首先,您似乎已将工作表锁定为UserInterfaceOnly
,这意味着您甚至根本不必解锁任何内容。只需更改要锁定的单元格的.Locked
属性即可,并且不要轻易保护工作表。
其次,正如我在评论中提到的,Target
并不总是只有一个单元格(想想复制粘贴)。这意味着您必须单独遍历Target
中的所有单元格。这也意味着您在测试Target.Value <> "X"
之前无法测试If Target.Cells.Count > 1
,因为如果您获得多个单元格,则会出现类型不匹配运行时错误。
第三,除非您需要根据在L
列中写入时间戳来处理其他事件,否则应在编写更改之前禁用事件处理,然后重新启用它。目前,您没有任何方法可以阻止重新进入事件处理程序。
那就是说,你可以简化整个程序,既安全又有工作的愉快副作用:
Private Sub Worksheet_Change(ByVal Target As Excel.Range)
Dim c As Range
For Each c In Target
If c.Column = 11 And c.Value = "X" Then
Application.EnableEvents = False
If Not c.Locked Then
c.Locked = True
Target.Parent.Cells(c.Row, 12).Value = Now
End If
Application.EnableEvents = True
End If
Next
End Sub
请注意,这假定工作表已受到保护。如果不是,请将单行If Not Me.ProtectionMode Then Me.Protect "PWD", , , , True
添加到过程的顶部,或者(更好)添加Worksheet_Activate()
事件。
答案 1 :(得分:0)
对于我对共产国际回答的修改请求,
Private Sub Worksheet_Change(ByVal Target As Excel.Range)
If Target.Cells.Count > 1 Then Exit Sub
PW = "PWD"
Dim iRet As Integer
Dim strPrompt As String
Dim strTitle As String
strPrompt = "Are you sure you want to set this field to X?"
strTitle = "Alert"
If Not Me.ProtectionMode Then Me.Protect PW, , , , True
Dim c As Range
For Each c In Target
If c.Column = 11 And c.Value <> "X" Then
Exit Sub
ElseIf c.Column = 11 And c.Value = "X" Then
iRet = MsgBox(strPrompt, vbYesNo, strTitle)
If iRet = vbNo Then
ActiveCell.ClearContents
ActiveSheet.Protect DrawingObjects:=True, Contents:=True, Scenarios:=True, Password:=PW
Exit Sub
ElseIf iRet = vbYes Then
Application.EnableEvents = False
If Not c.Locked Then
c.Locked = True
Target.Parent.Cells(c.Row, 13).Value = Now
Target.Parent.Cells(c.Row, 13).Locked = True
End If
Application.EnableEvents = True
End If
End If
Next
End Sub
我非常感谢任何关于我如何简化或改善这一点的提示!