DataWright Information Services

Consulting and Resources for Excel and Access

Finding out who is using your database

If you have multiple users in your database, you often need to know who is in the database when it comes time to do some maintenance. If you have set up user-level security, it's possible to get that information with the Jet User Roster, which reads the contents of the .ldb locking file for the database. However, if you are not using user-level security, you can only retrieve the machine name.

This method is an alternative that will allow you to log your users by their Windows login, see who is currently in the database, and keep a record of when users were using your system. The system consists of one table, two simple forms, and a module with two custom functions.

How it works

A hidden form called frmMonitor is opened in the background when the database launches. At this stage it triggers a custom function, LogOn(), which creates a new record in tblUserLog, recording the user's Windows login name and the current date and time. When the user closes the database, frmMonitor triggers LogOff() which writes the current time to the LogOff field in tblUserLog.

To see who is in the database, we use a form with a listbox that displays all log records with a blank LogOff field. Another button on the form lets you see the full history, sorted descending by login date/time.

  • You can download a sample database here (17,616 bytes)

The components

tblUserLog

This table goes in the back end database of your split system. It has four fields, as shown below:

Field Data Type Comments
UserLogID Autonumber Primary Key
UserID Text User's Windows login name
LogOn Date/Time Login timestamp; default value is =Now()
LogOff Date/Time Logout timestamp

modUserLog

This module holds the two custom functions that write the log table values. Both functions use Environ("username") to find the Windows login of the current user. They also use DoCmd.SetWarnings to suppress the dialog that "you are about to append / change / delete xxx records", and to reset those warnings once the operation is complete. The code for these functions is shown below:

Function LogOn()
  Dim sUser As String
  Dim sSQL As String

  DoCmd.SetWarnings False
  sUser = Environ("username")
  sSQL = "INSERT INTO tblUserLog ( UserID )" _
    & "SELECT '" & sUser & "' AS [User];"
  DoCmd.RunSQL sSQL
  DoCmd.SetWarnings True
End Function

The SQL statement in LogOn() is an Append query. It writes the Windows login to the UserID field; because that login value is also the result of a function, it is given the alias [User] so that Access can treat it like a field.

The DoCmd.RunSQL command runs the query, creating the new log record.

Function LogOff()
  Dim sUser As String
  Dim sSQL As String

  DoCmd.SetWarnings False
  sUser = Environ("username")
  sSQL = "UPDATE tblUserLog SET tblUserLog.LogOff = Now() " _
    & "WHERE tblUserLog.UserID='" & sUser & "' AND tblUserLog.LogOff Is Null;"
  DoCmd.RunSQL sSQL
  DoCmd.SetWarnings True
End Function

In this case, sSQL is an Update query. The WHERE clause filters the log to the correct record by using the Windows login name and selecting null LogOff fields.

frmMonitor

frmMonitor is opened when the database opens, and stays in the background until the database closes. It contains two very simple event procedures:

Private Sub Form_Load()
  modUserLog.LogOn
End Sub

Private Sub Form_Unload(Cancel As Integer)
  modUserLog.LogOff
End Sub

Form_Load is triggered at database launch time, and runs the LogOn() function. Form_Unload is triggered when the database (and the form) is closed, and it runs the LogOff() function.

frmUserLog

The above three components are needed to write and store the log data. To view it, frmUserLog has a listbox and two command buttons to toggle between currently logged in users and all log records. A third button closes the form. the user log form

The listbox has the following properties set:

Property Value / Setting
Column Count 3
Column Widths 3cm;3.85cm;3.85cm
Width 10.7cm
Column Heads Yes
Row Source SELECT tblUserLog.UserID, tblUserLog.LogOn, tblUserLog.LogOff
FROM tblUserLog
WHERE (((tblUserLog.LogOff) Is Null))
ORDER BY tblUserLog.LogOn DESC;

The code for the form is listed below.

Option Compare Database
Option Explicit
Const sSELECT = "SELECT tblUserLog.UserID, tblUserLog.LogOn, tblUserLog.LogOff " _
  & "FROM tblUserLog "
Const sWHERE = "WHERE (((tblUserLog.LogOff) Is Null)) "
Const sORDER = "ORDER BY tblUserLog.LogOn DESC;"
Dim sSQL As String

Private Sub cmdAll_Click()
  sSQL = sSELECT & sORDER
  With Me.lstUsers
    .RowSource = sSQL
    .Requery
  End With
  Me.lblUsers.Caption = "Full Log"
End Sub

Private Sub cmdClose_Click()
  DoCmd.Close acForm, Me.Name
End Sub

Private Sub cmdCurrent_Click()
  sSQL = sSELECT & sWHERE & sORDER
  With Me.lstUsers
    .RowSource = sSQL
    .Requery
  End With
  Me.lblUsers.Caption = "Currently Logged On"
End Sub

By default, the form will display users who are currently logged on. The All button will display all user logins, so that you can see the history, and the Current button will switch back again. In addition, each button rewrites the caption for the listbox to give user feedback.

The code is modular. The SQL statement has been split up into three components, and placed in the Declarations section of the module as the constants sSELECT, sWHERE and sORDER.

To display all users, the Rowsource of the listbox is changed to sSELECT & sORDER. To show only current users, sWHERE is inserted into the listbox SQL. The Requery command refreshes the listbox display.

Using the system

To use this in your setup, do the following:

  • Import the table, forms and module into your database.
  • Create a command button that launches frmUserLog. If you want all users to be able to use this feature, place the button / launch command on the main menu. You can place this on a form that only administrators can get to, if you need to restrict access to this view.