How to: Show a note after an action, with Undo
Tell users that an action worked (“Rule deleted”) in a short note at the lower right of the Access window, with an Undo they can reach with the mouse, the keyboard, or a screen reader, without a message box that has to be closed and without moving the focus.
Requires WKL Forms Object Library 1.34 or later.
Solution overview
WklToastis an object, not a control. Create it withNewin the module that performs the action; no form needs a control, and a subform can show notes too.Showdisplays a note: the text, the kind (wtkSuccess,wtkWarning, and so on), an optional title, the caption of the action, and aTagthat comes back with it (for example, the key of the deleted record). The note closes on its own after 4 seconds, or after 8 seconds if it has an action.- The action: declare the object
WithEventsat the module level of the form and handleAction(Id, Tag). Or name a function inActionFunction(=RestoreRule(17)), as for theOnActionproperty of an Access menu entry: it runs even when the module no longer listens. - Keyboard: Ctrl+Shift+Z runs the action of the newest note; F6 moves into the note, Esc closes it, and F6 returns. Without a visible note, nothing changes.
Implementation
The table for the example, created once (run the procedure from the Immediate window):
Public Sub CreateNoteSample()
With CurrentDb
.Execute "CREATE TABLE tblRules (ID LONG CONSTRAINT PK_Rules PRIMARY KEY, Name TEXT(50), IsDeleted YESNO)"
.Execute "INSERT INTO tblRules VALUES (1, 'Reminder after 30 days', False)"
.Execute "INSERT INTO tblRules VALUES (2, 'Discount from $1,000', False)"
End With
End Sub
A continuous form frmRules over SELECT * FROM tblRules WHERE Not IsDeleted, with the text
box Name and the button cmdDelete; deleting only marks the record (IsDeleted), so Undo
can bring it back:
Option Compare Database
Option Explicit
Private WithEvents mToast As WklToast
Private Sub Form_Load()
Set mToast = New WklToast
End Sub
Private Sub cmdDelete_Click()
Dim id As Long
Dim ruleName As String
If IsNull(Me!ID) Then Exit Sub
id = Me!ID
ruleName = Nz(Me!Name, "") ' read before Requery: afterwards the form is on another record
CurrentDb.Execute "UPDATE tblRules SET IsDeleted = True WHERE ID = " & id, dbFailOnError
Me.Requery
mToast.Show "Rule """ & ruleName & """ deleted.", wtkSuccess, , "Undo", id
End Sub
Private Sub mToast_Action(ByVal Id As Long, ByVal Tag As Variant)
CurrentDb.Execute "UPDATE tblRules SET IsDeleted = False WHERE ID = " & Tag, dbFailOnError
Me.Requery
End Sub
The same without an event procedure, from a standard module, with a function that performs the undo:
Public Sub DeleteRule(ByVal id As Long)
Dim note As New WklToast
CurrentDb.Execute "UPDATE tblRules SET IsDeleted = True WHERE ID = " & id, dbFailOnError
note.Show "Rule deleted.", wtkSuccess, , "Undo", , , , "=RestoreRule(" & id & ")"
End Sub
Public Function RestoreRule(ByVal id As Long) As Boolean
CurrentDb.Execute "UPDATE tblRules SET IsDeleted = False WHERE ID = " & id, dbFailOnError
If CurrentProject.AllForms("frmRules").IsLoaded Then Forms!frmRules.Requery
RestoreRule = True
End Function
A message after saving, in the corner of the form instead of the Access window:
Private Sub Form_AfterUpdate()
mToast.Show "Saved.", wtkSuccess, , , , 2000, Me
End Sub
Remarks
- A local variable can't be declared
WithEvents, so the events of a note shown by a local object go nowhere. UseActionFunctionthere, or keep the object at the module level. - The note holds a copy of
Tag. Pass the key, not a recordset or a form: the note might outlive them. - Notes shown with
Formclose when that form closes (ClosedwithwtrOwnerClosed); notes in the Access window stay until their time is up, even when the form that showed them closes. Count,Close, andCloseAllwork on all notes in the Access session, whichever object showed them; useCloseAllbefore a long operation that should start with an empty corner.- At most three notes are visible at a time; further ones wait. Don't show a note for each record in a loop; show one note with the number (“12 rules deleted”).
- Errors and decisions that need an answer belong in a message box or a dialog, not in a note: a note disappears.
Related topics
- API reference: WklToast: members, events, kinds, and close reasons.
- API reference: WklDockLayout: F6 between areas, which a visible note joins as the first stop.