Skip to content

Merging data from Queries and Recordsets to Word, Part 1

How to merge data from a recordset based on a query to Word documents.

Access Archon #168

 


Introduction

An AW reader wrote to me asking if the document properties merge code in my Code Sample #24could be modified to merge data to Word from a query, instead of selections in a listbox.  While the ItemsSelected collection of a listbox (which is used in Code Sample #24) is a very handy way to select records for a merge, sometimes it is more convenient to merge from a query, already set up to include all the records you want to merge.  And you can create such a query on-the-fly, in VBA code.  This article describes how to merge data from a recordset based on a query to Word documents.


Using Saved Queries to Filter Data

The sample database, Merging Data from a Recordset to Word (AA 168).mdb, has tables of data from the old Northwind sample database.  The tblCustomers table has data on customers in many different countries; if you frequently send out mailings to just to customers in certain countries, you can create filters for the countries that you send mailings to most frequently, and use the queries to send out mailings. 

Figure A.  A form for creating labels using TypeText

The frmWordLabelsTypeText form (shown in Figure A) uses an option group to select one of four countries for the mailing (each uses a saved query that filters for that country), and offers you a choice of two Avery mailing labels documents.  After selecting a Labels document and a country, clicking the Mergebutton creates a new Labels document and fills its cells with address data from tblCustomers, usin g the TypeText method to insert data from one record into one cell of the table, as shown in Figure B:

Figure B.  An Avery 5160 Labels document filled with customer address data


VBA Code

The cmdMerge_Click event procedure on frmWordLabelsTypeText creates a single Labels document from the selected template and fills its cells with name and address data, using a saved query:

Private Sub cmdMerge_Click()

‘Creates a Labels document, with one address per cell

 

On Error GoTo ErrorHandler

 

   Dim appWord As Word.Application

   Dim ctl As Access.Control

   Dim dbs As DAO.Database

   Dim doc As Word.Document

   Dim docs As Word.Documents

   Dim fil As Scripting.File

   Dim fso As New Scripting.FileSystemObject

   Dim i As Integer

   Dim intSaveNameFail As Boolean

   Dim prps As Object

   Dim rst As DAO.Recordset

   Dim strAddress As String

   Dim strCountry As String

   Dim strCompanyName As String

   Dim strDocsPath As String

   Dim strDocType As String

   Dim strJobTitle As String

   Dim strLongDate As String

   Dim strName As String

   Dim strPrompt As String

   Dim strQuery As String

   Dim strRecordSource As String

   Dim strSaveName As String

   Dim strSaveNamePath As String

   Dim strShortDate As String

   Dim strSQL As String

   Dim strTemplate As String

   Dim strTemplateNameAndPath As String

   Dim strTemplatePath As String

   Dim strTest As String

   Dim strTestFile As String

   Dim strTitle As String

  

   ‘Check that a document has been selected

   strTemplate = Nz(Me![cboSelectLabels].Value)

   Set ctl = Me![cboSelectLabels]

   If strTemplate = “” Then

      strTitle = “No selection made”

      strPrompt = “Please select a labels document”

      MsgBox prompt:=strPrompt, _

         buttons:=vbCritical + vbOKOnly, _

         Title:=strTitle

      ctl.SetFocus

      ctl.Dropdown

      GoTo ErrorHandlerExit

   Else

      strTemplate = ctl.Value

   End If

  

   ‘Set Word application variable; if Word is not running,
   ‘the error handler defaults to CreateObject

   Set appWord = GetObject(, “Word.Application”)

  

   strShortDate = Format(Date, “m-d-yyyy”)

   strDocsPath = GetProperty(strName:=”DocumentsPath”, _

      strDefault:=””)

   If Right(strDocsPath, 1) <> “” Then

      strDocsPath = strDocsPath & “”

   End If

  

   strTemplatePath = GetProperty(strName:=”TemplatesPath”, _

      strDefault:=””)

   If Right(strTemplatePath, 1) <> “” Then

      strTemplatePath = strTemplatePath & “”

   End If

  

   strTemplateNameAndPath = strTemplatePath & strTemplate

  

On Error Resume Next

   ‘Check for existence of template in template folder,
   ‘and exit if not found

   Set fil = fso.GetFile(strTemplateNameAndPath)

   If fil Is Nothing Then

      strTitle = “Template not found”

      strPrompt = “Can’t find ” & strTemplate & ” in ” _

         & strTemplatePath & “; canceling”

      MsgBox strPrompt, vbCritical + vbOKOnly

      GoTo ErrorHandlerExit

   End If

  

