Learn Microsoft Access Advanced Programming Techniques, Tips and Tricks.

Progress Meter

Introduction.

When processing large volumes of data for Microsoft Access reports, the operation can take anywhere from a few seconds to several minutes, depending on the volume and complexity of the transactions involved. These transactions are typically organized and executed using a combination of Select and Action Queries, orchestrated through Macros or VBA routines to produce the final report output.

If your Action Queries depend on SELECT or CROSSTAB Queries as input sources—particularly when dealing with high transaction volumes—the overall processing time can increase significantly.

In such cases, users may find it difficult to estimate how long the task will take to complete. Over time, with repeated use, they may develop a rough idea of the expected duration.

A common practice is to display the hourglass cursor (DoCmd.Hourglass True) at the beginning of a long-running operation to signal that processing is underway. The hourglass is then reset at the end of the task. However, this visual cue does not provide users with a clear indication of progress or how much time remains until completion.

If the process takes longer than usual—due to factors such as increased transaction volume, heavy network traffic, or other system-related delays—it becomes difficult to determine whether the operation is still actively running or if the system has encountered a hang or failure.

The Quick Solution.

When multiple Action Queries are executed in sequence within a Macro, Microsoft Access briefly displays a Progress Meter on the Status Bar for each query. If the Status Bar is not visible, you can enable it by selecting Options from the Tools menu, navigating to the View tab in the dialog box, and checking the Status Bar option under the Show group. However, this only provides momentary feedback for individual queries and does not indicate the overall progress or estimated time remaining for the entire process.

A Better Approach.

We will explore how to make more effective use of the Progress Meter during data processing tasks by implementing multiple methods. This will allow users of our application to stay informed about the progress, giving them the confidence to momentarily step away or flip through a weekly magazine, while occasionally glancing at the screen to monitor the process.

  1. Displaying the Progress Meter on the Status Bar
  2. Displaying the Progress Meter on a Form
  3. Usage of a transaction countdown method.

Usage of Progress Meter on the Status Bar.

We will use the Order Details table from the Northwind.mdb sample database to demonstrate our example. Our objective is to write a VBA routine that calculates the Extended Price for each entry in this table. If you haven’t already imported the table while working through previous examples, you may do so now. If you're unsure about the exact location of the Northwind.mdb file on your machine, refer to the page Saving Data on Forms Not in Table for guidance.

Steps:

  1. Import the Order Details table from the Northwind.mdb sample database into your project.

  2. Open the table in Design View, and add a new field  ExtendedPrice at the end of the existing fields.

    • Data Type: Number

    • Field Size: Double

  3. Design a simple form with a Command Button on it, similar to the sample shown below. We’ll use and enhance this form for the next example as well.

  4. Assigning the Procedure to the Command Button.

    1. Click on the Command Button to select it.

    2. Open the Property Sheet (choose ViewProperties if it’s not already visible).

    3. Locate the On Click property.

    4. Enter the following expression in the On Click property:

      =ProcessOrders()

      Note: Make sure to include the equal sign (=) at the beginning. Without it, MS Access will interpret the value as the name of a macro instead of a function call.

    5. Close the form and save it with the name: ProgressMeter.

    Usage of SysCmd().
  5. Copy and paste the following Code into a Global VB Module of your Project and save it.
    Public Function ProcessOrders()
    Dim db As Database, rst As Recordset
    Dim TotalRecords As Long, xtimer As Date
    Dim ExtendedValue As Double, Quantity As Integer
    Dim Discount As Double, x As Variant, UnitRate As Double
    
    On Error GoTo ProcessOrders_Err
    
    DoCmd.Hourglass True
    
    Set db = CurrentDb
    Set rst = db.OpenRecordset("Order Details", dbOpenDynaset)
    rst.MoveLast
    TotalRecords = rst.RecordCount
    
    rst.MoveFirst
    Do While Not rst.EOF
      With rst
        Quantity = ![Quantity]
        UnitRate = ![UnitPrice]
        Discount = ![Discount]
        ExtendedValue = Quantity * (UnitRate * (1 - Discount))
    
        .Edit
        ![ExtendedPrice] = ExtendedValue
        .Update
    
        If .AbsolutePosition + 1 = 1 Then
           x = SysCmd(acSysCmdInitMeter, "process:", TotalRecords)
        Else
          'a delay loop to slow down the program       
          'to view the Progress Meter in action.      
          'you may remove it.      
    '=================================================
          xtimer = Timer
          Do While Timer < xtimer + 0.02
            Doevents
          Loop
    '=================================================
    
          x = SysCmd(acSysCmdUpdateMeter, .AbsolutePosition + 1)
        End If
    
       .MoveNext
      End with
    Loop
    rst.Close
    x = SysCmd(acSysCmdRemoveMeter)
    DoCmd.Hourglass False
    
    MsgBox "Process completed.", , "ProcessOrders()"
    
    Set rst = Nothing
    Set db = Nothing
    
    ProcessOrders_Exit:
    Exit Function
    
    ProcessOrders_Err:
    MsgBox Err.Description, , "ProcessOrders()"
    Resume ProcessOrders_Exit
    
    End Function
  6. Open the ProgressMeter form in Form View and click the Command Button. You will see the Progress Meter gradually advancing across the status bar. Once it reaches the end, a message will appear indicating that the task has been completed successfully.

We have used Microsoft Access's built-in Function SysCmd() to control and display the Progress Meter on the Status Bar. When the function is first invoked, it is passed the total number of records in the table as the third parameter, which initializes the Progress Meter. Subsequent calls to the function supply the current record number, allowing Access to calculate the percentage of records processed and update the meter accordingly.

