在 Access VBA 中禁止写入冲突消息
Posted
技术标签:
【中文标题】在 Access VBA 中禁止写入冲突消息【英文标题】:suppress write conflict message in Access VBA 【发布时间】:2009-02-23 17:09:11 【问题描述】:我的问题。
我编写了一个存储过程来计算通过 Ms Access 前端(到 MSSQL2000 db)上的表单呈现的字段数量。
只要我调用 Me.Form.Requery 来获取更改的值。我可以收到我引起写入冲突的恼人消息。
自从您开始编辑此记录后,其他用户已对其进行了更改。如果您保存记录,您将覆盖其他用户所做的更改。 将更改复制到剪贴板将让您查看其他用户输入的值, 如果您决定进行更改,然后将更改粘贴回来。
我知道是我更改了数据,所以我想隐藏消息或阻止消息发生。
【问题讨论】:
您真的要更改表单中的任何数据吗? 是的,我愿意。我有 2 个“做”同样事情的应用程序,我想从另一个应用程序重用存储过程。当 sproc 触发时,它会更新该表单上的数据。 所以存储过程更新数据而不是表单本身的任何数据条目? 不在那个阶段。输入数据,然后 sproc 对其进行处理,更新表单上的某些字段。 在运行存储过程之前将记录保存在表单中。 【参考方案1】:(我想我应该把我的 cmets 放在一个帖子里,因为我实际上是在回答这个问题)
您收到写入冲突消息的原因是您通过表单和存储过程编辑记录创建了写入冲突。为避免该错误,只需在执行存储过程之前将记录保存在表单中即可。从上面发布的代码 sn-p 来看,它应该是:
Me.Dirty = False
cmd.Execute , , adCmdStoredProc
这是一个常见的 Access 错误,它是由于尝试通过绑定表单和直接 SQL 更新来编辑数据而引起的。在通过 SQL 更新同一条记录之前,您需要保存表单的编辑缓冲区。
换句话说,您应该感谢出现错误消息,否则,您将丢失其中一项更改。
不过,我质疑设计。如果您在绑定表单中打开了记录,则对表单中加载的数据进行编辑,而不是运行 SQL 来更新它。我不确定为什么您需要一个存储过程来更改您已经在表单中编辑的记录——这对我来说听起来像是一个设计错误(即使解决方案很简单)。
【讨论】:
证明设计的合理性。我有 2 个系统 Access 和 .Net 做同样的事情(在数据库中的字段上运行计算)。 Access 使用 VBA 进行计算,.Net 使用存储过程。我必须进行更改并希望应用 DRY,因此 sproc 是它的最佳位置。 很好的答案!我在 AfterUpdate 事件上触发了记录集更新。这导致 VBA 代码尝试更新与用户绑定表单中的记录相同的记录。将“Me.Dirty = False”添加到 VBA 提交表单数据,使 VBA 可以毫无问题地完成其工作。谢谢!【参考方案2】:我有一个链接到后端 SQL 数据库的访问表单。链接到子表单的表上的触发器会更新表单中的字段。如果在更改子表单中的值后在表单中编辑同一记录,则会收到错误消息“写入冲突此记录已更改....”。
触发器更新的字段不能直接在表单上更改,因此选择“保存记录”总是可以的,但我不知道如何自动选择“保存记录”。
正如其他人所说,避免错误的方法是在编辑记录之前重新查询表单,但这会使用户体验不太流畅。
我终于找到了解决方法:
在表单的类模块中输入:
Private Sub Form_Error(DataErr As Integer, Response As Integer)
If DataErr = 7787 Then
Response = acDataErrContinue
Me.Recordset.MovePrevious
Me.Recordset.MoveNext
End If
结束子
我花了很长时间寻找解决方案 - 我希望它可以帮助其他人
【讨论】:
谢谢!对于我的解决方案,我只是将 MovePrevious/MoveNext 更改为一个消息框,通知用户您需要再次尝试他们的更改。这使它成为一个更好的解决方案。【参考方案3】:我也遇到过类似的问题。
例子:
假设记录有一个字段aForm!text = "Hello"
。
如果用户点击一个按钮,VBA代码在哪里执行
aForm!text = "Hello World!"
当我关闭记录时,我收到错误消息“此记录已更改...”
解决方案:
如果通过aForm.Refresh
和aForm.Requery
刷新表单,可以避免写冲突。
【讨论】:
【参考方案4】:如果这些答案都不起作用,那么试试这个。在您遇到错误的表单中,插入此代码。
Private Sub Form_Deactivate()
DoCmd.RunCommand acCmdSaveRecord
End Sub
基本上,错误是两个表单编辑相同的信息。因此,您必须在离开任一表单后告诉 Access 进行保存。
来源:https://support.microsoft.com/en-ca/kb/304181
【讨论】:
【参考方案5】:我遇到了同样的问题。我在主表单(主表)中通过从属表单(从属表)中的代码更改了字段,并且在关闭表单之前我总是收到警告:“记录已被另一个用户更改......”错误状态: 从属表单中的错误语法(字段更新后的操作)是:
Private Sub Value1_AfterUpdate()
Me.Parent.Controls("Result").Value = 123.52
End Sub
然后在检测到父表单后,另一个“用户”更改了它的字段。
解决方案: 强制主窗体从自身更改值。 使用主表单作为类: 1) 为值定义私有变量,从从属形式改变 2) 在主表单中定义 Public let 并获取属性 - 即“Public Property LetResult(ByVal myVal as double) ...” 3) 在主表单中定义公共过程 Write_Values,它根据私有值设置主表单字段中的值(从公共属性 let ... 获取的值)
4) 在从属表单中定义语法,该语法将值发送给主表单中的 let 属性。 5) 最后从从属窗体调用主窗体中的公共过程Write_Values
示例代码主表单:
Private myResult As Double
Public Property Let letResult(ByVal myval As Double)
myResult = myval
End Property
Public Sub Write_Values()
Me.Result.Value = myResult
DoCmd.RunCommand acCmdSaveRecord
Me.Dirty = False
End Sub
示例代码从属形式:
Private Sub Value1_AfterUpdate()
Me.Parent.letResult = 123.52
Me.Parent.Write_Values
End Sub
【讨论】:
这是我的问题的一个巧妙的解决方案,即从子表单更新表单。【参考方案6】:我遇到了同样的问题,两个不同形式的控件链接到后端链接表中的同一字段。我通过仅将一个控件字段链接到表来解决此问题,当其中一个控件更新时,另一个将信息写入第二个其他控件。
它有效。你可能会问,为什么我需要两种形式的两个控制字段?一个注册数据,另一个在输入所有数据后使用它进行计算。这是为了让用户无法访问进行计算的表单。当然,我可以通过使用一行 VBA 代码注册数据的表单访问计算数据,以供在计算表单中参考。我希望它有所帮助。它对我有用。
【讨论】:
【参考方案7】:我发现解决此问题的方法是重置记录源
Me.RecordSource = ""
cmd.Execute , , adCmdStoredProc
Me.RecordSource = "SELECT SourceFields FROM SomeTable "
但这看起来很老套。
【讨论】:
有效的原因是因为它会在您更改记录源时将编辑保存到绑定表单。如果你只是在调用存储过程之前做了 Me.Dirty = False,你会得到同样的结果。【参考方案8】:当你执行类似这样的存储过程时会发生什么:
db.Execute "<SP_NAME>", dbSeeChanges
【讨论】:
【参考方案9】:检查您尝试更新的表上是否有触发器。如果是这样,请确保它在执行时不会在文本窗口中返回任何内容。
我遇到了同样的问题并且无法解决,直到我在触发器的开头添加了“SET NOCOUNT ON”。
触发器没有在外部更新任何内容,因为它是“AFTER INSERT,DELETE”触发器,但我的问题已经解决了。
【讨论】:
以上是关于在 Access VBA 中禁止写入冲突消息的主要内容,如果未能解决你的问题,请参考以下文章
来自 Access 的 Excel VBA SQL 没有结果
如何避免 Access VBA 中出现“您必须输入值”错误消息
Microsoft Access VBA 中的记录已删除消息