On Error GoTo ErrorHandler

   Set docs = appWord.Documents

   Set doc = docs.Add(strTemplateNameAndPath)

   appWord.Visible = True

  

   strRecordSource = “tblCustomers”

   strCountry = GetProperty(strName:=”Country”, strDefault:=””)

   strTemplatePath = GetProperty(strName:=”TemplatesPath”, strDefault:=””)

   strQuery = “qryTempMerge”

   strSQL = “SELECT * FROM ” & strRecordSource & _

      ” WHERE [Country] = ” & Chr(39) & strCountry & Chr(39) & “;”

   Debug.Print “SQL Statement: ” & strSQL

   If CreateAndTestQuery(strQuery, strSQL) = 0 Then

      strTitle = “Can’t merge”

      strPrompt = “There are no customers in ” & strCountry _

         & “; can’t create labels”

      MsgBox prompt:=strPrompt, _

         buttons:=vbCritical + vbOKOnly, _

         Title:=strTitle

      GoTo ErrorHandlerExit

   End If

 

   Set dbs = CurrentDb

   Set rst = dbs.OpenRecordset(strQuery, dbOpenDynaset)

  

   Do While Not rst.EOF

      ‘Write info from customer item to variables
      ‘Check for required address information

      strTest = rst![Address]

      Debug.Print “Street address: ” & strTest

      If strTest = “” Then

         MsgBox “Can’t create label — no street address!”

         GoTo NextCustomer

      End If

     

      strTest = rst![City]

      Debug.Print “City: ” & strTest

      If strTest = “” Then

         MsgBox “Can’t create label — no city!”

         GoTo NextCustomer

      End If

     

      strTest = rst![PostalCode]

      Debug.Print “Postal code: ” & strTest

      If strTest = “” Then

         MsgBox “Can’t create label — no postal code!”

         GoTo NextCustomer

      End If

  

      strName = Nz(rst![ContactName])

      strJobTitle = Nz(rst![ContactTitle])

      If strJobTitle <> “” Then

         strName = strName & vbCrLf & strJobTitle

      End If

      strCompanyName = Nz(rst![CompanyName])

      strAddress = Nz(rst![Address]) & vbCrLf & _

         Nz(rst![City]) & ”  ” & _

         Nz(rst![Region]) & _

         ”  ” & Nz(rst![PostalCode])

      Debug.Print “Address: ” & strAddress

      If strCountry <> “USA” Then

         strAddress = strAddress & vbCrLf & strCountry

      End If

     

      ‘Insert data into labels

      With appWord.Selection

         .TypeText Text:=strName

         .TypeParagraph

         .TypeText Text:=strCompanyName

         .TypeParagraph

         .TypeText Text:=strAddress

         .TypeParagraph

         .MoveRight Unit:=wdCell

      End With

     

NextCustomer:

      rst.MoveNext

   Loop

  

   ‘Check for existence of previously saved document in documents folder,
   ‘and append an incremented number to save name if found

   strDocType = doc.BuiltInDocumentProperties(2)

   strSaveName = strDocType & ” on ” & strShortDate & “.doc”

   i = 2

   intSaveNameFail = True

   Do While intSaveNameFail

      strSaveNamePath = strDocsPath & strSaveName

      Debug.Print “Proposed save name and path: ” _

         & vbCrLf & strSaveNamePath

      strTestFile = Nz(Dir(strSaveNamePath))

      Debug.Print “Test file: ” & strTestFile

      If strTestFile = strSaveName Then

         Debug.Print “Save name already used: ” & strSaveName

        

         ‘Create new save name with incremented number

         intSaveNameFail = True

         strSaveName = strDocType & ” ” & CStr(i) & _

            ” on ” & strShortDate & “.doc”

         strSaveNamePath = strDocsPath & strSaveName

         Debug.Print “New save name and path: ” _

            & vbCrLf & strSaveNamePath

         i = i + 1

      Else

         Debug.Print “Save name not used: ” & strSaveName

         intSaveNameFail = False

      End If

   Loop

  

   With appWord

      .Selection.HomeKey Unit:=wdStory

      .ActiveDocument.SaveAs strSaveNamePath

      .Visible = True

      .ActiveWindow.WindowState = 0

      .Activate

   End With

  

ErrorHandlerExit:

   Set appWord = Nothing

   Exit Sub

 

ErrorHandler:

   ‘Word is not running; open Word with CreateObject

   If Err.Number = 429 Then

      Set appWord = CreateObject(“Word.Application”)

      Resume Next

   Else

      MsgBox “Error No: ” & Err.Number & “; Description: “

      Resume ErrorHandlerExit

   End If

 

End Sub

 


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.  It is accarch168.zip, which is the last entry in the table of Access Archon columns for Access Watch.



























Document Name

Document Type

Place in

Merge Recordset to Word (AA 168).mdb

Access 2000 database (can also be used in higher versions of Access)

Wherever you want

Contact Letter DP.dot

Word 97-2003 template

Word User Templates folder, or location of your choice

Customer Letter DP.dot

Word 97-2003 template

Word User Templates folder, or location of your choice

Avery 5160 Labels.dot

Word 97-2003 template

Word User Templates folder, or location of your choice

Avery 5161 Labels.dot

Word 97-2003 template

Word User Templates folder, or location of your choice

 

About this author