问题
Is there a technique I'm overlooking when coding my form?
I have a pair of cascading combos.
ComboSource filters the options available for choice in ComboInformation
ComboInformation sets the contents of a mandatory field in a table
The rowsource for ComboSource is:
SELECT tblSource.SourceID, tblSource.Source
FROM tblSource
ORDER BY tblSource.Source;
The rowsource for ComboInformation is:
SELECT tblInformation.InformationID, tblInformation.SourceID, tblInformation.InformationSelector
FROM tblInformation
WHERE (((tblInformation.SourceID)=[ComboSource])) OR ((([ComboSource]) Is Null))
ORDER BY tblInformation.InformationSelector;
It is valid to select a value in ComboSource which results in the .Listcount for ComboInformation being zero. The user can choose to type a new value in ComboInformation and be prompted to create the relevant item in the Information table linked to the ComboSource entry in the Source table, or they can choose to navigate back to ComboSource to select a different Source.
The problem arises when a user edits an existing record and changes ComboSource to a value for which there is no associated Information records. In the After_Update event for ComboSource I have the following code, intended to update ComboInformation to reflect the new source and force the user to select a new value for ComboInformation (otherwise they could save the record with the old value of Information without realising it).
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
If the user selects a source for which there are no valid information choices, and then chooses to create a new value for Information, no problem. But if they decide to navigate back to ComboSource instead, they get an error message insisting they complete ComboInformation, which they can't do. They can undo the change they made to get back to the previous state, but that isn't an intuitive response to an error message telling them to complete ComboInformation.
Is there either a way to allow them to navigate back to ComboSource when ComboInformation is invalid or another way to force them to update ComboInformation after updating ComboSource before saving the record that doesn't have this issue?
Update about the error message: I can trap it in Form_Error although the error message isn't generated there -- no other procedures in the stack. The error message is the message associated with the Information field in the Information table (Validation rule: Is Not Null; Validation text; Every piece of evidence must derive from a piece of information)
Further update: I could handle the error (3316) in the Form_OnError but there will be occasions when isn't a 'valid error' that I don't want to ignore...
Other things tried so far:
Refreshing the page doesn't help.
Demonstration database
There's a database to demo the problem at https://s3-eu-west-1.amazonaws.com/genquiry/test.accdb
Open the only form in the database, set the Source to S3 and attempt to navigate back to Source to select a different value.
回答1:
I think my last message kind of hit it. Instead of having the Information combo be bound, set it's Control Source dynamically in the AfterUpdate event of the Source field. You're trying to forcefully fill a bound field with a NULL when there's a "Is Not Null" validation set up in the table design. If you unbind it, you should be able to get it to work.
回答2:
Do you have to clear the second combo box on the after update? I wrote a quick test one and it seems to clear it automatically.
I do not think that the issues is whether or not the combo box is bound, but that you are setting focus to the combobox before you might have items in it or knowing if the user wants to add items to it which could be done before they enter.
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
回答3:
One possibility:
If I set ComboInformation and ComboInformation.DefaultValue to -1 rather than Null when ComboInformation.Listcount = 0, this avoids triggering the table validation rule (Is Not Null) when the user navigates back to ComboSource. However, it is still an invalid value (as it breaks data integrity between tables) and the user is prevented from exiting the form or saving the record until a valid value is entered (by choosing a different value for Source or creating a value in the Information list).
It works, but it isn't an elegant solution and depends on -1 always being an invalid value for the Automatically-generated InformationID field in the linked Information table, which I don't believe is a safe assumption...
However, if I modify the method slightly to find the lowest existing InformationID field (call this LOWID) and then use LOWID-1 to set ComboInformation, that also works, and always produces an invalid value for the period it is in use.
来源:https://stackoverflow.com/questions/18377452/how-to-force-the-update-of-an-access-combobox