【问题标题】:Preventing close buttons from saving records in MS Access防止关闭按钮在 MS Access 中保存记录
【发布时间】:2018-03-28 19:03:32
【问题描述】:

在 Microsoft Access 表单中,只要当前记录发生更改,绑定控件中的任何更改都会以静默方式保存到数据库表中。这很好,但我不希望在用户关闭表单时发生这种情况,因为这与许多人的预期相反。

最好的例子是,当您尝试关闭未保存更改的 Excel 文件时,它会询问是否应丢弃更改。这正是我试图在 Access 中实现的目标,但在 VBA 中找不到任何方法来捕获关闭按钮的事件。

表单的 Unload 事件是当有人单击关闭按钮时触发的第一个事件,但此时更改已写入数据库。

这完全可能吗,还是我必须创建自己的关闭按钮?我很乐意为此类琐碎的事情编写大量代码,但我讨厌让 GUI 变得混乱。

【问题讨论】:

  • 这可能没有严格的帮助,但这就是为什么未绑定表单非常适合使用的原因。我认为它是这样的:使用绑定表单,您必须防止任何您不想要的更改,而使用 unbound 您只提交您想要的更改,这取决于您喜欢从哪一方来解决问题。但是绑定形式可能很有用,但我真的只在需要连续形式时才使用它们。
  • 以某种方式正是我正在寻找的,但我不想丢失在绑定控件时为我完成的所有代码管道。
  • 遗憾的是,未绑定表单的问题出现了,在设置过程中有更多的代码工作,但最终是一个更容易控制的产品。

标签: vba ms-access-2007


【解决方案1】:

您必须使用Form_BeforeUpdate 事件。下面是一个例子;但是它确实会创建一条典型的警告消息:“此时您无法保存此记录。Microsoft Access 在尝试保存记录时可能遇到错误......” - 取决于您的数据库设置。您可以使用下面的简单解决方法来避免显示该消息。

Private Sub Form_BeforeUpdate(Cancel As Integer)
   Cancel = True
   'Or even better you can check certain fields here (If Then...)

End Sub


Private Sub Form_Error(DataErr As Integer, Response As Integer)
    If DataErr = 2169 Then 
        Response = True
    End If
End Sub

【讨论】:

  • 我忘记了 BeforeUpdate 事件,但它不会在表单的任何关闭事件之前触发吗?
  • 澄清一下,我只想在用户单击表单关闭按钮的情况下取消 = true。
  • 您可以轻松禁用表单上的关闭 (X) 按钮(表单属性)。
  • 我仍然希望允许用户关闭表单,但他们需要以某种方式被告知他们的更改将被保存。如果他们可以在关闭表单之前撤消更改,那就更好了。没有 BeforeUnload 事件真是太烦人了。
【解决方案2】:

肖恩给出了一个几乎正确的答案,但它留下了空白。

一般来说,FORM 的BeforeUpdate 是最重要的表单事件。这是您的最后一道防线,并且无论什么提示保存(表单关闭、新记录、您自己的保存按钮、单击子表单等),始终在保存记录之前运行。虽然我偶尔使用控件的 @987654322 @ 事件只是为了让用户更快地收到错误消息,我编写的大部分验证代码都在 Form_BeforeUpdate 事件中运行。如果要确保某些控件不为空,则必须使用此事件。在所有情况下,没有任何控制级别事件能够可靠地做到这一点。主要是因为如果控件永远不会获得焦点,则不会触发控件级别事件。如果您的验证涉及多个字段,Form_BeforeUpdate 也是您将使用的事件。如果您正在使用任何其他控件或事件级别的事件,那么您就是在浪费时间。你的“陷阱”总是很远,而且你的表几乎肯定包含无效数据。

关于 OP 的问题。如果您想强制人们使用您自己的保存按钮并在他们不使用时提示他们,那么您需要一个表单级别的变量,正如 Sean 的建议所暗示的那样。唯一的区别是您需要在表单的 Current 事件而不是 Open 事件中将其设置为 False。您希望为每条新记录重置标志,而不仅仅是在表单打开时。然后在您的保存按钮单击事件中将其设置为 True,就在您使用 DoCmd.RunCommand acCmdSaveRecord 强制记录保存之前。

最后,在Form_BeforeUpdate 事件中,检查变量的值。

If bClose = False Then
   If MsgBox("Do you want to save the changes?", vbYesNo) = vbNo Then
       Cancel = True
       If MsgBox("Do you want to discard the Changes?", vbYesNo) = vbYes Then           
            Me.Undo
       End If
       Exit Sub
   End If
End If

【讨论】:

  • 更好地格式化你的代码会改善你的答案。
  • 这真的很聪明。太糟糕了,我 3 年前没有想到。
【解决方案3】:

这是我用来检查表单是否被关闭或保存的代码。

Private Sub Form_BeforeUpdate(Cancel As Integer)

If Not UsingSaveButton Then
    If MsgBox("Abandon Data?", vbInformation + vbYesNo) = vbNo Then
        Cancel = True
    Else
        DoCmd.RunCommand acCmdUndo
    End If
End If
End Sub

我有一个布尔标志,在加载时设置为 False,然后当我使用“保存”按钮时,我将其设置为 true 以允许更新运行。
如果未设置标志,那么他们将离开记录(通过转到不同的记录或关闭表单)所以我问他们是否真的要保存更改。
如果进行了任何更改,Cancel = True 将中止退出表单或移动到不同的记录。
DoCmd.RunCommand acCmdUndo 撤消任何更改,因此不会保存它们。

【讨论】:

  • 这听起来很不错。我假设 UsingSaveButton = False 进入 Form_AfterUpdate?
  • 我在保存程序中使用它。将UsingSaveButton=True 放在开头,并在结尾设置为 false(确保任何错误处理也将值设置为 false。在 form load 时将值设置为 false当前事件
【解决方案4】:

实际上,您无法捕捉到这一点,Access 直接在表上工作,当字段通过移动到另一个字段、记录或按钮而失去焦点时,每个更改都已保存。

实际上,与 Excel 相比,这是一个很大的优势

如果您确实想要类似于 Excel 的行为,您需要处理表格的副本和一些用于更新的代码。

【讨论】:

  • 我一直认为绑定的控件实际上链接到表单的 RecordSet 属性的字段。这是一个错误的假设吗?
  • @StevenDotNet,直到执行保存,或执行移动到不同(或新)记录,或关闭表单后才会保存记录。
  • 这类似于您必须调用RecordSet.Update() 以应用更改。除了表单会更新记录集,即使我不想这样做。
【解决方案5】:

在“On Unload”事件的表单中添加以下代码。

DoCmd.RunCommand acCmdUndo
DoCmd.Quit

当用户以任何方式关闭表单时,不再保存记录。

【讨论】:

    【解决方案6】:

    ** 您可以使用此代码使用退出按钮**

    Private Sub Button_Click()
    If Me.Dirty = True Then
       If MsgBox(" Save Change ", vbYesNo) = vbYes Then
          Me.Dirty = False
       Else
          Me.Undo
       End If
    End If
    DoCmd.Close acForm, "FormName"
    End Sub
    

    【讨论】:

    • 我没有否决这个答案,但我猜它被否决了,因为它只是没有描述的代码。
    猜你喜欢
    • 2018-02-01
    • 1970-01-01
    • 2010-09-25
    • 2013-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多