Category Archives: MS Access – Word Automation

Using VBA to List Active Processes

Because of some recent work I’ve been doing trying to embed applications within an Access form (so far I’ve managed to embed Brave, Edge, PowerShell ISE, Excel, Word, …) I’ve been working with listing the active computer processes. So I thought I’d share a few procedures I’ve developed to aid me with that task.

I tried a couple different approaches to get the process listing.

Initially, I was using the cmd:

tasklist /fo csv /nh

and although it did work, it was slow and created unnecessary lag in my process (no pun intended). Eventually I turned to my tried, tested and true friend WMI!
 
Continue reading

VBA – Forcing Applications to Close

The Headache

I’ve been experiencing issues with longstanding code that opens other Office applications (Excel, PowerPoint, Word) are not managing to close the applications even though the code used to work just fine. This is especially true of PowerPoint! So you end up with hidden processes running in the background and this can lock files and cause all sorts of headaches.

Now, I can’t say why this is now happening, when the .Quit command used to work beautifully, but I had to come up with a way to insure that I didn’t leave such processes, below is my solution.

Continue reading

MS Access – Use Word Document As Outlook E-mail Body

Once again, trying to help someone out with a question in a forum lead to me creating the following function that I thought I’d share in case it could serve others. I can’t take credit for the base code, I merely cleaned it up substantially and switched it over to using Late Binding so it is more versatile.

The idea is simple, use a word document as the body of a new Outlook e-mail. So we need to open the document, copy its content, then start a new e-mail and paste in the content. Below is the resulting code.

Continue reading

VBA – Early Binding and Late Binding

Early Binding and Late Binding

When coding using VBA, as a developer, you have a choice of either using Early Binding or Late Binding.
Below I will attempt to explain in plain English what each technique consists of and go over their Pros and Cons.
Please keep in mind the advice provided below is all relative to Early and Late Binding, nothing more.

Early Binding

Early Binding consists in setting specific Library References within your VBA Project (Tools -> References).

VBA - Tools -> References Menu

VBA - References Dialog

Benefits

The benefits of using Early Binding include:

  • The use of Intellisense
    • Say your add a reference to Excel, then you gain all the Intellisense relating to Excel (properties, Methods, …)
  • The use of constants
    • Say your add a reference to Excel, then you gain the ability to directly use Excel’s application specific constants, things like: xlSolid, xlContinuous, xlCenter, xlByRows, …
  • Use of the Object Browser
  • Help (using F1)
    • You can use F1 to quickly access help relating to any property, method, …, but this will err with Late Binding.

Drawbacks

The MAJOR (or not depending on your user’s setup) drawback to Early Binding is that it can lead to versioning issues when your program is used on multiple versions of MS Office (or whatever program you are automating). Say you develop a 2013 accdb database and set the Microsoft Excel 15.0 Object Library because you perform some Excel automation. Now if you have a user try and open the accdb in 2010, they will be presented with errors at the startup
[Pic] , and the database itself will throws seemingly random errors with code that has nothing to do with Excel to the point of being unusable.
[Pic]?

On the other hand, if a user opens the same accdb in Access 2016, Access, if a newer library is registered, will automatically upgrade the reference and as such, the database will work seamlessly.

So keeping this in mind, this is why you should always perform any development using the oldest version of the program on which your solution will be run. So if you have users running Office 2013, 2016 and 2003, you need to perform your development using Office 2003 if you are using Early Binding!

Early Binding Example

'Function to open a specified Word file
'Req'd: Reference to Microsoft Word XX.X Object Library
Function OpenWordDoc1(sFileName As String)
    Dim oApp                  As Word.Application
    Dim oDoc                  As Word.Document

    On Error Resume Next
    Set oApp = GetObject(, "Word.Application")
    If Err.Number <> 0 Then    'Word isn't running so start it
        Set oApp = CreateObject("Word.Application")
    End If
    On Error GoTo Error_Handler

    Set oDoc = oApp.Documents.Open(sFileName)
    oApp.Visible = True

Error_Handler_Exit:
    On Error Resume Next
    Set oDoc = Nothing
    Set oApp = Nothing
    Exit Function

