如何强制更新 Access 组合框?
Posted
技术标签:
【中文标题】如何强制更新 Access 组合框?【英文标题】:How to force the update of an Access combobox? 【发布时间】:2013-08-22 10:06:56 【问题描述】:在编写表单时,我是否忽略了一项技术?
我有一对级联组合。
ComboSource 过滤 ComboInformation 中可供选择的选项
ComboInformation 设置表格中必填字段的内容
ComboSource 的行源是:
SELECT tblSource.SourceID, tblSource.Source
FROM tblSource
ORDER BY tblSource.Source;
ComboInformation 的行源是:
SELECT tblInformation.InformationID, tblInformation.SourceID, tblInformation.InformationSelector
FROM tblInformation
WHERE (((tblInformation.SourceID)=[ComboSource])) OR ((([ComboSource]) Is Null))
ORDER BY tblInformation.InformationSelector;
在 ComboSource 中选择一个导致 ComboInformation 的 .Listcount 为零的值是有效的。用户可以选择在 ComboInformation 中键入一个新值,并提示在信息表中创建与 Source 表中的 ComboSource 条目链接的相关项,或者他们可以选择导航回 ComboSource 以选择不同的 Source。
当用户编辑现有记录并将 ComboSource 更改为没有关联信息记录的值时,就会出现问题。在 ComboSource 的 After_Update 事件中,我有以下代码,旨在更新 ComboInformation 以反映新源并强制用户为 ComboInformation 选择新值(否则他们可能会在没有意识到的情况下将记录保存为 Information 的旧值)。
Me.ComboInformation.Requery 'Reflect the current source
'Set a default value for ComboInformation
If Me.ComboInformation.ListCount > 0 Then
Me.ComboInformation.DefaultValue = Me.InformationTitle.ItemData(0)
Else
On Error Resume Next 'Ignore inevitable error
Me.ComboInformation.DefaultValue = Null
On Error GoTo PROC_ERR 'restore normal error handling
End If
'Force the user to update Information by setting content to "" -- if this isn't done, the
'record can be saved with the 'previous value of Information and the user may not realise
'they haven't made any change
ComboInformation.SetFocus
If Not Me.NewRecord Then
If Me.ComboInformation.ListCount = 0 Then
'Clear info to force it to be updated
On Error Resume Next 'Ignore inevitable error
ComboInformation.Text = "" 'Set it to an invalid value
ComboInformation= Null
On Error GoTo PROC_ERR
Else
ComboInformation= ComboInformation.DefaultValue 'set it to a valid value
End If
End If
End If
如果用户选择了一个没有有效信息选择的来源,然后选择为 Information 创建一个新值,没问题。但是,如果他们决定改为导航回 ComboSource,则会收到一条错误消息,要求他们完成 ComboInformation,而这是他们无法做到的。他们可以撤消所做的更改以返回到以前的状态,但这并不是对告诉他们完成 ComboInformation 的错误消息的直观响应。
是否有办法让他们在 ComboInformation 无效时导航回 ComboSource,或者在保存不存在此问题的记录之前强制他们在更新 ComboSource 后更新 ComboInformation?
关于错误消息的更新:我可以在 Form_Error 中捕获它,尽管错误消息不是在那里生成的——堆栈中没有其他过程。错误消息是与Information表中Information字段相关的消息(验证规则:不为空;验证文本;每条证据都必须来自一条信息)
进一步更新:我可以处理 Form_OnError 中的错误 (3316),但有时不是我不想忽略的“有效错误”...
到目前为止尝试的其他事情:
刷新页面没有帮助。
演示数据库
https://s3-eu-west-1.amazonaws.com/genquiry/test.accdb有一个数据库来演示这个问题
打开数据库中唯一的表单,将 Source 设置为 S3 并尝试导航回 Source 以选择不同的值。
【问题讨论】:
您是否尝试过刷新页面?这是我的第一个想法;当你这样做时会发生什么?我会再考虑一下。 当您因错误进入调试模式时(按住“Ctrl”按钮并按下“Pause/Break”按钮),突出显示哪一行? 任何时候代码停止,即使它是一个消息框,Ctrl-Pause-Break 应该可以工作。或者,您可以在 VBA 代码中添加一个断点,然后单步执行,直到出现错误。 教用户按 Escape 一次(字段级别)或两次(记录级别)怎么样?或者你不能使用 Me.Undo 吗?或者(不好,我知道)SendKeys Escape(s) 加载主表单时,会弹出一个消息框,上面写着“RTFM!” :o) 这是一个奇怪的。我必须在测试数据库中构建表格,看看我是否可以提供更多帮助,我今天工作有点忙,所以我现在做不到。如果我发现了什么,我会告诉你的。 【参考方案1】:我认为我的最后一条消息有点命中。与其绑定 Information 组合,不如在 Source 字段的 AfterUpdate 事件中动态设置它的 Control Source。当表设计中设置了“非空”验证时,您正试图用 NULL 强制填充绑定字段。如果你解绑它,你应该可以让它工作。
【讨论】:
看看这个,特别是让用户从第二个组合框中选择任何项目部分:datawright.com.au/access_resources/access_combo_boxes.htm。我认为您想设置行源而不是记录源,这将使第二个组合未绑定。 我认为这与我已经设置 Row Source 的方式类似:SELECT qryInformation.InformationID, qryInformation.SourceID, qryInformation.InformationSelector FROM qryInformation WHERE (((qryInformation.SourceID)=[Source])) OR ((([Source]) Is Null)) ORDER BY qryInformation.InformationSelector;
但是,Source 在我的应用程序中永远不会为 Null,因为未经过滤的信息值列表对于用户选择来说是无可救药的长来自。
我的错,这就是我的意思。 :o) ControlSource 将组合绑定到字段,RowSource 不应该。因为您想让他们在必要时添加一个新值,所以您必须在第二个组合的 AfterUpdate 事件中放置一些代码以查看数据是否存在,如果不存在则将其添加到表中。您可以在此处控制是否尝试保存 NULL 值。
查看项目是否存在并在必要时创建它的代码已经在组合的 Not In List 事件中(我从示例数据库中删除了它,因为它是一组类模块的一部分这增加了演示问题所不需要的复杂性)。但这对于用户选择错误源、不想创建新信息但想要导航回源以选择其他信息的用例没有帮助。在这种情况下,永远不会触发第二个组合的 after_update 事件。
问题是,如果不绑定,它怎么能抱怨呢?这就是为什么绝对必须是第二个组合需要解除绑定。然后,如果您返回并更改第一个组合,它只会刷新第二个组合框中的可用项目。它不会尝试写入表格,组合中的项目是完全独立的。现在,它正试图在第二个组合失去焦点后立即返回并在表中添加一个新值,因为它已绑定到该信息字段。【参考方案2】:
更新后是否必须清除第二个组合框?我写了一个快速测试,它似乎会自动清除它。
我认为问题不在于组合框是否已绑定,而是您在组合框可能包含项目之前将焦点设置为组合框,或者知道用户是否想要向其中添加项目,这可能是在他们进入之前完成。
Private Sub cboSource.AfterUpdate()
cboInformation.Requery
' if the combobox doesn't refresh to be empty or have a default after the
' requery check the row source for information.
' This way you don't have to focus the second combo box and run into problems
' when you leave it
Dim db as DAO.database
Dim rs as DAO.recordset
Set db = CurrentDB()
Set rs = db.OpenRecordset("SELECT tblInformation.InformationID,
tblInformation.SourceID, tblInformation.InformationSelector
FROM tblInformation
WHERE (((tblInformation.SourceID)= " & ComboSource.value & "))
OR (((" & ComboSource.value & " ) Is Null))
ORDER BY tblInformation.InformationSelector")
If rs.recordcount <> 0 then
cboInformation.SetFocus
Else
' Set and empty value for the combobox so they can't accidentally save the
' record with an old value.
' Prompt them to either select a new value that has records or create a
' new one here
End If
rs.close
db.close
Set rs = nothing
Set db = nothing
end Sub
【讨论】:
这种方法是可行的(在导航到空组合之前提示确认)。我可能只是测试 .Listcount 来测试组合是否为空。【参考方案3】:一种可能性:
如果我在 ComboInformation.Listcount = 0 时将 ComboInformation 和 ComboInformation.DefaultValue 设置为 -1 而不是 Null,这可以避免在用户导航回 ComboSource 时触发表验证规则(不是 Null)。但是,它仍然是一个无效值(因为它破坏了表之间的数据完整性),并且在输入有效值之前,用户无法退出表单或保存记录(通过为 Source 选择不同的值或在信息列表)。
它有效,但它不是一个优雅的解决方案,并且依赖于 -1 始终是链接信息表中自动生成的 InformationID 字段的无效值,我不认为这是一个安全的假设......
但是,如果我稍微修改该方法以找到最低的现有 InformationID 字段(称为此 LOWID),然后使用 LOWID-1 设置 ComboInformation,这也有效,并且始终会在使用期间产生无效值.
【讨论】:
以上是关于如何强制更新 Access 组合框?的主要内容,如果未能解决你的问题,请参考以下文章