Option Explicit
'iRng 为上一次选中的单元格,全局变量
Dim iRng As Object
'val为上一次选中单元格的值
Dim val
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
'本功能可以实现通过判断表格第26列的布尔值来决定是否允许用户修改单元格的值
'不允许修改的逻辑为:保存上一次选中单元格的range和range的value
'不允许修改的核心方法是给上一次选中的单元格赋值修改前的值
'保存上一次选中单元格的range是为了知道上一个选中单元格的地址,存值是因为上一个选中的单元格值修改就找不到了
'bug:如果选中的一个区域而不是单元格则无效
'如果是操作锁定列,或表格之外的区域则退出sub
If Target.Column > 25 Then Exit Sub
'初始化状态栏
Application.StatusBar = ""
If Cells(Target.Row, 26) Then
'在状态栏显示单元格锁定信息,没有锁定则无需显示
Application.StatusBar = Application.StatusBar & "----当前单元格已锁定"
End If
'如果选中的不是一个区域则
If Not IsArray(Target.Value) Then
'如果iRng没有赋值则现在赋值
If iRng Is Nothing Then
Set iRng = Target
val = iRng.Formula
Else
'判断本列是否锁定
If Cells(iRng.Row, 26) Then
'如果锁定了,且现在的值不等于原来的值则,还原原来的值
If iRng.Formula <> val Then
'写入修改的日志信息
iLog Target
'时光倒流
iRng.Formula = val
'写入修改失败的日志信息
log.Cells(log.Cells(1, 10).Value - 1, 5).Value = False
End If
Else
'如果没有锁定,且现在的值不等于原来的值
If iRng.Formula <> val Then
'写入日志
iLog Target
'写入修改成功的日志信息
log.Cells(log.Cells(1, 10).Value - 1, 5).Value = True
End If
End If
End If
'保留时光
Set iRng = Target
'保留时光公式
val = iRng.Formula
End If
End Sub
Private Sub iLog(ByVal Target As Range)
Debug.Print log.Cells(1, 10).Value
'在第1列写入时间
log.Cells(log.Cells(1, 10).Value, 1) = Now
'在第2列写入单元格地址
log.Cells(log.Cells(1, 10).Value, 2) = Target.Address
'在第3列写入单元格原值
log.Cells(log.Cells(1, 10).Value, 3) = val
'在第4列写入单元格新值
log.Cells(log.Cells(1, 10).Value, 4).Value = iRng.Formula
'在第10列第1行写入下一次写入新的日志的行号
log.Cells(1, 10).Value = log.Cells(1, 10).Value + 1
End Sub
下面是运行效果, 代码放在sheet1里面使用,再新建一个sheet,在VBA界面属性里面修改新建的sheet2名称为log