Error_Handler:
    MsgBox "The following error has occurred." & vbCrLf & vbCrLf & _
           "Error Number: " & Err.Number & vbCrLf & _
           "Error Source: OpenWordDoc" & vbCrLf & _
           "Error Description: " & Err.Description, _
           vbCritical, "An Error has Occurred!"
    Resume Error_Handler_Exit
End Function

The above can also be re-written as follows when using Early Binding (although I always use the above approach as there have been Bugs noted when using the New … coding)

'Function to open a specified Word file
'Req'd: Reference to Microsoft Word XX.X Object Library
Function OpenWordDoc2(sFileName As String)
    Dim oApp                  As Word.Application
    Dim oDoc                  As Word.Document

    On Error Resume Next
    Set oApp = GetObject(, "Word.Application")
    If Err.Number <> 0 Then    'Word isn't running so start it
        Set oApp = New Word.Application 'CreateObject("Word.Application")
    End If
    On Error GoTo Error_Handler

    Set oDoc = oApp.Documents.Open(sFileName)
    oApp.Visible = True

Error_Handler_Exit:
    On Error Resume Next
    Set oDoc = Nothing
    Set oApp = Nothing
    Exit Function

Error_Handler:
    MsgBox "The following error has occurred." & vbCrLf & vbCrLf & _
           "Error Number: " & Err.Number & vbCrLf & _
           "Error Source: OpenWordDoc" & vbCrLf & _
           "Error Description: " & Err.Description, _
           vbCritical, "An Error has Occurred!"
    Resume Error_Handler_Exit
End Function

Late Binding (Dynamic Binding)

Late Binding on the other hand does not make use of pre-defined Libraries and hence it’s MAJOR benefit and thus does not suffer from versioning issues. Code written in Office 2016 will typically run just fine in Office 2013, 2010, …, 97 (always assuming the library is registered on the PC – You can’t perform say Excel automation if Excel isn’t installed!).

Late binding, or dynamic binding, is a computer programming mechanism in which the method being called upon an object is looked up by name at runtime.

Benefits

The key benefits of Late Binding include:

  • Does not require declaring Reference Libraries
  • Does not suffer from versioning issues

Drawbacks

The main drawbacks of Late Binding include:

  • Loss of Intellisense during development
  • No constants, so you have to declare the constants yourself when writing your code
  • Since the process is all done in real-time (dynamically binding to libraries in real-time), technically speaking, Late Binding will be slower that Early Binding. That said, with today’s computer hardware, the difference is truly not noticeable. So to me, this point is moot.

Late Binding Example

'Function to open a specified Word file
'Req'd: None
Function OpenWordDoc(sFileName As String)
Dim oApp As Object 'Word.Application
Dim oDoc As Object 'Word.Document
 
On Error Resume Next
    Set oApp = GetObject(, "Word.Application")
    If Err.Number <> 0 Then 'Word isn't running so start it
        Set oApp = CreateObject("Word.Application")
    End If
On Error GoTo Error_Handler
 
    Set oDoc = oApp.Documents.Open(sFileName)
    oApp.Visible = True
 
Error_Handler_Exit:
    On Error Resume Next
    Set oDoc = Nothing
    Set oApp = Nothing
    Exit Function
 
Error_Handler:
    MsgBox "The following error has occurred." & vbCrLf & vbCrLf & _
            "Error Number: " & Err.Number & vbCrLf & _
            "Error Source: OpenWordDoc" & vbCrLf & _
            "Error Description: " & Err.Description, _
            vbCritical, "An Error has Occurred!"
    Resume Error_Handler_Exit
End Function

The Best of Both World

Now that you understand the basic concepts and see the benefit of Early Binding (Intellisense to aid in coding) and the benefit of Late Binding (no versioning issues, thus can be distributed with much greater ease) we can explorer how we can combine both techniques to gain the best of both worlds.

Although the coding examples provided above are very simple ones, they do illustrate just how simple it is, normally, to convert between Early and Late Binding. As such, it is very easy during development to work in Early Binding to ease the coding process and then when you are ready to distribute your solution into production you simply switch to Late Binding by changing a few declarations and hard coding a few constants.

You may also wish to review Late Binding in Microsoft Access in which Tony Toews demonstrates how you can use conditional compiling instruction to accommodate both techniques within the same code

Some thoughts about all of the above

As an experienced developer I have, over time, come to truly value Late Binding for the flexibility it provides and use it in all my more recent code.

