MS Access 2013 如何实现弹出窗体显示记录锁定状态及锁定用户
MS Access 2013 自定义记录锁定提示落地实现
完全可以实现你需要的自定义弹窗效果,不需要依赖Access自带的默认锁定提示。因为Access原生的锁定提示本身无法读取并展示记录被谁锁定的信息,需要搭配轻量的状态追踪逻辑、VBA错误捕获,和你已经配置的“编辑记录”级锁机制配合,就能拿到你要的两类提示内容。
实现前提
你已经设置的窗体属性(记录锁定=编辑记录)是核心基础,这层原生锁会从底层阻止两个用户同时编辑同一条记录,不会出现数据写入冲突。但因为原生锁只返回“记录被锁定”的报错、不返回锁定人信息,所以需要额外补一层自建的锁追踪逻辑来获取锁定用户名。别想着直接解析后端生成的.laccdb锁文件拿用户信息,这个方法不同Access版本的文件结构不统一,兼容性差、维护成本高,远不如自建追踪表稳定。
分步实现方案
1. 搭建共享锁状态追踪表
这张表必须建在后端共享数据库里,用来跨用户同步记录占用状态,表结构配置:
- 表名:
tbl_RecordLocks - 字段明细:
LockID:自动编号类型,设为主键TableName:短文本类型,存储被锁定记录所属的表名RecordID:长整型类型,存储被锁定记录的唯一主键值LockUser:短文本类型,存储当前占用该记录编辑权限的用户账号LockTime:日期/时间类型,默认值设为=Now(),记录锁定的触发时间,用于后续清理死锁
2. 给绑定编辑窗体挂载核心VBA逻辑
在需要做编辑权限控制的绑定窗体上,绑定对应事件的代码:
- 当用户开始编辑当前记录(触发
Form_Dirty事件)时,先做锁状态校验:Private Sub Form_Dirty(Cancel As Integer) Dim currentUser As String Dim checkSQL As String ' 获取当前本地登录的用户名,也可以替换为你系统的统一登录账号 currentUser = Environ("USERNAME") ' 查询当前要编辑的记录是否被其他用户占用 checkSQL = "SELECT LockUser FROM tbl_RecordLocks " & _ "WHERE TableName = '" & Me.RecordSource & "' " & _ "AND RecordID = " & Me.Recordset("ID") & " " & _ "AND LockUser <> '" & Replace(currentUser, "'", "''") & "'" Dim rs As DAO.Recordset Set rs = CurrentDb.OpenRecordset(checkSQL, dbOpenSnapshot) If Not rs.EOF Then ' 检测到其他用户的锁,取消编辑状态,弹出自定义提示窗 Cancel = True Me.Undo DoCmd.OpenForm "frm_LockNotice", OpenArgs:=rs!LockUser rs.Close Exit Sub End If rs.Close ' 没有检测到其他锁,给当前用户登记一条锁记录 CurrentDb.Execute "INSERT INTO tbl_RecordLocks (TableName, RecordID, LockUser, LockTime) " & _ "VALUES ('" & Me.RecordSource & "', " & Me.Recordset("ID") & ", '" & Replace(currentUser, "'", "''") & "', Now())", _ dbFailOnError End Sub - 当用户完成保存、切换记录、关闭窗体时,清理自己留下的锁记录,避免锁残留:
先写一个通用的锁清理函数:
分别在窗体的3个事件里调用这个函数:Private Sub ReleaseCurrentLock() Dim currentUser As String currentUser = Environ("USERNAME") ' 清理当前用户在当前记录上的锁标记 CurrentDb.Execute "DELETE FROM tbl_RecordLocks " & _ "WHERE TableName = '" & Me.RecordSource & "' " & _ "AND RecordID = " & Me.Recordset("ID") & " " & _ "AND LockUser = '" & Replace(currentUser, "'", "''") & "'", _ dbFailOnError End SubAfterUpdate:记录保存完成后调用Current:切换到新记录前,清理上一条记录的锁Unload:关闭窗体时,清理当前记录的锁
3. 配置自定义提示弹窗
你要做的弹出窗体frm_LockNotice直接设为弹出式、模式窗体,在窗体的加载事件里根据传入的OpenArgs渲染提示内容:
Private Sub Form_Load() Me!txtPrompt.Caption = "该记录已被其他用户锁定,无法编辑" & vbNewLine & _ "当前锁定该记录的用户:" & Nz(Me.OpenArgs, "未知用户") End Sub
4. 死锁兜底清理
如果遇到用户强关Access、断网的异常情况,之前登记的锁记录不会被自动清理,需要加定时清理逻辑:
- 在系统主切换面板窗体上设置
TimerInterval = 60000(即每1分钟触发一次定时事件) - 在Timer事件里清理所有锁定时间超过10分钟的无效锁记录,避免出现永久锁死的情况
兼容补全
你原来设置的“编辑记录”锁配置不要改动,这是最后一层保险:就算锁追踪逻辑因为网络延迟没及时检测到其他用户的锁,原生的记录锁还是会拦截并发写入,不会造成数据冲突。同时需要拦截Access原生的锁提示弹窗,不然用户还是会看到系统默认的无意义报错:
Private Sub Form_Error(DataErr As Integer, Response As Integer) ' 拦截原生锁触发的3186错误 If DataErr = 3186 Then ' 屏蔽系统默认提示,换成自己的弹窗 Response = acDataErrContinue DoCmd.OpenForm "frm_LockNotice", OpenArgs:="其他在线用户" End If End Sub
内容的提问来源于stack exchange,提问作者TechOffAl
相关产品推荐
相关产品推荐

