Re: Automation of a mail merge in access 2003
- From: "Geoff" <geoff@xxxxxxxxxx>
- Date: Fri, 23 Jun 2006 12:36:15 +0100
In trying to bullet-proof this code, I have discovered that the
OpenDataSource method is essential for Access 2002, but not for Access 2000.
As your code didn't call the OpenDataSource method, perhaps that was the
source of error 4605 when the school upgraded.
Well, here is my attempt to make the code blast-proof!
Good luck with your project!
Geoff
Option Compare Database
Option Explicit
' This declaration is not essential, but may be good to tidy the
' screen. In the general declarations section at the top of the
' module, declare the Windows API function SetForegroundWindow&.
' We can call this function to set the focus on the Microsoft
' Access window after the CreateObject function activates
' Microsoft Word (assumes Method 2 below is used to start Word):
Declare Function SetForegroundWindow& Lib "user32" _
(ByVal hwnd As Long)
' For displaying messages:
Private mMsg As gMsg
Private Type gMsg
Message As String
Buttons As VbMsgBoxStyle
Heading As String
RetVal As VbMsgBoxResult
End Type
Public Sub RunMailMerge()
Const MY_QUERY_NAME As String = "MyTempQuery"
Const MY_DATASOURCE As String = "Data.rtf"
Dim objDB As DAO.Database
Dim objQDF As DAO.QueryDef
Dim objRS As DAO.Recordset
Dim objWORD As Word.Application
Dim objWDMAL As Word.Document
Dim objMERGEDDOC As Word.Document
Dim strSQL As String
Dim strPath As String
Dim strMainPathName As String
Dim strDataPathName As String
Dim strFilnavn As String
On Error GoTo ErrorHandler
' ...Your code here to create strSQL and set strFilnavn...
' Get path to working directory:
strPath = Access.Application.CurrentProject.Path
If Right(strPath, 1) <> "\" Then strPath = strPath & "\"
' Initialise path\names:
strMainPathName = strPath & strFilnavn & ".dot"
strDataPathName = strPath & MY_DATASOURCE
' Ensure that the main document exists:
If Not FileExists(strMainPathName) Then
GoTo Exit_MainDocNotFound
End If
' Ensure that the data document is deleted:
If FileExists(strDataPathName) Then Kill strDataPathName
' Point to current database:
Set objDB = CurrentDb()
' Ensure that temporary query does not exist:
GoSub DeleteTemporaryQuery
' Recreate temporary query:
Set objQDF = objDB.CreateQueryDef(MY_QUERY_NAME, strSQL)
objDB.QueryDefs.Refresh
Access.Application.RefreshDatabaseWindow
' Create DAO recordset using query:
Set objRS = objQDF.OpenRecordset()
' Exit if query returns no records:
If objRS.BOF And objRS.EOF Then
GoTo Exit_NoRecordsToMerge
End If
' Output data from query:
DoCmd.OutputTo acOutputQuery, MY_QUERY_NAME, _
acFormatRTF, strDataPathName
' Exit if new data file does not exist:
If Not FileExists(strDataPathName) Then
GoTo Exit_NewDataDocNotFound
End If
' Open Microsoft Word using Method 1 or 2:
' Method 1
' This method maybe essential for Word 2003:
Set objWORD = New Word.Application
' Method 2
' You may prefer this method for versions of
' Word before Word 2003. This method may not
' work for Word 2003:
' On Error Resume Next
' Set objWORD = GetObject(, "Word.Application")
' If Err.Number <> 0 Then
' ' The CreateObject function makes Word active.
' ' If you don't like this,
' Set objWORD = CreateObject("Word.Application")
' End If
' On Error GoTo ErrorHandler
' It's faster to use the "With...End With" construct
' when calling out-of-process Automation servers,
' like Word.
' Set up Word:
With objWORD
' Make word visible now in case Word displays
' a dialog that suspends this code:
.Visible = True
' Maximize the Word window:
.WindowState = wdWindowStateMaximize
' Open main template in Word:
Set objWDMAL = .Documents.Add(strMainPathName)
End With
' Set up main document:
With objWDMAL
' Maximize the document window within Word:
.ActiveWindow.WindowState = wdWindowStateMaximize
' Set other options:
.ShowGrammaticalErrors = True
.ShowSpellingErrors = True
End With
' Set up mail merge for main document:
With objWDMAL.MailMerge
' Attach main document to RTF file
' (required for Access 2002):
.OpenDataSource strDataPathName
' Exit if Main document and Datasource not
' able to perform merge:
If .State <> wdMainAndDataSource Then
GoTo Exit_DataSourceNotAttached
End If
' Set up Datasource:
With .DataSource
.FirstRecord = wdDefaultFirstRecord
.LastRecord = wdDefaultLastRecord
End With
' Set mailmerge options:
.Destination = wdSendToNewDocument
.SuppressBlankLines = True
.MainDocumentType = wdFormLetters
' Check mailmerge state before executing merge:
If .State = wdMainAndDataSource Then
.Execute False
Else
GoTo Exit_CannotExecuteMerge
End If
End With
' Set reference to new merged document:
Set objMERGEDDOC = objWORD.ActiveDocument
' Set options for merged document:
With objMERGEDDOC
.ActiveWindow.WindowState = wdWindowStateMaximize
.Activate
.ShowGrammaticalErrors = True
.ShowSpellingErrors = True
End With
' Close main document:
objWDMAL.Close wdDoNotSaveChanges
' Activate Access
' (The CreateObject function will have activated Word
' if Method 2 above was used to start Word).
' The next code line calls the Windows API function
' declared at the top of this module:
SetForegroundWindow& Access.Application.hWndAccessApp
' Show final message:
mMsg.Message = "Mail merge finished."
mMsg.Buttons = vbOKOnly + vbExclamation
mMsg.Heading = "Program Finished" & Space(30)
ShowMessage
' The user may have closed Word by now,
' so ignore (objWord) server errors:
On Error Resume Next
' Show Word:
' Use Visible = False/True to make Word wake up!
' Otherwise, Word remains "frozen" on my system.
objWORD.Visible = False
objWORD.Visible = True
objWORD.Activate
Bye:
' The user may have got here from the ErrorHandler,
' so ensure we finish:
On Error Resume Next
' Delete temporary query:
GoSub DeleteTemporaryQuery
' Delete data document:
If FileExists(strDataPathName) Then Kill strDataPathName
Set objMERGEDDOC = Nothing
Set objWDMAL = Nothing
Set objWORD = Nothing
Set objRS = Nothing
Set objQDF = Nothing
Set objDB = Nothing
Exit Sub
DeleteTemporaryQuery:
For Each objQDF In objDB.QueryDefs
If objQDF.Name = MY_QUERY_NAME Then
objDB.QueryDefs.Delete MY_QUERY_NAME
objDB.QueryDefs.Refresh
Access.Application.RefreshDatabaseWindow
Exit For
End If
Next
Return
Exit_MainDocNotFound:
mMsg.Message = strMainPathName & vbNewLine & vbNewLine _
& "The above main mail merge document was not found." _
& "Mail merge cancelled."
mMsg.Buttons = vbOKOnly + vbExclamation
mMsg.Heading = "Program Terminated"
ShowMessage
GoTo Bye
Exit_NoRecordsToMerge:
mMsg.Message = "There are no records to merge " _
& "at the present time."
mMsg.Buttons = vbOKOnly + vbInformation
mMsg.Heading = "Program Finished"
ShowMessage
GoTo Bye
Exit_NewDataDocNotFound:
mMsg.Message = strDataPathName & vbNewLine & vbNewLine _
& "The above data file was not found."
mMsg.Buttons = vbOKOnly + vbExclamation
mMsg.Heading = "Program Terminated"
ShowMessage
GoTo Bye
Exit_DataSourceNotAttached:
mMsg.Message = "Data source not attached. " _
& "Mail merge cancelled."
mMsg.Buttons = vbExclamation + vbOKOnly
mMsg.Heading = "Program Terminated"
ShowMessage
GoTo Bye
Exit_CannotExecuteMerge:
mMsg.Message = "Cannot execute mail merge."
mMsg.Buttons = vbOKOnly + vbExclamation
mMsg.Heading = "Program Terminated"
ShowMessage
GoTo Bye
ErrorHandler:
mMsg.Message = "Error Number: " & Err.Number _
& vbNewLine & vbNewLine _
& Err.Description
mMsg.Buttons = vbExclamation + vbOKOnly
mMsg.Heading = "Error"
ShowMessage
GoTo Bye
End Sub
Private Function FileExists(PathName As String) As Boolean
FileExists = (Len(Dir(PathName)) > 0)
End Function
Private Sub ShowMessage()
mMsg.RetVal = MsgBox(mMsg.Message, mMsg.Buttons, mMsg.Heading)
End Sub
.
- References:
- Re: Automation of a mail merge in access 2003
- From: Geoff
- Re: Automation of a mail merge in access 2003
- From: Geoff
- Re: Automation of a mail merge in access 2003
- From: IndianaJonas
- Re: Automation of a mail merge in access 2003
- From: Geoff
- Re: Automation of a mail merge in access 2003
- From: Geoff
- Re: Automation of a mail merge in access 2003
- From: Geoff
- Re: Automation of a mail merge in access 2003
- Prev by Date: Re: Automatic Form Letters
- Next by Date: Re: Sorting by date in a report
- Previous by thread: Re: Automation of a mail merge in access 2003
- Next by thread: Re: Word Mail Merge Custom Template
- Index(es):