Access: Emailing Order Lists to Clients


By Helen Feddema
Access versions: 2007-2013
Level:  Intermediate
Access Archon #240:

Introduction

In a database (like the sample Northwind database) that records orders, you might want a quick and easy way to send order lists to customers.  This article demonstrates how to send order lists to customers in both Plain Text and HTML format emails.

The Main Menu

The sample database for this article, Emailing Orders to Customers.accdb, has a New Style Main Menu (see Access Archon #212 for more details on this type of menu), with a large button for opening the main form, a selector for opening other forms, and a group of controls used to filter order records for emailing order lists:

AW 1705-A

Figure A.  The main menu of the sample database, with controls for filtering order lists

The Start Date control’s row source is the OrderDate field in tblOrders, and once you select a date from this combo box, the End Date combo box’s row source is filtered for dates equal to or later than the selected start date.  This method is preferable to letting users enter any dates, since it prevents the selection of date ranges with no orders.

The Select Customer control lets you select a customer from tblCustomers, using a filter to select only customers with orders, and applying a date range filter if a date range has been selected.  There is also an [All] selection so users can explicitly select all customers.  For both the date range and customer filters, if no filter value is selected, all dates (or all customers) are selected.

The option group at the bottom of the main menu offers a selection of Plain Text (the default selection) or HTML for the mail message format; when you click the Email Orders to Customers button, one of two procedures runs to create and open (but not send) emails to a customer, or to all customers.  The two procedures are listed below:

1
Public Sub EmailPlainText(strSelectedCustomerID As String)
1
On Error GoTo ErrorHandler
1
  
1
   Dim appOutlook As New Outlook.Application
1
  
1
   Debug.Print "Selected Customer ID: " & strSelectedCustomerID
1
  
1
   If strSelectedCustomerID = "ALL" Then

1
      'Create emails for all customers

1
      Set rstCustomers = CurrentDb.OpenRecordset("tblCustomers")
1
      strQueryOrders = "qrySelectedOrders"
1
     
1
      Do While Not rstCustomers.EOF

1
         'Create filtered recordset of orders for this customer

1
         strEMail = Nz(rstCustomers![Email])
1
         strCompany = Nz(rstCustomers![CompanyName])
1
         strSubject = "Orders for " & strCompany
1
         strCustomerID = Nz(rstCustomers![CustomerID])
1
        
1
         If strCustomerID <> "" Then
1
            strSQL = "SELECT * FROM qryOrdersWithDetailsDateRange WHERE " _
1
               & "[CustomerID] = " & Chr(39) & strCustomerID & Chr(39) & ";"
1
         End If
1
     
1
         Debug.Print "SQL for " & strQueryOrders & ": " & strSQL
1
         lngCount = CreateAndTestQuery(strQueryOrders, strSQL)
1
         Debug.Print "No. of items found: " & lngCount
1
         If lngCount = 0 Then
1
            GoTo NextCustomer
1
         Else

1
            'Create email for this customer

1
            Set msg = appOutlook.CreateItem(olMailItem)
1
            msg.To = strEMail
1
            msg.Subject = strSubject
1
              

1
         'Create header line

1
         strHeader = "Order Date" & "    " & "Quantity" _
1
            & "    " & "ProductName"
1
         strBody = strHeader & vbCrLf & vbCrLf
1
        

1
         'Put orders data into body of email

1
         Set rstOrders = CurrentDb.OpenRecordset(strQueryOrders)
1
         'Debug.Print "Processing orders for " & strCompany
1
        
1
         Do While Not rstOrders.EOF
1
            dteOrder = Nz(rstOrders![OrderDate])
1
            strItem = Nz(rstOrders![ProductName])
1
            lngQuantity = Nz(rstOrders![Quantity])
1
            strQuantity = FormatNo(lngQuantity)
1
           

1
            'Create line of body text

1
            strLine = Format(dteOrder, "mm/dd/yyyy") & "     " _
1
               & strQuantity & "       " & strItem
1
            'Debug.Print "Line text: " & strLine
1
            strBody = strBody & strLine & vbCrLf
1
           
1
            rstOrders.MoveNext
1
         Loop
1
        
1
         msg.body = strBody
1
         msg.Display
1
           
1
         End If
1
NextCustomer:
1
         rstCustomers.MoveNext
1
      Loop
1
   Else

1
      'Create email for selected customer

1
      strSQL = "SELECT * FROM qryOrdersWithDetailsDateRange WHERE " _
1
         & "[CustomerID] = " & Chr(39) & strSelectedCustomerID _
1
         & Chr(39) & ";"
1
      strQueryOrders = "qrySelectedOrders"
1
      'Debug.Print "SQL for " & strQueryOrders & ": " & strSQL
1
      lngCount = CreateAndTestQuery(strQueryOrders, strSQL)
1
      'Debug.Print "No. of items found: " & lngCount
1
      If lngCount = 0 Then
1
         strPrompt = "No records found; canceling"
1
         strTitle = "Canceling"
1
         MsgBox strPrompt, vbOKOnly + vbCritical, strTitle
1
         GoTo ErrorHandlerExit
1
      Else
1
         Set rstCustomer = CurrentDb.OpenRecordset(strQueryOrders)
1
         strEMail = Nz(rstCustomer![Email])
1
         strCompany = Nz(rstCustomer![CompanyName])
1
         strSubject = "Orders for " & strCompany
1
        

1
         'Create email for this customer

1
         Set msg = appOutlook.CreateItem(olMailItem)
1
         msg.To = strEMail
1
         msg.Subject = strSubject
1
           

1
         'Create header line

1
         strHeader = "Order Date" & "    " & "Quantity" _
1
            & "    " & "ProductName"
1
         strBody = strHeader & vbCrLf & vbCrLf
1
        

1
         'Put orders data into body of email

1
         Set rstOrders = CurrentDb.OpenRecordset(strQueryOrders)
1
         'Debug.Print "Processing orders for " & strCompany
1
        
1
         Do While Not rstOrders.EOF
1
            dteOrder = Nz(rstOrders![OrderDate])
1
            strItem = Nz(rstOrders![ProductName])
1
            lngQuantity = Nz(rstOrders![Quantity])
1
            strQuantity = FormatNo(lngQuantity)
1
           

1
            'Create line of body text

1
            strLine = Format(dteOrder, "mm/dd/yyyy") & "     " _
1
               & strQuantity & "       " & strItem
1
            'Debug.Print "Line text: " & strLine
1
            strBody = strBody & strLine & vbCrLf
1
           
1
            rstOrders.MoveNext
1
         Loop
1
        
1
         msg.body = strBody
1
         msg.Display
1
        
1
      End If
1
   End If
1
  
1
ErrorHandlerExit:
1
   Set appOutlook = Nothing
1
   Exit Sub
1
ErrorHandler:
1
   MsgBox "Error No: " & Err.Number _
1
      & " in EmailPlainText procedure; " _
1
      & "Description: " & Err.Description
1
   Resume ErrorHandlerExit
1
End Sub
1
Public Sub EmailHTML(strSelectedCustomerID As String)
1
On Error GoTo ErrorHandler
1
   Dim appOutlook As New Outlook.Application
1
  
1
   Debug.Print "Selected Customer ID: " & strSelectedCustomerID
1
  
1
   If strSelectedCustomerID = "ALL" Then

1
      'Create emails for all customers

1
      Set rstCustomers = CurrentDb.OpenRecordset("tblCustomers")
1
      strQueryOrders = "qrySelectedOrders"
1
     
1
      Do While Not rstCustomers.EOF

1
         'Create filtered recordset of orders for this customer

1
         strEMail = Nz(rstCustomers![Email])
1
         strCompany = Nz(rstCustomers![CompanyName])
1
         strSubject = "Orders for " & strCompany
1
         strCustomerID = Nz(rstCustomers![CustomerID])
1
        
1
         If strCustomerID <> "" Then
1
            strSQL = "SELECT * FROM qryOrdersWithDetailsDateRange WHERE " _
1
               & "[CustomerID] = " & Chr(39) & strCustomerID & Chr(39) & ";"
1
         End If
1
     
1
         Debug.Print "SQL for " & strQueryOrders & ": " & strSQL
1
         lngCount = CreateAndTestQuery(strQueryOrders, strSQL)
1
         Debug.Print "No. of items found: " & lngCount
1
         If lngCount = 0 Then
1
            GoTo NextCustomer
1
         Else

1
            'Create email for this customer

1
            Set msg = appOutlook.CreateItem(olMailItem)
1
            msg.To = strEMail
1
            msg.Subject = strSubject
1
              

1
            'Create starter HTML text for this customer

1
            strHTMLBody = ""
1
            strHeader = "<p> <font face='Arial', size=3>" _
1
               & "Your orders are listed below: <br><br>" _
1
               & "<table width='500' border='1'>" _
1
               & "   <tr>" _
1
               & "      <td width='50'height='26' nowrap valign='bottom'" _
1
               & "align='left'><font face='Arial', " _
1
               & "size=3><strong>Order Date</strong></font></td>" _
1
               & "      <td width='25' height='26'nowrap valign='bottom'" _
1
               & "align='left'><font face='Arial', " _
1
               & "size=3><strong>Quantity</strong></font>" _
1
               & "      <td width='200'height='26' nowrap valign='bottom'" _
1
               & "align='left'><font face='Arial', " _
1
               & "size=3><strong>Item</strong></font></td>" _
1
               & "   </tr>"
1
  

1
            'Put orders data into body of email

1
            Set rstOrders = CurrentDb.OpenRecordset(strQueryOrders)
1
            Debug.Print "Processing orders for " & strCompany
1
           
1
            Do While Not rstOrders.EOF
1
               dteOrder = Nz(rstOrders![OrderDate])
1
               strOrderDate = Format(dteOrder, "Short Date")
1
               strItem = Nz(rstOrders![ProductName])
1
               lngQuantity = Nz(rstOrders![Quantity])
1
              

1
               'Create line of body text

1
               strLine = "<font face='Arial', size=3" _
1
                  & "   <tr>" _
1
                  & "      <td width='5'valign='bottom' align='center'>" _
1
                  & strOrderDate & "</td>" _
1
                  & "      <td width='25' valign='bottom' align='center'>" _
1
                  & CStr(lngQuantity) & "</td>" _
1
                  & "      <td width='200'valign='bottom' align='left'>" _
1
                  & strItem & "</td>" _
1
                  & "   </tr></font>"
1
               Debug.Print "Line text: " & strLine
1
               strHTMLBody = strHTMLBody & strLine
1
              
1
               rstOrders.MoveNext
1
            Loop
1
        
1
         msg.HTMLBody = strHeader & strHTMLBody
1
         msg.Display
1
           
1
         End If
1
NextCustomer:
1
         rstCustomers.MoveNext
1
      Loop
1
   Else

1
      'Create email for selected customer

1
      strSQL = "SELECT * FROM qryOrdersWithDetailsDateRange WHERE " _
1
         & "[CustomerID] = " & Chr(39) & strSelectedCustomerID _
1
         & Chr(39) & ";"
1
      strQueryOrders = "qrySelectedOrders"
1
      'Debug.Print "SQL for " & strQueryOrders & ": " & strSQL
1
      lngCount = CreateAndTestQuery(strQueryOrders, strSQL)
1
      'Debug.Print "No. of items found: " & lngCount
1
      If lngCount = 0 Then
1
         strPrompt = "No records found; canceling"
1
         strTitle = "Canceling"
1
         MsgBox strPrompt, vbOKOnly + vbCritical, strTitle
1
         GoTo ErrorHandlerExit
1
      Else
1
         Set rstCustomer = CurrentDb.OpenRecordset(strQueryOrders)
1
         strEMail = Nz(rstCustomer![Email])
1
         strCompany = Nz(rstCustomer![CompanyName])
1
         strSubject = "Orders for " & strCompany
1
        

1
         'Create email for this customer

1
         Set msg = appOutlook.CreateItem(olMailItem)
1
         msg.To = strEMail
1
         msg.Subject = strSubject
1
           

1
         'Create starter HTML text for this customer

1
         strHTMLBody = ""
1
         strHeader = "<p> <font face='Arial', size=3>" _
1
            & "Your orders are listed below: <br><br>" _
1
            & "<table width='500' border='1'>" _
1
            & "   <tr>" _
1
            & "      <td width='50'height='26' nowrap valign='bottom'" _
1
            & "align='left'><font face='Arial', " _
1
            & "size=3><strong>Order Date</strong></font></td>" _
1
            & "      <td width='25' height='26'nowrap valign='bottom'" _
1
            & "align='left'><font face='Arial', " _
1
            & "size=3><strong>Quantity</strong></font>" _
1
            & "      <td width='200'height='26' nowrap valign='bottom'" _
1
            & "align='left'><font face='Arial', " _
1
            & "size=3><strong>Item</strong></font></td>" _
1
            & "   </tr>"

1
         'Put orders data into body of email

1
         Set rstOrders = CurrentDb.OpenRecordset(strQueryOrders)
1
         Debug.Print "Processing orders for " & strCompany
1
        
1
         Do While Not rstOrders.EOF
1
            dteOrder = Nz(rstOrders![OrderDate])
1
            strOrderDate = Format(dteOrder, "Short Date")
1
            strItem = Nz(rstOrders![ProductName])
1
            lngQuantity = Nz(rstOrders![Quantity])
1
           

1
            'Create line of body text

1
            strLine = "<font face='Arial', size=3" _
1
               & "   <tr>" _
1
               & "      <td width='5'valign='bottom' align='center'>" _
1
               & strOrderDate & "</td>" _
1
               & "      <td width='25' valign='bottom' align='center'>" _
1
               & CStr(lngQuantity) & "</td>" _
1
               & "      <td width='200'valign='bottom' align='left'>" _
1
               & strItem & "</td>" _
1
               & "   </tr></font>"
1
            Debug.Print "Line text: " & strLine
1
            strHTMLBody = strHTMLBody & strLine
1
           
1
            rstOrders.MoveNext
1
         Loop
1
        
1
         msg.HTMLBody = strHeader & strHTMLBody
1
         msg.Display
1
        
1
      End If
1
   End If
1
  
1
ErrorHandlerExit:
1
   Set appOutlook = Nothing
1
   Exit Sub
1
ErrorHandler:
1
   MsgBox "Error No: " & Err.Number _
1
      & " in EmailHTML procedure; " _
1
      & "Description: " & Err.Description
1
   Resume ErrorHandlerExit
1
End Sub

A Note on Outlook HTML

The dialect of HTML used in creating an Outlook HTML message is rather peculiar.  It seems to more or less correspond to HTML 3.2, circa 1993 (at least, an HTML manual for that version was helpful).  One extra peculiarity is the font sizing – instead of using actual font sizes in points (10 pt, 12 pt, etc), Outlook HTML uses sizes 1, 2 and 3.  When writing code to create an HTML email message, you may need to do a lot of trial and error tinkering to get the results you want.

The Customers and Orders Form

The main form in the sample database is frmCustomersAndOrders, a main form with a subform displaying orders for each customer.  The form footer has an option group for selecting the email format with a button for generating a message listing all orders for the customer, and a button for previewing a report of all orders for the current customer:

AW 1705-B

Figure B.  The Customers and Orders form, with controls for emailing an orders list or previewing a report.

The Email Orders button uses the same code as the button on the main menu, but just the portion that creates an email for a single customer.

The report for Alfreds Futterkiste is shown below:

AW 1702-C

Figure C.  The Orders report for a single customer

References

The code in the sample database needs the following references (in addition to the default references):

Microsoft DAO 3.6 Object Library (if running a version of Access older than 2007)

Microsoft Outlook 14.0 Object Library

Microsoft Word 14.0 Object Library (for SortDeclarations procedure only)

Microsoft Forms 2.0 Object Library (for SortDeclarations procedure only)

If you import code or objects into a database of your own, you may need to set one or more of these references.  The version number may differ, depending on your Office version; check the version you have.  References are set in the References dialog, opened from the VBA window.  For more information on working with references, see Access Archon #107, Working with References.

Supporting Files

The zip file containing this article, in Word 97-2003 format, plus the supporting file(s), may be downloaded from the Access Archon page of my Web site, as accarch240.zip, which is the last entry in the table of Access Archon columns for Access Watch.

Document Name Document Type Place in
Emailing Orders to Customers.accdb Access 2007-2010 database (can be used in higher versions) Wherever you want

 


Want More?

Office Watch has the latest news and tips about Microsoft Office.  Delivered once a week.