|[ Team LiB ]|
Recipe 10.4 Send Messages to Other Users Without Using Email
When you have multiple users logged into your application, you want them to be able to communicate quickly and easily with one another. You need a simple interface for sending notes back and forth so users can check whether anyone else is editing a particular entry, compare notes on workflow, and so on. How can you implement this in Access?
You can keep your notes in a table in a shared database to which all users have access. Whenever someone writes a note to another user, that note is added as another record in this table. By using a form that makes use of the Timer event, you can monitor the status of this table from any Access application and notify users when new messages have arrived.
This solution employs two files, 10-04fe.MDB and 10-04be.MDB. Before you can try it, you'll need to link the data tables from 10-04be.MDB (the "backend" or data database) to 10-04fe.MDB (the "frontend" or application database). Linking a data table allows you to use a table from one Access database within another Access database. Start Access and load 10-04fe.MDB. Choose File Get External Data Link Tables, and select 10-04be.MDB as the Access link database. At the Link Tables dialog, select tblMessage and click OK, as shown in Figure 10-16.
Now you can test-drive this solution by sending a message to yourself. Open both frmSendMail and frmReceiveMail. Minimize the Receive Mail form. Select your username from the To combo box. If you haven't altered the default Access security settings, your username will be Admin, which should be confirmed in the From text box. Enter any message and click the Send Message button. In Figure 10-17, Peter has used frmSendMail to compose a message to Jean.
The Send Mail form will clear as soon as the message is sent. Within 10 seconds, the Receive Mail form will pop up with the message. Figure 10-18 shows how Jean would see the message from Peter. Click on the Mark as Read button to clear the Receive Mail form. If more than one message is waiting, you can navigate through them.
To use this technique in your own applications, follow these steps:
This technique works by passing messages back and forth through tblMessage. The sending form is unbound, because when you send a message, you don't want to have to flip through all the previous messages. The acbSendMail function just takes whatever you type into the form and puts it into this table. It also uses the CurrentUser function to put your name into the From field of the table, and the Now function to time-stamp the message. The acbSendMail function is shown here:
Public Function acbSendMail( ) As Integer ' Take the message and user from the ' frmMailSend form and send it to the mail ' backend On Error GoTo HandleErr Dim db As DAO.Database Dim rstMail As DAO.Recordset Dim frmMail As Form Set db = CurrentDb( ) Set rstMail = db.OpenRecordset( _ "tblMessage", dbOpenDynaset, dbAppendOnly) Set frmMail = Forms("frmSendMail") rstMail.AddNew rstMail("From") = CurrentUser( ) rstMail("To") = frmMail.cboTo rstMail("DateSent") = Now rstMail("Message") = frmMail.txtMessage rstMail.Update frmMail.cboTo = Null frmMail.txtMessage = Null ExitHere: On Error Resume Next rstMail.Close Err.Clear Exit Function HandleErr: MsgBox Err & ": " & Err.Description, , "acbSendMail( )" Resume ExitHere End Function
Opening the recordset with the dbAppendOnly flag accelerates the process of adding a new record because it avoids reading in the existing records that the send function doesn't care about.
The cboTo combo box uses a list-filling function to fill the combo box with a list of current users in the workgroup. List-filling functions were discussed in the Solution in Recipe 7.5. This particular function fills its list using security data access objects to iterate through the collection of users in the workgroup. We defer discussion of this topic to the Solution in Recipe 10.5.
The Receive Mail form is based on a query that finds all messages directed to the current user that have nothing in their DateReceived fields. By default, new records added from elsewhere on a network do not show up on an already-opened form; you must explicitly requery the form for this to happen. The acbCheckMail function automatically performs this requery at load time and once every 10 seconds to check for new mail. The acbCheckMail function is shown here:
Function acbCheckMail( ) As Integer ' Check for new mail, and if there is any, ' restore the received mail form On Error GoTo HandleErr Dim rstClone As DAO.Recordset Dim frmMail As Form Set frmMail = Forms("frmReceiveMail") frmMail.Requery Set rstClone = frmMail.RecordsetClone If Not rstClone.EOF Then rstClone.MoveFirst frmMail.Caption = "New Mail!" If IsIconic(frmMail.Hwnd) Then frmMail.SetFocus DoCmd.Restore End If Else frmMail.Caption = "No mail" End If ExitHere: Exit Function HandleErr: Select Case Err.Number Case 3021 ' no current record, do nothing Case Else MsgBox Err & ": " & Err.Description, , "acbCheckMail( )" End Select Resume ExitHere End Function
After the form is requeried, acbCheckMail checks for new mail by looking at the RecordsetClone property of the form. This property returns an exact duplicate of the form's underlying recordset. If there are any records to be shown, this RecordsetClone will not be at its EOF, so the function changes the form's caption and, if it is currently minimized, restores the form to its full size. The function calls the Windows API function IsIconic (declared in the declarations section of basMail) to determine if the form is minimized.
We have used the form's Picture property, a rectangle, and the form's AllowAdditions property to add one more effect to the form: when the form's recordset is empty, all the controls on the form disappear and a bitmap reading "There are no new mail messages" appears on the form (see Figure 10-19).
This trick is accomplished by setting the form's AllowAdditions property to No, adding a watermark picture to the form, and adding an opaque rectangle that hides the watermark when there are records in the form's recordset. When there are no records in a form's recordset and you have set AllowAdditions to No, Access hides all of the form's controls—including the unbound Rectangle control—and prominently displays the form's watermark, if there is one.
This method uses the Access username to track mail senders and recipients. To use it in production, you'll need to activate Access security (otherwise, everyone is signed on as the Admin user at all times). To activate security, simply use Security Change Password to assign a password to the Admin user. Then you can select Users from the Security menu and create as many new users as you like. Security was discussed in more detail in the Solution in Recipe 10.1.
To test this solution with multiple users, you'll need to have several machines available on a network. Make a copy of 10-04fe.MDB for each computer, and use File Get External Data Link Tables to link the same copy of tblMessage to each one. Log in as a different user at each computer, and you'll be able to send messages back and forth.
You can adjust the performance impact of this technique by changing the TimerInterval property of frmReceiveMail. This property measures the number of milliseconds between each execution of the OnTimer event. In the sample database, the TimerInterval property is set to 10000 milliseconds, or 10 seconds; its highest possible value is 65535, or just over a minute. If you want a longer delay, you can add a static integer variable to acbCheckMail and increment it more than once before you check for new mail.
10.4.4 See Also
|[ Team LiB ]|