That being said, if you are a corporate developer in an organization with a very controlled environment in which you can be guaranteed that everyone is running the same versions of Office (or whatever program you are automating) then you can utilize Early Binding without any issues.

The Story Continues

Be sure to check out part 2 of this article: VBA – Early Binding and Late Binding – Part 2 in which I delve more into how to implement The Best of Both Worlds.

Resources

Using early binding and late binding in Automation
Early vs. Late Binding
Early vs. Late Binding
VBA references and early binding vs late binding

VBA – Save a Word Document as a PDF

I was asked in a forum how to print/save a word document as a PDF from within Access.

Below is a simple procedure to do exactly that using Late Binding (so no reference libraries are required)

'---------------------------------------------------------------------------------------
' Procedure : PrintWordDoc
' Author    : Daniel Pineault, CARDA Consultants Inc.
' Website   : http://www.cardaconsultants.com
' Purpose   : Print/Save a Word document as a PDF in the specified directory
' Copyright : The following may be altered and reused as you wish so long as the
'             copyright notice is left unchanged (including Author, Website and
'             Copyright).  It may not be sold/resold or reposted on other sites (links
'             back to this site are allowed).
'
' Input Variables:
' ~~~~~~~~~~~~~~~~
' sFile     : Full path, filename and extension of the word document to convert to a PDF
' sSavePath : Path where you would like the PDF saved to
'
' Usage:
' ~~~~~~
' Call PrintWordDoc("C:\Users\Dev\Documents\Test.doc", "C:\Users\Dev\Desktop\")
'
' Revision History:
' Rev       Date(yyyy/mm/dd)        Description
' **************************************************************************************
' 1         2016-02-01                  Initial Release
'---------------------------------------------------------------------------------------
Sub PrintWordDoc(sFile As String, sSavePath As String)
    Dim oApp                  As Object
    Dim oDoc                  As Object
    Dim sFileName             As String
    Dim bAppAlreadyOpen       As Boolean

    bAppAlreadyOpen = True
    'Get an instance of word to work with
    'See if Word is already running
    On Error Resume Next
    Set oApp = GetObject(, "Word.Application")
    If Err.Number <> 0 Then
        'Launch a new instance of Word
        Err.Clear
        On Error GoTo Error_Handler
        Set oApp = CreateObject("Word.Application")
        bAppAlreadyOpen = False
    End If
    'Determine the Word doc filename without the path or extension
    sFileName = Right(sFile, Len(sFile) - InStrRev(sFile, "\"))
    sFileName = Left(sFileName, InStr(sFileName, ".") - 1)
    'Ensure the path has the final \
    If Right(sSavePath, 1) <> "\" Then sSavePath = sSavePath & "\"
    'Open the document
    Set oDoc = oApp.Documents.Open(sFile)
    'Print the document as a PDF
    oDoc.ExportAsFixedFormat sSavePath & sFileName & ".pdf", 17

Error_Handler_Exit:
    On Error Resume Next
    'Close the Document
    oDoc.Close False
    Set oDoc = Nothing
    If bAppAlreadyOpen = False Then oApp.Quit
    Set oApp = Nothing
    Exit Sub

Error_Handler:
    MsgBox "The following error has occurred" & vbCrLf & vbCrLf & _
           "Error Number: " & Err.Number & vbCrLf & _
           "Error Source: PrintWordDoc" & vbCrLf & _
           "Error Description: " & Err.Description _
           , vbOKOnly + vbCritical, "An Error has Occurred!"
    Resume Error_Handler_Exit
End Sub

This procedure should work in Access, Excel, PowerPoint, …

VBA – Enumerate Fonts

Just a little twist on my code from my last post (VBA – Is a Font Installed). Should you need a listing of available fonts, why not employ so simple word automation to extract a list.

'---------------------------------------------------------------------------------------
' Procedure : EnumerateFonts
' Author    : Daniel Pineault, CARDA Consultants Inc.
' Website   : http://www.cardaconsultants.com
' Purpose   : List the available fonts on the system
' Copyright : The following may be altered and reused as you wish so long as the
'             copyright notice is left unchanged (including Author, Website and
'             Copyright).  It may not be sold/resold or reposted on other sites (links
'             back to this site are allowed).
'
' Usage:
' ~~~~~~
' Call EnumerateFonts
'
' Revision History:
' Rev       Date(yyyy/mm/dd)        Description
' **************************************************************************************
' 1         2015-10-15              Initial Release
'---------------------------------------------------------------------------------------
Public Function EnumerateFonts()
    On Error GoTo Error_Handler
    Dim oWord                 As Object
    Dim i                     As Long

    Set oWord = CreateObject("Word.Application")
    For i = 1 To oWord.FontNames.Count
        Debug.Print oWord.FontNames(i)
    Next i

Error_Handler_Exit:
    On Error Resume Next
    oWord.Quit
    Set oWord = Nothing
    Exit Function

Error_Handler:
    MsgBox "The following error has occurred." & vbCrLf & vbCrLf & _
           "Error Number: " & Err.Number & vbCrLf & _
           "Error Source: EnumerateFonts" & vbCrLf & _
           "Error Description: " & Err.Description, _
           vbCritical, "An Error has Occurred!"
    Resume Error_Handler_Exit
End Function

MS Access – VBA – Find A String In Word Document

I recent was asked the following question in an UtterAccess forum and thought the solution could be useful to someone else down the line.

I have an access database with hyperlinks to many protected word documents (write protection only).
The target is : user enters a search string in access and selects specific protected document.

In the thread I developed 2 possible solutions: (1) Open the document and highlight the search term throughout the document, (2) Open the document and the start the Find dialog and allow the user the control of what they do from that point on.
 

Find and Highlight Occurrances of a Term

One option is to open the document and highlight the search term throughout the document and you can do this by using code like:

'---------------------------------------------------------------------------------------
' Procedure : OpenWordDocAndSearch
' Author    : Daniel Pineault, CARDA Consultants Inc.
' Website   : http://www.cardaconsultants.com
' Purpose   : Open the document and highlight the search term throughout the document
' Copyright : The following is release as Attribution-ShareAlike 4.0 International
'             (CC BY-SA 4.0) - https://creativecommons.org/licenses/by-sa/4.0/
'
' Input Variables:
' ~~~~~~~~~~~~~~~~
' sFileName     : Fully qualified path and filename with extension of the word document
'                 to search through
' sSearchString : The search term to look for
'
' Usage:
' ~~~~~~
' OpenWordDocAndSearch "c:\demo\Test.docx", "The"
'
' Revision History:
' Rev       Date(yyyy/mm/dd)        Description
' **************************************************************************************
' 1         2013-05-15              Initial Release
' 2         2023-10-02              Fix name of function in error handler
'---------------------------------------------------------------------------------------
Function OpenWordDocAndSearch(sFileName As String, sSearchString As String)
    On Error GoTo Error_Handler
    Dim oApp            As Object
    Dim oDoc            As Object
    Const wdYellow = 7

    On Error Resume Next
    Set oApp = GetObject(, "Word.Application")
    If Err.Number <> 0 Then    'Word isn't running so start it
        Set oApp = CreateObject("Word.Application")
    End If
    On Error GoTo 0

    Set oDoc = oApp.Documents.Open(sFileName)
    oApp.Visible = True
    oDoc.Content.Find.HitHighlight FindText:=sSearchString

Error_Handler_Exit:
    On Error Resume Next
    Set oDoc = Nothing
    Set oApp = Nothing
    Exit Function

Error_Handler:
    MsgBox "The following error has occurred." & vbCrLf & vbCrLf & _
           "Error Number: " & Err.Number & vbCrLf & _
           "Error Source: OpenWordDocAndSearch" & vbCrLf & _
           "Error Description: " & Err.Description, _
           vbCritical, "An Error has Occurred!"
    Resume Error_Handler_Exit
End Function

 

Use the Find Dialog

Another option is to open the document and then start the Edit/Find dialog and allow the user the control of what they do from that point on. To do so, we can use a function like:

'---------------------------------------------------------------------------------------
' Procedure : OpenWordDocAndSearch
' Author    : Daniel Pineault, CARDA Consultants Inc.
' Website   : http://www.cardaconsultants.com
' Purpose   : Open the document and the start the Find dialog and allow the user the
'             control of what they do from that point on
' Copyright : The following is release as Attribution-ShareAlike 4.0 International
'             (CC BY-SA 4.0) - https://creativecommons.org/licenses/by-sa/4.0/
'
' Input Variables:
' ~~~~~~~~~~~~~~~~
' sFileName     : Fully qualified path and filename with extension of the word document
'                 to search through
' sSearchString : The search term to look for
'
' Usage:
' ~~~~~~
' OpenWordDocAndSearchDialog "c:\demo\Test.docx", "The"
'
' Revision History:
' Rev       Date(yyyy/mm/dd)        Description
' **************************************************************************************
' 1         2013-05-15              Initial Release
' 2         2023-10-02              Updated Function name to avoid conflict
'---------------------------------------------------------------------------------------
Function OpenWordDocAndSearchDialog(sFileName As String, sSearchString As String)
    On Error GoTo Error_Handler
    Dim oApp            As Object
    Dim oDoc            As Object
    Dim dlgFind         As Object
    Const wdDialogEditFind = 112

    On Error Resume Next
    Set oApp = GetObject(, "Word.Application")
    If Err.Number <> 0 Then    'Word isn't running so start it
        Set oApp = CreateObject("Word.Application")
    End If
    On Error GoTo 0

    Set oDoc = oApp.Documents.Open(sFileName)
    oApp.Visible = True
    Set dlgFind = oApp.Dialogs(wdDialogEditFind)
    With dlgFind
        .Find = sSearchString
        .Show
    End With

Error_Handler_Exit:
    On Error Resume Next
    Set dlgFind = Nothing
    Set oDoc = Nothing
    Set oApp = Nothing
    Exit Function

Error_Handler:
    MsgBox "The following error has occurred." & vbCrLf & vbCrLf & _
           "Error Number: " & Err.Number & vbCrLf & _
           "Error Source: OpenWordDocAndSearchDialog" & vbCrLf & _
           "Error Description: " & Err.Description, _
           vbCritical, "An Error has Occurred!"
    Resume Error_Handler_Exit
End Function

MS Access Sample- Export Data to Excel and/or Word

Over the years, I have answered numerous questions regarding how to export a records, or records to either MS Excel or MS Word. I already have 2 posts on the subject:

but thought a concrete example would help illustrate things even further.

Here are a few screenshots of the sample.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Now in this sample I am covering Excel and Word automation, not built-in commands, such as:

  • DoCmd.TransferSpreadsheet
  • DoCmd.TransferText
  • DoCmd.OutputTo
  • DoCmd.RunCommand acCmdExportRTF

These are well documented, and plenty of examples can be found online.  Instead, I concentrate on demonstrating a few possible ways to export using late binding and word and excel automation, permitting much more control on the final product (font, colors, layout, page orientation and so much more) and no need for any external reference libraries.

Note: for this sample to work, all the supporting files (excel and word) must be in the same folder as the database itself (although this very easy to change in the VBA code provided).

Fill In Excel Or Word Access Demo

MS Access – VBA – Convert Excel XLS to CSV

I was asked in a support forum how to convert an Excel *.xls, *.xlsx file to *.csv format. I didn’t readily have an answer so I created a custom function to help the user out. So here are the fruits on my labors should it help someone else out. What is also nice about the way it is written, is that it will run in any MS Office application (MS Access, MS Word, MS PowerPoint, MS Outlook, …) without requiring any modifications (copy & paste, that’s it)!

'---------------------------------------------------------------------------------------
' Procedure : ConvertXls2CSV
' Author    : Daniel Pineault, CARDA Consultants Inc.
' Website   : http://www.cardaconsultants.com
' Purpose   : Converts a standard Excel file to csv format
' Requirements: Requires MS Excel be installed
'               Uses late binding, so no libraries need be declared
' Copyright : The following may be altered and reused as you wish so long as the
'             copyright notice is left unchanged (including Author, Website and
'             Copyright).  It may not be sold/resold or reposted on other sites (links
'             back to this site are allowed).
'
' Input Variables:
' ~~~~~~~~~~~~~~~~
' sXlsFile  : Fully qualified path and filename with extension of the Excel workbook
'
' Usage:
' ~~~~~~
' ConvertXls2CSV "C:\Users\Daniel\Desktop\Contact_E-mail listing.xls"
'       Will output a file C:\Users\Daniel\Desktop\Contact_E-mail listing.csv
'
' Revision History:
' Rev       Date(yyyy/mm/dd)        Description
' **************************************************************************************
' 1         2012-May-11             Initial Release - Answer to forum question
'---------------------------------------------------------------------------------------
Function ConvertXls2CSV(sXlsFile As String)
    On Error Resume Next
    Dim oExcel          As Object
    Dim oExcelWrkBk     As Object
    Dim bExcelOpened    As Boolean    'Was Excel already open or not
    'Review 'XlFileFormat Enumeration' for more formats
    Const xlCSVWindows = 23 'Windows CSV Format
    Const xlCSV = 6 'CSV
    Const xlCSVMac = 22 'Macintosh CSV
    Const xlCSVMSDOS = 24 'MSDOS CSV

    Set oExcel = GetObject(, "Excel.Application")    'Bind to existing instance of Excel

    If Err.Number <> 0 Then    'Could not get instance of Excel, so create a new one
        Err.Clear
        On Error GoTo Error_Handler
        Set oExcel = CreateObject("excel.application")
        bExcelOpened = False
    Else    'Excel was already running
        bExcelOpened = True
    End If

    On Error GoTo Error_Handler
    oExcel.ScreenUpdating = False
    oExcel.Visible = False   'Keep Excel hidden from the user
    oExcel.Application.DisplayAlerts = False

    Set oExcelWrkBk = oExcel.Workbooks.Open(sXlsFile)
    'Note: you may wish to change the file format constant for another type declared
    '      above based on your usage/needs in the following line.
    oExcelWrkBk.SaveAs Left(sXlsFile, InStrRev(sXlsFile, ".")) & "csv", xlCSVWindows
    oExcelWrkBk.Close False

    If bExcelOpened = False Then
        oExcel.Quit
    End If

Error_Handler_Exit:
    On Error Resume Next
    Set oExcelWrkBk = Nothing
    Set oExcel = Nothing
    Exit Function

Error_Handler:
    MsgBox "The following error has occurred." & vbCrLf & vbCrLf & _
            "Error Number: " & Err.Number & vbCrLf & _
            "Error Source: ConvertXls2CSV" & vbCrLf & _
            "Error Description: " & Err.Description, _
            vbCritical, "An Error has Occurred!"
    Resume Error_Handler_Exit
End Function

Now this could be further improved by extending the error handling further to trap specific errors such as 1004 – file not found, etc… but it definitely illustrates the basic principle in using late binding to utilize Excel to open the file and convert it to *.csv format.

I hope this helps.

MS Access – VBA – Export Records to MS Word

Similarily to my post regarding exporting records to MS Excel, below is some sample code that illustrates how one can export data into a new Word document (in a table structure). The code determines the necessary rows and columns based on the table or query passed to it and then does the rest. You can easily from this simple example get into formatting fonts, etc…

'---------------------------------------------------------------------------------------
' Procedure : Export2DOC
' Author    : Daniel Pineault, CARDA Consultants Inc.
' Website   : http://www.cardaconsultants.com
' Purpose   : Export a recordset to a MS Word table in a new document
' Note      : Overwrites file if it already exists without any warning, so you may wish
'               to add a check prior to calling this function
' Copyright : The following is release as Attribution-ShareAlike 4.0 International
'             (CC BY-SA 4.0) - https://creativecommons.org/licenses/by-sa/4.0/
' Req'd Refs: Uses Late Binding, none required
'
' Input Variables:
' ~~~~~~~~~~~~~~~~
' sQuery        : Name of the Table or Query to Export the data from
' sFileName     : Path and Filename to save the Word Document as
' bOpenDocument : Leave the document open to the users or not (close after generating)
'
' Usage:
' ~~~~~~
' Export2DOC "Contacts", "C:\Temp\testing01.docx"
' Export2DOC "IncomingOrders", "C:\Temp\orders.docx", True
'
' Revision History:
' Rev       Date(yyyy/mm/dd)        Description
' **************************************************************************************
' 1         2012-Apr-23             Initial Release
' 2         2020-04-08              Updated proc header
'                                   Added sFileName and bOpenDocument arguments
'                                   Added PageSetup.Orientation to proc
'                                   Fixed a bug in the table row count
'                                   Updated and expanded the error handler
'---------------------------------------------------------------------------------------
Function Export2DOC(sQuery As String, _
                    sFileName As String, _
                    Optional bOpenDocument As Boolean = False)
    Dim oWord                 As Object
    Dim oWordDoc              As Object
    Dim oWordTbl              As Object
    Dim bWordOpened           As Boolean
    Dim db                    As DAO.Database
    Dim rs                    As DAO.Recordset
    Dim iCols                 As Integer
    Dim iRecCount             As Integer
    Dim iFldCount             As Integer
    Dim i                     As Integer
    Dim j                     As Integer
    Const wdPrintView = 3
    Const wdWord9TableBehavior = 1
    Const wdAutoFitFixed = 0
    '    Const wdOrientPortrait = 0
    Const wdOrientLandscape = 1

    'Start Word
    On Error Resume Next
    Set oWord = GetObject("Word.Application")    'Bind to existing instance of Word

    If Err.Number <> 0 Then    'Could not get instance of Word, so create a new one
        Err.Clear
        On Error GoTo Error_Handler
        Set oWord = CreateObject("Word.application")
        bWordOpened = False
    Else    'Word was already running
        bWordOpened = True
    End If
    On Error GoTo Error_Handler
    oWord.Visible = False   'Keep Word hidden until we are done with our manipulation
    Set oWordDoc = oWord.Documents.Add   'Start a new document
    'Not strictly necessary, but for larger tables switching to Landscape can be very beneficial!
    '   so the next line demonstrates how that can easily be done
    oWordDoc.PageSetup.Orientation = wdOrientLandscape

    'Open our SQL Statement, Table, Query
    Set db = CurrentDb
    Set rs = db.OpenRecordset(sQuery, dbOpenSnapshot)
    With rs
        If .RecordCount <> 0 Then
            .MoveLast   'Ensure proper count
            iRecCount = .RecordCount    'Number of records returned by the table/query
            .MoveFirst
            iFldCount = .Fields.Count   'Number of fields/columns returned by the table/query

            'Switch to print preview mode (not req'd just a personal preference)
            oWord.ActiveWindow.View.Type = wdPrintView
            'Create the basic table
            oWord.ActiveDocument.Tables.Add oWord.selection.Range, _
                                            iRecCount + 1, _
                                            iFldCount, _
                                            wdWord9TableBehavior, _
                                            wdAutoFitFixed

            Set oWordTbl = oWordDoc.Tables(1)
            'Build our Header Row
            For i = 0 To iFldCount - 1
                oWordTbl.Cell(1, i + 1) = rs.Fields(i).Name
            Next i
            'Build our data rows
            For i = 1 To iRecCount
                For j = 0 To iFldCount - 1
                    oWordTbl.Cell(i + 1, j + 1) = Nz(rs.Fields(j).Value, "")
                Next j
                .MoveNext
            Next i
        Else
            MsgBox "There are no records returned by the specified queries/SQL statement.", _
                   vbCritical + vbOKOnly, "No data to generate an Word spreadsheet with"
            GoTo Error_Handler_Exit
        End If
    End With

    oWordDoc.SaveAs (sFileName)   'Save and close
    If bOpenDocument = False Then
        oWordDoc.Close

        '    Close Word if is wasn't originally running
        If bWordOpened = False Then
            oWord.Quit
        End If
    End If

Error_Handler_Exit:
    On Error Resume Next
    rs.Close
    Set rs = Nothing
    Set db = Nothing
    oWord.Visible = True   'Make Word visible to the user
    Set oWordTbl = Nothing
    Set oWordDoc = Nothing
    Set oWord = Nothing
    Exit Function

Error_Handler:
    If Err.Number = 5148 Then
        MsgBox "Your Table/Query contains a total of " & iFldCount & " fields/columns, but Word tables can only support a maximum of 63.  " & _
               "Please change your Table/Query to only supply a maximum of 63 fields/columns and try again.", _
               vbCritical Or vbOKOnly, "Operation Aborted"
    Else
        MsgBox "The following error has occurred" & vbCrLf & vbCrLf & _
               "Error Number: " & Err.Number & vbCrLf & _
               "Error Source: Export2DOC" & vbCrLf & _
               "Error Description: " & Err.Description & _
               Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
               , vbOKOnly + vbCritical, "An Error has Occurred!"
    End If
    Resume Error_Handler_Exit
End Function

You may also wish to review my MS Access Sample- Export Data to Excel and/or Word.