请尝试下面的代码将它安装在您想要的工作表的代码表中你的按钮
查看顶部的Enum作为某种控制面板,这是你在整个代码中设置参数的地方,例如,你可以将第一个数据行从2更改为其他东西。命名为D列“NclTest”和列N“NclResult ”。使用编辑/替换将这些名称更改为更合适的名称。请注意,枚举名称不区分大小写。所以,如果你用小写字母写下他们,我的宝贵资本将永远消失。
我已经设置了列O(15)采取“按钮”。如果您在列O中有其他内容,则必须更改。分配一个空列。
现在,当您激活工作表时,将会检查列N中的所有项目,并在列O中创建“按钮”。每当有更改时,都会进行更新。因此不需要超过一次。但请记住,更新不适用于多个单元格。因此,如果您复制/粘贴更大的范围,请停用并重新激活工作表以更新按钮。
Option Explicit
Const Pw As String = "password"
Private Enum Ncl ' worksheet columns
' 11 Aug 2017
NclFirstDataRow = 2 ' change as appropriate
NclTest = 4 ' 4 = D (used to test if range is locked)
NclResult = 14 ' 14 = N
NclButton = 15 ' = column O (change as required)
End Enum
Private Sub Worksheet_Activate()
' 29 Aug 2017
Dim TestVal
Dim Cap As String
Dim Rl As Long
Dim R As Long
Application.ScreenUpdating = False
With ActiveSheet
Rl = .Cells(.Rows.Count, NclResult).End(xlUp).Row
For R = NclFirstDataRow To Rl
ResetButton R
Next R
' you can double-click this cell to end Administrator rights
.Cells(1, NclButton).Locked = False
.Protect Password:="", _
DrawingObjects:=True, _
Contents:=True, _
Scenarios:=True, _
UserInterfaceOnly:=True
.EnableSelection = xlUnlockedCells
End With
Application.ScreenUpdating = True
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
' 29 Aug 2017
Dim LockStatus As Boolean
Set Target = Target.Cells(1) ' only accept first cell
' meaning you can't copy/paste ranges
If Not Application.Intersect(Target, WsRange) Is Nothing Then
If Target.Locked Then
MsgBox "This cell is locked for editing", _
vbInformation, "Modification not allowed"
With Application
.EnableEvents = False
.Undo
.EnableEvents = True
End With
Exit Sub
End If
End If
' reset the button when Result is changed
If Application.Intersect(Target, WsRange(C:=NclResult)) Is Nothing Then
' reset range lock when button is changed
If Not Application.Intersect(Target, WsRange(C:=NclButton)) Is Nothing Then
With Target
If Len(Trim(.Value)) Then
LockStatus = (.Value = BtnCap(1))
WsRange(.Row).Locked = LockStatus
Else
ResetButton .Row
End If
End With
End If
Else
ResetButton Target.Row
End If
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
' 29 Aug 2017
Static PermitEdit As Boolean
Dim Cap As String
Set Target = Target.Cells(1) ' only accept first cell
' meaning you can't copy/paste ranges
If Target.Address = ActiveSheet.Cells(1, NclButton).Address Then
If PermitEdit Then
PermitEdit = False
MsgBox "Administrator rights have been terminated.", _
vbInformation, "End of Admin session"
End If
Else
If Not Intersect(Target, WsRange(C:=NclButton)) Is Nothing Then
Application.EnableEvents = False
With Target
Do While Not PermitEdit
If RefuseAccess(PermitEdit) Then GoTo AccessDenied
Loop
Cap = Trim(.Value)
If Len(Cap) Then
.Value = BtnCap(Int(Cap = BtnCap(1)) + 1)
End If
.Offset(0, -1).Select
End With
AccessDenied:
Application.EnableEvents = True
End If
End If
End Sub
Private Function RefuseAccess(PermitEdit As Boolean) As Boolean
' 29 Aug 2017
Dim Pass As String
Dim Rl As Long
Pass = InputBox("Please enter the administrator's password", _
"Password required")
PermitEdit = Not CBool(StrComp(Pass, Pw, vbBinaryCompare))
If PermitEdit Then
With ActiveSheet
Rl = .Cells(.Rows.Count, NclResult).End(xlUp).Row
.Range(.Cells(NclFirstDataRow, NclButton - 1), .Cells(Rl, NclButton)).Locked = False
End With
Else
If Len(Pass) Then
MsgBox "The password is not correct." & vbCr & _
"Access will be denied.", _
vbInformation, "Invalid password"
End If
End If
RefuseAccess = Not PermitEdit
End Function
Private Function BtnCap(ByVal CapId As Long) As String
' 11 Aug 2017
BtnCap = Split("LOCK,UNLOCK", ",")(CapId)
End Function
Private Function WsRange(Optional R As Long, _
Optional C As Long) As Range
' 11 Aug 2017
Dim Rstart As Long, Rend As Long
Dim Cstart As Long, Cend As Long
If R Then
Rstart = R
Rend = R
Else
Rstart = NclFirstDataRow
Rend = Cells(Rows.Count, NclResult).End(xlUp).Row
End If
If C Then
Cstart = C
Cend = C
Else
Cstart = NclTest
Cend = NclResult
End If
Set WsRange = Range(Cells(Rstart, Cstart), Cells(Rend, Cend))
End Function
Private Sub ResetButton(ByVal R As Long)
' 11 Aug 2017
Dim TestVal
Dim Cap As String
With Cells(R, NclResult)
TestVal = .Value
If Len(TestVal) Then
Cap = ""
Else
' if NclTest is locked then D:N are presumed locked
Cap = BtnCap(Int(Cells(R, NclTest).Locked) + 1)
End If
End With
With Cells(R, NclButton)
If .Value <> Cap Then
.Value = Cap
End If
End With
End Sub
没有按钮。这只是列O中标有“LOCK”或“UNLOCK”的单元格。虽然列N不是空列O将是空白的。如果N为空,O将会有一个按钮,它可以点击。您不能点击两次而不点击其他地方。这是Excel,而不是我。您可以按Delete按照您希望的频率切换。
当“按钮”显示“锁定”时,单元格D:N将被解锁并可以进行编辑。如果编辑N,该按钮可能会消失。如果按钮是“UNLOCK”,则单元格被锁定,当您尝试编辑它们之后编辑被反转时,您会收到一条消息。你猜对了:我不喜欢工作表保护。
使用代码或者只是格式化O列,可以轻松地对“按钮”进行一点格式化。使用类似的方法,您可以突出显示锁定的单元格。我不想这样做。所以我把最好的一部分乐趣留给了你。 :-)
单元格如何变为非空白? – jsotola
@jsotola。你好,伙计。通过向其输入数据,单元格变为非空白。我想锁定他们点击按钮后输入的数据。 – Omar
提示:您可以用一行代替工作表中的'if ... then ... else' CommandButton2.Visible =(Cells(1,14).Value <>“”)' – jsotola