The blue indicator on the Progress Meter advances in proportion to the percentage of completion. For large datasets, this means the bar may not visibly move with every single record processed, but instead updates after processing a batch, based on the overall total.

A delay loop has been added to the code for demonstration purposes, allowing users to observe the Progress Meter in action. You may remove these lines when incorporating the routine into your actual project for better performance.

Need a Better Method.

We cannot use this method when sequencing process steps through Macros involving Action Queries. This is because, during execution, Microsoft Access automatically updates the Status Bar to display the progress of each individual query, which overrides and interferes with our custom Progress Meter based on SysCmd().

To overcome this limitation, we must devise an alternative method to track the overall progress of the entire process.

In the next section, we will explore how to use a custom Progress Meter on a Form to visually track the progress of data processing steps executed through a Macro.

Download.


Download Access2007 Version



Download Access2003 Version

Share:

Keyboard Shortcuts

Introduction.

Keyboard Shortcuts can significantly enhance productivity when practiced and memorized. They allow you to perform frequently used actions quickly, without constantly switching between the mouse and keyboard. Microsoft Access offers an extensive set of keyboard shortcuts that make working with the application more efficient. You can find a categorized list by searching for “Keyboard Shortcuts” in the Help menu. For your convenience, I have selected and listed some of the most useful shortcuts at the end of this post.

If you observe the Microsoft Access menu items closely, you’ll notice that one letter in each menu name is underlined. This indicates a keyboard shortcut key for that menu.

For example, the letter E in the Edit menu is underlined, meaning you can open the Edit menu by pressing ALT + E. Similarly, many options within each menu display their own shortcut keys on the right-hand side—these are predefined system shortcuts designed to improve efficiency and ease of use.

Defining Custom Shortcuts

When designing Forms in Microsoft Access, you can define your own custom keyboard shortcuts—also known as Access Keys—for form controls using the & (ampersand) symbol. By placing the & symbol before a character in the Caption property of a Command Button or Label, you enable the user to press ALT + that character to trigger the associated control.

For example, if you have a command button labeled Export, setting its Caption  &Export allows the user to press ALT + E to run the button’s action. However, you should avoid using characters already reserved for built-in shortcuts, such as ALT + E, which is assigned to the Edit menu.

To prevent conflicts, you can place the & before a different letter in the word, for instance, use Ex&port to assign ALT + P as the shortcut.

In addition to this method, you can define global keyboard shortcuts using a special macro named AutoKeys. This macro allows you to bind specific keystroke combinations to actions such as:

  • Opening a specific form in design or normal view,

  • Running a macro to process report data,

  • Or initiating a Print Preview.

An example of the AutoKeys macro layout is shown below.

In the AutoKeys macro, each line maps a key combination to a specific action. For example:

  • The line ^O (where ^ represents the CTRL key) triggers the OpenReport action when CTRL+O is pressed.

  • Similarly, CTRL+K runs another macro assigned to the ^K key combination.

Note: If you assign an action to a key combination that is already used by a built-in Access shortcut (such as CTRL+C for Copy), your custom action will override the default behavior.

AutoKeys.

A list of key combinations that you can use in your Autokeys Macro is given below.

Key Codes for Autokey Macro
Key Code Key Press
^A or ^4 CTRL+A or CTRL+4
{F1} F1
^{F1} CTRL+F1
+{F1} SHIFT+F1
{INSERT} INS
^{INSERT} CTRL+INS
+{INSERT} SHIFT+INS
{DELETE} or {DEL} DEL
^{DELETE} or ^{DEL} CTRL+DEL
+{DELETE} or +{DEL} SHIFT+DEL

A macro with the name Autoexec runs automatically when you open a database.

General Purpose Keyboard Shortcuts

A list of useful general-purpose Keyboard Shortcuts is given below for your reference.

Seq Key Strokes Action
SAVING AND PRINTING
1. CTRL+S or SHIFT+F12 or ALT+SHIFT+F2 To save a Database Object
2. F12 or ALT+F2 To open the Save As... dialog box
3. CTRL+P To Print the Current or Selected Object
FINDING REPLACING
4. CTRL+F To open the Find tab in the Find and Replace dialog box (Datasheet view and Form view only
5. CTRL+H To open the Replace tab in the Find and Replace dialog box (Datasheet view and Form view only)
6. SHIFT+F4 To find the next occurrence of the text specified in the Find and Replace dialog box when the dialog box is closed (Datasheet view and Form view only)
WORKING IN DESIGN VIEW
7. F2 To switch between Edit mode (with insertion point displayed) and Navigation mode
8. F4 To switch to the property sheet (Design view in forms and reports in databases and Access projects)
9. F5 To switch to Form view from the Form Design view
10. F6 To switch between the upper and lower portions of a window (Design view of tables, macros, and queries, and the Advanced Filter/Sort window only)
11. SHIFT+F7 To switch from the Visual Basic Editor to form or report Design view
12. ALT+V+P To open the property sheet for a selected object
Editing Controls in Form and Report Design View
13. CTRL+C To copy the selected control to the Clipboard
14. CTRL+X To cut the selected control and copy it to the Clipboard
15. CTRL+V To paste the contents of the Clipboard in the upper-left corner of the selected section
16. CTRL+RIGHT ARROW To move the selected control to the right
17. CTRL+LEFT ARROW To move the selected control to the left
18. CTRL+DOWN ARROW To move the selected control down
19. SHIFT+DOWN ARROW To increase the height of the selected control
20. SHIFT+RIGHT ARROW To increase the width of the selected control
21. SHIFT+UP ARROW To reduce the height of the selected control
22. SHIFT+LEFT ARROW To reduce the width of the selected control
WINDOW OPERATIONS
23. F11 To bring the Database window to the front
24. CTRL+F6 To cycle between open windows
25. ENTER To restore the selected minimized window when all windows are minimized
26. CTRL+F8 To turn on Resize mode for the active window when it's not maximized, press the arrow keys to resize the window
27. ALT+SPACEBAR To display the Control menu
28. SHIFT+F10 To display the shortcut menu
29. CTRL+W or CTRL+F4 To close the active window
30. ALT+F11 To switch between the Visual Basic Editor and the previous active window
MISCELLANEOUS
31. F7 To check to spelling
32. SHIFT+F2 To open the Zoom box to conveniently enter expressions and other text in small input areas
33. ALT+ENTER To display a property sheet in the Design view
34. ALT+F4 To quit Microsoft Access, close a dialog box, or close a property sheet
35. CTRL+F2 To invoke a Builder

Share:

Find or Filter Data on Form

Introduction

When I began learning Microsoft Access in 1996, the first challenge I encountered was figuring out how to locate a specific record on a data entry form or how to filter some records based on certain conditions.

I was assigned to develop a system for the Vehicles Division of our company to track pending orders and receipts of heavy equipment and vehicles. If I am the only one using the system, I could have managed to locate the required information on my own—regardless of how long it took—without anyone noticing. But since the system was intended for use by others, it was my responsibility to ensure that it was as user-friendly and efficient as possible. Although I had a solid background in the BASIC programming language at the time, I had no prior experience with Access Basic (the programming language in MS Access Version 2, an early form of Visual Basic).

I struggled with the problem for some time before deciding to explore the Northwind.mdb sample database for ideas. There, on the Customer Phone List form, I discovered the very technique I had been searching for. An Option Group Control was used, featuring 27 buttons labeled A to Z, along with an "All" button to remove the filter. When a user clicks one of the lettered buttons, the form filters the records to display only company names beginning with that letter. The option group was linked to a macro that executed the filtering action. This simple yet effective method provided the solution I had been looking for.

There were no second thoughts on this, and I immediately applied this method to my first MS-Access Project. It was developed without touching a single line of Access Basic Code; all automated procedures are by macros only.

In this exercise, we will explore three different methods for finding and filtering records—all implemented on the same form. You may choose to use any one of these techniques individually or incorporate all of them into your own project, depending on your needs. For demonstration purposes, we will use the Products table from the Northwind.mdb sample database.

Get a Sample Table and Design a Form.

  1. Import the Products table from the Northwind.mdb database. If you're unsure about the file's location, refer to the article titled Saving Data on Forms Not in Table for help.

  2. Once the table is imported, select it in the Navigation Pane, then go to the Insert menu and choose Form. From the list of available options, select AutoForm: Columnar, and click OK to generate the form. Save the newly created form with the name Products.

  3. Display the Form Header/Footer sections, if they are not already visible. To do this, go to the View menu and select Form Header/Footer.

    Next, add a label control to the Form Header section and set its Caption to "Products List". Click on the label, then use the Format toolbar to increase the font size to 20 (or higher, depending on your preference) and apply bold styling for emphasis.

    Tip: If you’d like to give the heading a stylish 3D shadow effect, refer to the article [Shadow 3D Heading Style] for step-by-step instructions.

  4. Add a Command Button to the Footer section of the form.

    To configure the button:

    1. Select the button after placing it on the form.

    2. Press Alt + Enter or choose Properties from the View menu to open the Property Sheet.

    3. Update the button's properties with the following values:

    • Name = cmdExit

    • Caption = Exit

  5. Design a Text Box and four Command Buttons on the Form, as shown in the shaded area of the Form. Change the property values of the Text Box and Buttons as given below:

  6. Click on the Text Box, Display the Property Sheet, and change the property values:

    • Name = xFind

    • Back Color = 0

    • Text Box child-Label Caption = Find / Filter Product Name

  7. Click on the first button, Display the Property Sheet, and change the property Values.

    • Name = FindPID

    • Caption = << Product ID

    • Fore Color = 128

  8. Click on the second button, Display the Property Sheet, and change the property Values.

    • Name = FindFirstLetter

    • Caption = << First Letter

    • Fore Color = 128

  9. Click on the third Button, Display the Property Sheet, and change the property Values.

    • Name = PatternMatch

    • Caption = << Pattern Match

    • Fore Color = 128

  10. Click on the fourth Button, display the Property Sheet, and change the property Values.

    • Name = cmdReset

    • Caption = Reset Filter

  11. Display the Visual Basic Module of the form, select Tools > Macros > Visual Basic Editor when the Products Form is still in Design View.

  12. VBA Code of Form Class Module

  13. Copy and paste the following Code into the VB Module of the Form and save the Form:

Private Sub cmdExit_Click()
DoCmd.Close
End Sub

Private Sub cmdReset_Click()
'Remove Filter effect
'Clear Text Box

Me!xFind = Null
Me.FilterOn = False
End Sub

Private Sub FindPID_Click()
'Find Record matching Product ID
Dim m_find, rst As Recordset

m_find = Me![xFind]
If IsNull(m_find) Then
   Me.FilterOn = False
   Exit Sub
End If

If Val(m_find) = 0 Then
  MsgBox "Give Product ID Number..!"
   Exit Sub
End If

If Val(m_find) > 0 Then
   Set rst = Me.RecordsetClone
   rst.FindFirst "ProductID = " & m_find
   If Not rst.NoMatch Then
      Me.Bookmark = rst.Bookmark
   End If
   rst.Close
End If

End Sub

Private Sub FindfirstLetter_Click()
'Filter Names matching First character
Dim xfirstletter

xfirstletter = Me![xFind]
If IsNull(xfirstletter) Then
  Me.FilterOn = False
  Exit Sub
End If
If Val(xfirstletter) > 0 Then
   Exit Sub
End If

xfirstletter = Left(xfirstletter, 1)
Me.FilterOn = False
Me.Filter = "Products.ProductName Like '" & xfirstletter & "*'"
Me.FilterOn = True

End Sub

Private Sub PatternMatch_Click()
'Filter Names matching the group of characters
'anywhere within the Name
Dim xpatternmatch

xpatternmatch = Me![xFind]
If IsNull(xpatternmatch) Then
  Me.FilterOn = False
  Exit Sub
End If

Me.FilterOn = False
Me.Filter = "Products.ProductName Like '*" & xpatternmatch & "*'"
Me.FilterOn = True
End Sub

How it Works.

  1. Usage of << Product ID Button.

    • Click the Button with a number less than or equal to the Product Code range of values in the Text Box.

    • If clicked with Text Value, it will ask for the Product ID Number.

    • If clicked when the TextBox is empty, it is the same as clicking the Filter Reset Button.

  2. Usage of << First Letter Button.

    • Click the Button with any Alphabet A to Z or a to z in the Text Box.

    • If more than one character is entered, only the first character will be taken.

    • If a Numeric Value is entered, the filter action will be ignored.

    • If clicked when the TextBox is empty, it is the same as clicking the Filter Reset Button.

  3. Usage of << Pattern Match Button.

    • Click the Button with a group of characters that match anywhere within the Product Name.

    • If clicked when the text box is empty, it is the same as clicking the Filter Reset Button.

  4. Usage of the Filter Reset Button.

    • Resets the earlier applied Filter action.

    • Empties the Text Box Control.

Share:

Who is Online

Introduction.

We already know that a Microsoft Access database can be deployed on a Local Area Network (LAN), allowing multiple users to work with it simultaneously. However, a common challenge in such environments is determining the number of users who have been actively connected to the application at any given time.

Similarly, when multiple Access databases are in use within a centrally managed security workgroup, it becomes useful to know which users are currently working on these applications across the network.

Fortunately, you don’t need any complex program to find this out. When a user opens a database, for example, Northwind.mdb—Microsoft Access automatically creates a companion lock file named Northwind.ldb (or .laccdb for .accdb files) in the same folder. This file records details about the active users, including their Workstation IDs and Access User IDs.

You can open this lock file using Notepad or any text editor to view its contents. Once all users close the database, Microsoft Access automatically deletes the lock file. In other words, the presence of a lock file indicates that the database is currently in use; if the file is absent, no users are connected.

In a networked environment, Microsoft Access security can be implemented across multiple databases using a common Workgroup Information File (with an .MDW extension). This file contains shared Workgroup IDs, User IDs, and Passwords, allowing centralized management of user authentication and permissions.

When users log in to the secured workgroup to access any database, Access creates a corresponding lock file (with the .ldb extension) using the same name as the .mdw file. This lock file records the Workstation IDs and User IDs of all users currently active within the workgroup, regardless of which database they are using. The .ldb file serves as a useful tool for monitoring real-time user activity across multiple databases on the network.

We will design a form interface and develop supporting VBA procedures to read and interpret the lock file (.ldb) associated with a Microsoft Access database or Workgroup Information File (.mdw). The program will extract and display a list of active Workstation IDs and User IDs, providing a real-time view of users currently connected to the database.

In addition to displaying this information, we will implement functionality to send messages over the network to selected users from the list, enabling basic communication or alerting capabilities within the local environment.

Designing a WhoIsOnline Form

  1. Design a Form similar to the one shown below and change the Properties of the Controls as explained. Smaller controls are TextBoxes, and the big Control under the label Users Online is a List Box.

  2. Click on the Text Box below the label: Workgroup or Database File Path, and display the property sheet. Change the value of the Name Property to FPath.

  3. Display the Property Sheet of the List Box and change the value of the following properties as given below:

    • Name = UsrList
    • Row Source Type = Value List
    • Column Count = 2
    • Column Heads = No
    • Column Width = 1.25";1.25"
    • Bound Column = 1
    • Multi Select = simple
  4. Display the property sheet of the Text Box above the Send Message Button and change the value of the Name Property to msgtxt.

  5. Display the Property Sheet of the Button with the caption symbol < and change the value of the Name Property to cmdUpdate.

  6. Display the Property Sheet of the Button with the Caption Send Message, and change the value of the Name property to cmdNS.

  7. Save the Form with the name 'whois online'.

    NB: We are referencing all the above Property Values in Programs, and you must specify the Values of respective controls as explained above.

    Copy and paste the following code into the VBA Module (Select Tools > Macro > Visual Basic Editor to display the VBA Module) of the Whois Online Form, save, and close the Form.

Form Class Module VBA Code

Private Sub cmdNS_Click()
'-------------------------------------------------------
'Author: a.p.r. pillai
'Date  : 01/12/2007
'-------------------------------------------------------
Dim ctl As ListBox, msg As String, usrs As String
Dim i As Integer, pcs() As String, xmsg As String
Dim ic As Integer, j As Integer, lc As Integer

On Error GoTo cmdNS_Click_Err

xmsg = Nz(Me.msgtxt, "")

If Len(xmsg) = 0 Then
   MsgBox "Message Control is Empty.", , "cmdNS_Click()"
   Exit Sub
End If

Set ctl = Me.UsrList
lc = ctl.listcount
ic = ctl.ItemsSelected.Count

If ic > 0 Then
ReDim pcs(1 To ic, 1 To 2)
i = 0
For j = 0 To lc - 1
If ctl.Selected(j) Then
    i = i + 1
    pcs(i, 1) = ctl.Column(0, j)
    pcs(i, 2) = ctl.Column(1, j)
End If
Next

usrs = ""
For j = 1 To i
msg = "NET SEND " & pcs(j, 1) & " User: " & pcs(j, 2) & " " & xmsg
  Call Shell(msg)
  If Len(usrs) = 0 Then
     usrs = j & ". WorkStationID: " & pcs(j, 1) & "  UserID: " & pcs(j, 2)
  Else
     usrs = usrs & vbCr & j & ". WorkStationID: " & pcs(j, 1) & "  UserID: " & pcs(j,2)
  End If
Next
  MsgBox "Messages Sent to:" & vbCr & vbCr & usrs & vbCr & vbCr & "successfully.", , "cmdNS_Click()"
Else
  MsgBox "Select one or more Users in list and try again.", , "cmdNS_Click()"
End If

cmdNS_Click_Exit:
Exit Sub

cmdNS_Click_Err:
MsgBox Err.Description, , "cmdNS_Click()"
Resume cmdNS_Click_Exit
End Sub

Private Sub cmdUpdate_Click()
    Me.UsrList.SetFocus
    Me.cmdUpdate.Enabled = False
   WhoisOnline Me.FPath
    Me.cmdUpdate.Enabled = True
End Sub

The Main Program

Copy and Paste the following VBA Code into a Global Module in your Project and save:

Public Function WhoisOnline(ByVal strPathName)
'-------------------------------------------------------
'Author : a.p.r. pillai
'Date   : 01/12/2007
'-------------------------------------------------------
Dim strldb() As String, j As Integer, strpath As String
Dim str As String, intlen As Integer, t As Date
Dim pos As Integer, xsize As Integer, l As Integer
Dim FRM As Form, ctl As ListBox, qt As String
Dim x As String

Const strlen As Integer = 62

On Error Resume Next

qt = Chr$(34)

strpath = Trim(Nz(strPathName, ""))

If Len(strpath) = 0 Then
  MsgBox "File Path is Empty.", , "WhoisOnline()"
  Exit Function
End If

str = Right(strpath, 4)
l = InStr(1, ".mdb.mdw.ldb", str)
Select Case l
    Case 0
      strpath = strpath & ".ldb"
    Case 1, 5
      strpath = Left(strpath, Len(strpath) - 4) & ".ldb"
    Case 9       'it is .ldb no action
End Select

Set FRM = Forms("WhoisOnline")
Set ctl = FRM.Controls("UsrList")

Open "c:\x.bat" For Output As #1
Print #1, "@Echo off"
Print #1, "copy " & strpath & " c:\xx.txt"
Close #1

Call Shell("c:\x.bat", vbHide)

x = Dir("c:\xx.txt")t = Timer
Do While Len(x) = 0 And Timer < (t + 2)
   x = Dir("c:\xx.txt")
Loop

t = Timer
Do While Timer < (t + 2)   'do nothingLoop

Open "c:\xx.txt" For Input As #1
If Err > 0 Then
  'Lock file copying was not successfull
  MsgBox "Database is idle.", , "WhoisOnline()"
  Exit Function
End If
Input #1, str
Close #1

intlen = Int(Len(str) / strlen) + 1
ReDim strldb(1 To intlen, 1 To 2) As String
xsize = strlen / 2

For j = 1 To intlen
  pos = IIf(j = 1, 1, (j - 1) * strlen + 1)
  strldb(j, 1) = Trim(Mid(str, pos, xsize))
  pos = pos + strlen / 2
  strldb(j, 2) = Trim(Mid(str, pos, xsize))
Next

str = ""
For j = 1 To intlen
  If Len(str) = 0 Then
    str = qt & Trim(strldb(j, 1)) & qt & ";" & qt & Trim(strldb(j, 2)) & qt
  Else
    str = str & ";" & qt & Trim(strldb(j, 1)) & qt & ";" & qt & Trim(strldb(j, 2)) & qt
  End If
Next
ctl.RowSource = strctl.Requery
Kill "c:\x.bat"
Kill "c:\xx.txt"

End Function

NOTE: The above VBA Code was written for Windows XP, and the NET SEND message Command is used for sending messages to a Workstation. Windows 10/08/7 uses the MSG Command. Type C:\MSG /? In the Command Prompt, for the full Parameter List and Options.

In the above program, we are creating a DOS Batch File (c:\x.bat) and running it to make a copy of the Lock-File c:\xx.txt as a work file.

The Demo Run

  1. Open the Whois online Form in Normal View. Type the full path of an active database (Tip: give the Path and Name of the Database you are currently working on, if you are not on a Network). If you are on a Network and have a common MS-Access Workgroup File, on which other users are currently connected, then give that File Path Name. No need to specify the File Name extensions mdb, mdw, or ldb, but if you wish to include, you may do so for clarity.

  2. Click on the Button with the < symbol.

  3. Select one or two Workstation IDs in the List Box.

  4. Type a message in the Text Box Control above the Send Message Button for the selected Users.

  5. Click on the Send Message Button. The Message Text will pop up on the selected Users' Machines.

NB: If you have selected your own machine name, then the Send Message action will not work.

Download Demo Database


Download Demo Who-is-online.zip


Share:

Automated Email Alerts

Continued from the previous post: Configure Outlook for Lotus Notes.

The procedure we are about to explore applies to both Internet and Intranet emails. We have already configured Microsoft Outlook with a Lotus Notes profile for users who wish to send scheduled emails from Microsoft Access within a Local Area Network (LAN).

When the If SendObject Action is invoked with the appropriate parameters, Microsoft Access will utilize the default Outlook profile—whether configured for Internet or Lotus Notes—to retrieve the target email addresses and transmit messages accordingly.

In our scenario, we aim to send mail alerts on a weekly schedule, which requires some preliminary setup. Specifically, we need to create two small tables to support the automation process.

Address Book Table.

  1. We will create a local Address Book table within the Access database to store the email addresses of recipients.

    Note: It is also possible to link the Microsoft Outlook or Lotus Notes Address Book directly to a Microsoft Access database. However, for our purpose, a simplified local table is preferred.

    While your Outlook or Lotus Notes Address Book may contain numerous contacts, our scheduled mail alerts will only be sent to a specific group of individuals relevant to the subject matter. Therefore, we will maintain a curated list of these recipients in a dedicated local table, populated with selected entries from the configured mail profile's Address Book. (Refer to the fifth image in the previous post titled Configure Outlook for Lotus Notes for context.)

    A sample layout of this local Lotus Notes Mail Address Table is shown below:

    We can use VBA code to read the contents of the local address table and construct the To and Cc fields of the email message dynamically.

    Lotus Notes email addresses are often long and structured, typically containing location names, department identifiers, and organizational units, separated by forward slashes. A typical address may look like:

    Nancy Davolio/Ohio/hrd/Orgzn01@Orgzn01

    However, for our local address table in Access, we only need to store the display name — typically the First Name and Last Name (e.g., Nancy Davolio). When the mail is sent via Lotus Notes, the application will resolve the full email address automatically by matching the display name against the entries in its main Address Book and insert the complete address into the email.

    In some cases, the contents of the report attached to the email may be relevant only to specific recipients, and we may wish to exclude others from receiving that particular message. To implement such targeted email distribution, we need a way to filter out unrelated addresses from the Address Book for the current mailing.

    This can be achieved by using a unique identifier, such as an Employee Code, which should be recorded in both the report’s source data and the local Address Book table (refer to the ECODE field in the Address Book example above). With this common field in place, we can link the two datasets and retrieve only those email addresses that match the relevant employee codes from the report.

    Alternatively, the program can search for each employee code from the report’s source data within the address table and extract the corresponding email addresses. This approach ensures that report attachments are sent only to the appropriate recipients, maintaining both relevance and confidentiality.

    However, for now, we will proceed with a simpler method in our demonstration.

    Email Scheduling

  2. The second required table is a Control Parameter Table for the email automation program. This table stores the weekly mail alert schedule and other related control settings necessary for managing the automated email process.

    A sample structure of the Parameter Table is shown in the image below.


Configuring a Machine.

Although the application may be shared across multiple users on different PCs, it is not necessary to configure every machine for sending emails. In fact, we want to avoid having emails sent from multiple sources. To ensure consistency, the program will identify the designated mail-sending machine by checking the active computer name at runtime. This is achieved by storing the authorized Computer Name in a control field and comparing it with the name of the current machine before executing the mail procedure.

  1. To find your computer's name, follow either of the methods below:

    Method 1: Using System Properties

    • Right-click the My Computer (or This PC) icon on your desktop and select Properties from the context menu.

    • In the System Properties window, go to the Computer Name tab.

    • Your computer’s name will be shown next to the Full computer name label.

    Method 2: Using the Command Prompt

    • Click the Start menu and select Run.

    • In the dialog box, type cmd and click OK to open the Command Prompt.

    • At the prompt, type set and press Enter.

    • A list of environment variables will appear. Look for the entry COMPUTERNAME=X, where X is your system’s name.

We can check for this value using the VBA Environ() Function with the parameter value "COMPUTERNAME".

X = Environ("COMPUTERNAME")

Our email alert is scheduled to be sent once a week, on a specific day—let’s say every Monday. We assume the application will be opened daily by users for regular use. Each time the application launches, it will perform a check against the email schedule.

If the current day is Monday, the program will initiate the mail-sending process. However, to avoid duplicate emails, the report should be sent only once per day, regardless of how many times the application is opened on that Monday.

It’s also possible that the user might forget to open the application on Monday, or the scheduled day falls on a holiday, causing the email alert to be missed. In such cases, the program should detect the missed schedule and send the overdue email the next time the application is opened, regardless of the day.

To support this behavior, we will store the last scheduled date in a control parameter table. This allows the application to determine whether the current day has passed the scheduled date and act accordingly. For our example, we will begin with a sample date: Monday, November 19, 2007.

The Email Sending VBA Code

With the above groundwork completed, our preparation phase is now complete. It’s time to move on to the VBA code implementation.

Copy the Main Program provided below and paste it into a standard module in your Access project. After pasting the code, save the module to proceed further.

Public Function SendWeeklyMail()
'--------------------------------------------------------
'Author : a.p.r. pillai
'Date   : 01/11/2007
'--------------------------------------------------------
Dim db As Database, rst As Recordset
Dim m_Addto As String, m_Cc As String, j As Integer
Dim msgBodyText As String, m_Subject As String
Dim m_MailDate, m_ComputerName As String, chk_CName As String

On Error GoTo SendWeeklyMail_Err

'Field Name and Table Name are same
m_MailDate = DLookup("MailDate", "MailDate")
m_ComputerName = DLookup("ComputerName", "MailDate")
chk_CName = Environ("COMPUTERNAME")

'identify the Mail Client Computer
If chk_CName  = m_ComputerName Then
   Exit Function
End If

'Verify Mail Schedule
If m_MailDate + 7 > Date Then
    Exit Function ' mail not due
End If

m_Addto = ""
m_Cc = ""
j = 0

'Create Address List
Set db = CurrentDb
Set rst = db.OpenRecordset("Add_Book", dbOpenDynaset)
Do While Not (rst.EOF)
    If rst!TO Then
        If Len(m_Addto) = 0 Then
            m_Addto = rst![MailID]
        Else
            m_Addto = m_Addto & ", " & rst![MailID]
        End If

    ElseIf rst![cc] Then

        If Len(m_Cc) = 0 Then 
           m_Cc = rst![MailID]
        Else
            m_Cc = m_Cc & ", " & rst![MailID]
        End If

    End If
rst.MoveNext
Loop
rst.Close

m_Subject = "BANK GUARANTEE RENEWAL REMINDER"

msgBodyText = "Bank Guarantee Renewals Due weekly Status Report as on " _& Format(Date, "dddd, mmm dd,yyyy") & " which expires within next 15 days Cases is attached for review and " & "necessary action. "
msgBodyText = msgBodyText & vbCr & vbCr & "Machine generated email, " & " please do not send reply to this email." & vbCr

'replace x with your Lotus Notes password retaining the ~ character at end. 
SendKeys "xxxxxxx~", False

DoCmd.SendObject acReport, "BG_Status", "SnapshotFormat(*.snp)", m_Addto, m_Cc, "", m_Subject, msgBodyText, False, ""

'Update MailDate to current date (if Monday) or date of
'previous Monday, if the mail was send after the due date.

Set rst = db.OpenRecordset("MailDate", dbOpenDynaset)
rst.Edit
Do While rst![MailDate] + 7 <= Date
  rst![MailDate] = rst![MailDate] + 7
Loop
rst.Update
rst.Close

SendWeeklyMail_Exit:
Exit Function

SendWeeklyMail_Err:
MsgBox Err.Description, , "SendWeeklyMail()"
Resume SendWeekly
Mail_Exit

End Function

Important Note:
In the above code, you will need to modify the SendKeys "xxxxxxx~", False line. Replace the x characters with your Lotus Notes password, ensuring the tilde character (~) is retained, as it simulates the Enter keystroke.

This line is intended to automatically pass the Lotus Notes password in anticipation of the login prompt, allowing the process to continue without user intervention. However, since the mail may be routed through multiple layers, this approach is somewhat unreliable—the timing may not always align with the prompt. If this fails, Lotus Notes will still request the password, and you’ll need to enter it manually and press Enter.

For Internet users (i.e., sending via SMTP), this line can be disabled by simply commenting it out with a single quote ('), If Outlook has already been configured to store the email password.

To ensure a smooth process at application startup, we’ll also include a few lines of code in the Control Screen module to introduce a brief delay after the application opens, before calling the SendWeeklyMail() procedure.

' put the next line at the header section of the Module
Dim i as integer 

Private Sub Form_Load()
   i = 0
   Me.TimerInterval = 1000
End Sub

Private Sub Form_Timer()
i=i+1
If i = 16 then ' 15 seconds delay
   Me.Timerinterval = 0
    SendWeeklyMail
End if
End Sub

Copy and paste the above lines in the Control Screen Module, save, and close the Form. Try out the Automated pre-scheduled Email Procedure.

Share:

Configure Outlook for Lotus Notes

Continued from earlier Post: MS-Access and Emails

We have seen that sending emails from Microsoft Access is quite straightforward, just like other familiar methods. With a few clicks, we can send emails with MS Access objects attached. The available output formats for the attachment depend on the type of object selected. For example, if a VBA code module is selected, it will be automatically converted into plain text format before being attached to the email.

As mentioned in an earlier post, we can automatically send mail alerts on important matters within a Local Area Network (LAN) using email transport services like Lotus Notes, directly from a Microsoft Access application.

However, before we delve into the mail-sending procedures and related programs, we must first configure Microsoft Outlook on one of the PCs to work with Lotus Notes and use its contact list for managing recipients.

Access Mail Client

Your application may be shared by multiple users across different PCs; however, all outgoing emails should be routed through a single designated machine—let’s call it the Access Mail Client. This machine must be configured specifically for sending emails via Lotus Notes.

Lotus Notes requires both a Mail Server and a Client application installed on each PC. Accordingly, the Access Mail Client must have the Lotus Notes Client installed and actively used for sending emails. Additionally, this machine will require a unique Lotus Notes ID file and an associated Lotus Notes email account.

NB: If you prefer that Mail Alerts from your Access application do not display a personal user ID as the sender, a dedicated Lotus Notes mail ID should be created for this purpose. The Lotus Notes Client on the Access Mail Client machine must then be configured using this ID. You may need to consult your Lotus Notes Administrator to set up and configure this special account.

Configuring MS Outlook with Lotus Notes.

We will now explore the Microsoft Outlook configuration steps, accompanied by a few illustrative images and explanations of what each step accomplishes.

  1. Your Lotus Notes ID file must be registered within Lotus Notes itself to make it accessible to external programs, such as Microsoft Outlook. To do this, open Lotus Notes and log in with your User ID and password. From the File menu, select MobileEdit Current Location. The Location: Office (Network) settings screen will appear.

  2. Click on the Advanced Tab and select Basics from the displayed 2nd set of Tabs. See the Image below.

  3. Click on the text box next to the User ID label to activate it, then click on the Search (magnifying glass) icon located below the label to browse for your Lotus Notes User ID file. The typical file path is:

    makefile
    X:\Lotus\Notes\Data\filename.id

    Here, X represents the drive where Lotus Notes is installed, and the filename usually resembles your name or the one assigned by your Lotus Notes administrator. Locate this .id file and insert it into the text box.

    This file contains your Lotus Notes email ID and password, which Microsoft Outlook requires to access the Lotus Notes Contact List and to send or receive emails through Lotus Notes.

  4. Close the Control after inserting the Location reference and minimize Lotus Notes.

  5. Open the Control Panel from the Start Menu → Settings, then double-click the Mail icon to display the Mail Setup control, which includes the Services, Delivery, and Addressing tabs (as shown in the image below).

    Please note that if your version of Microsoft Outlook is not installed as Corporate or Workgroup, the available options and layout may appear differently. The screenshots referenced are based on a Microsoft Office 2000 installation.

  6. Click on the Services tab. If no mail services have been previously configured, the Profiles window will appear empty.

  7. Next, go to the Delivery tab and select Lotus Notes Message Store in the control below. At this point, you may be prompted to enter your Lotus Notes password to complete the setup. Once this step is finished, the Information Service entry for Lotus Notes Transport will appear in the following window.

  8. Click the Add button to open the Add Services to Profile list. From the available options, select Lotus Notes Mail and click to add it to the Profiles window.

  9. Click on the Addressing tab in the Mail Setup control panel. You can choose either the Lotus Notes Main Address Book or your personal Lotus Notes Address Book—which may include selected entries copied from the main address book—and assign it to the appropriate controls. Refer to the image below for guidance.

  10. Click Apply to save the updated settings, and then click OK to close the window. These configuration steps can also be accessed through the Options menu under Tools in Microsoft Outlook.

  11. Next, we need to define how contact names are stored in the Address Book, which can be done from within Outlook.

  12. Open Microsoft Outlook and select Preferences from the Tools menu.

  13. Click on the Contact Options button.

  14. Choose the appropriate settings in both controls as shown in the image below, then click OK to confirm.

  15. The first control settings say that while sending mails, insert the Names in this order, but while storing the values in the Address Book, use the format in the second control.

    When you look for the Email addresses manually in the Address Book, it will be displayed in the second format, and you can search for the names by typing the first few characters of the first name in the lookup control.

    But when we attempt to send mail from MS-Access, we must present the email ID to Lotus Notes in the first format.

    The Image of the Lotus Notes Mail ID lookup control is given below for reference. I have edited the image to insert those names more familiar to you. Check the name displayed in the left window and how the name format changes when it is inserted in the To line.

  16. You may now try to send an e-mail through Lotus Notes Mail manually from MS-Access, as we did in an earlier session, using some of your friends' Lotus Notes IDs. During the mail transmitting point, Lotus Notes will prompt for the password.

Next, we will see how to send the Mail Alerts automatically from Microsoft Access through Lotus Notes at scheduled intervals.

Share:

PRESENTATION: ACCESS USER GROUPS (EUROPE)

Translate

PageRank

Post Feed


Search

Popular Posts

Blog Archive

Powered by Blogger.

Labels

Forms Functions How Tos MS-Access Security Reports msaccess forms Animations msaccess animation Utilities msaccess controls Access and Internet MS-Access Scurity MS-Access and Internet Class Module External Links Queries Array msaccess reports Accesstips WithEvents msaccess tips Downloads Objects Menus and Toolbars Collection Object MsaccessLinks Process Controls Art Work Property msaccess How Tos Combo Boxes Dictionary Object ListView Control Query VBA msaccessQuery Calculation Event Graph Charts ImageList Control List Boxes TreeView Control Command Buttons Controls Data Emails and Alerts Form Custom Functions Custom Wizards DOS Commands Data Type Key Object Reference ms-access functions msaccess functions msaccess graphs msaccess reporttricks Command Button Report msaccess menus msaccessprocess security advanced Access Security Add Auto-Number Field Type Form Instances ImageList Item Macros Menus Nodes RaiseEvent Recordset Top Values Variables Wrapper Classes msaccess email progressmeter Access2007 Copy Excel Export Expression Fields Join Methods Microsoft Numbering System Records Security Split SubForm Table Tables Time Difference Utility WScript Workgroup database function msaccess wizards tutorial Access Emails and Alerts Access Fields Access How Tos Access Mail Merge Access2003 Accounting Year Action Animation Attachment Binary Numbers Bookmarks Budgeting ChDir Color Palette Common Controls Conditional Formatting Data Filtering Database Records Defining Pages Desktop Shortcuts Diagram Disk Dynamic Lookup Error Handler External Filter Formatting Groups Hexadecimal Numbers Import Labels List Logo Macro Mail Merge Main Form Memo Message Box Monitoring Octal Numbers Operating System Paste Primary-Key Product Rank Reading Remove Rich Text Sequence SetFocus Summary Tab-Page Union Query User Users Water-Mark Word automatically commands hyperlinks iSeries Date iif ms-access msaccess msaccess alerts pdf files reference restore switch text toolbar updating upload vba code