Слияние почты, начатое VBA в Access, позволило Word снова открыть базу данных - PullRequest
4 голосов
/ 11 октября 2010

Я работаю над базой данных Access, которая генерирует несколько писем с объединением писем, вызываемых из кода VBA в базе данных Access. Проблема в том, что если я открою новый документ Word и начну слияние почты (VBA), Word откроет ту же базу данных Access (которая уже открыта) для получения данных. Есть ли способ предотвратить это? Чтобы использовался уже открытый экземпляр базы данных?

После некоторого тестирования я получаю странное поведение: если я открываю базу данных Access, удерживая клавишу SHIFT, слияние почты не открывает другой экземпляр Access той же базы данных. Если я открываю базу данных Access, не удерживая клавишу, я получаю описанное поведение.

Код VBA слияния моей почты:

On Error GoTo ErrorHandler

    Dim word As word.Application
    Dim Form As word.Document

    Set word = CreateObject("Word.Application")
    Set Form = word.Documents.Open("tpl.doc")

    With word
        word.Visible = True

        With .ActiveDocument.MailMerge
            .MainDocumentType = wdMailingLabels
            .OpenDataSource Name:= CurrentProject.FullName, ConfirmConversions:=False, _
                ReadOnly:=False, LinkToSource:=False, AddToRecentFiles:=False, _
                PasswordDocument:="", PasswordTemplate:="", WritePasswordDocument:="", _
                WritePasswordTemplate:="", Revert:=False, Format:=wdOpenFormatAuto, _
                SQLStatement:="[MY QUERY]", _
                SQLStatement1:="", _
                SubType:=wdMergeSubTypeWord2000, OpenExclusive:=False
            .Destination = wdSendToNewDocument
            .Execute
            .MainDocumentType = wdNotAMergeDocument
        End With
    End With

    Form.Close False
    Set Form = Nothing

    Set word = Nothing

Exit_Error:
    Exit Sub
ErrorHandler:
    word.Quit (False)
    Set word = Nothing
    ' ...
End Sub

Все это делается с помощью Access / Word 2003.

Обновление № 1 Также было бы полезно, если бы кто-то мог сказать мне, в чем точная разница между открытием Access с помощью клавиши SHIFT или без нее. И если можно написать некоторый код VBA для включения «функций», то есть, если база данных открыта без клавиши SHIFT, она как минимум «имитирует» ее.

Cheers, Грегор

1 Ответ

8 голосов
/ 11 октября 2010

Когда я делаю почтовые слияния, я обычно экспортирую файл .txt из Access, а затем устанавливаю для него источник данных слияния. Таким образом, Access участвует только в экспорте запроса и последующем указании документу Word выполнить автоматизацию, примерно так:

    Public Function MailMergeLetters() 
           Dim pathMergeTemplate As String
            Dim sql As String
            Dim sqlWhere As String
            Dim sqlOrderBy As String


'Get the word template from the Letters folder  

            pathMergeTemplate = "C:\MyApp\Resources\Letters\"

'This is a sort of "base" query that holds all the mailmerge fields
'Ie, it defines what fields will be merged.

            sql = "SELECT * FROM MailMergeExportQry" 

            With Forms("MyContactsForm")

' Filter and order the records you want
'Very much to do for you

            sqlWhere = GetWhereClause()
            sqlOrderBy = GetOrderByClause()

            End With

' Build the sql string you will use with this mail merge

            sql = sql & sqlWhere & sqlOrderBy & ";"

'Create a temporary QueryDef to hold the query

                Dim qd As DAO.QueryDef
                Set qd = New DAO.QueryDef
                    qd.sql = sql
                    qd.Name = "mmexport"

                    CurrentDb.QueryDefs.Append qd

' Export the data using TransferText

                        DoCmd.TransferText _
                            acExportDelim, , _
                            "mmexport", _
                            pathMergeTemplate & "qryMailMerge.txt", _
                            True
' Clear up
                    CurrentDb.QueryDefs.Delete "mmexport"

                    qd.Close
                Set qd = Nothing

'------------------------------------------------------------------------------
'End Code Block:
'------------------------------------------------------------------------------
'------------------------------------------------------------------------------
'Start Code Block:
'OK. Access has built the .txt file.
'Now the Mail merge doc gets opened...
'------------------------------------------------------------------------------

                Dim appWord As Object
                Dim docWord As Object

                Set appWord = CreateObject("Word.Application")

                    appWord.Application.Visible = True

' Open the template in the Resources\Letters folder:

                    Set docWord = appWord.Documents.Add(Template:=pathMergeTemplate & "MergeLetters.dot")

'Now I can mail merge without involving currentproject of my Access app

                        docWord.MailMerge.OpenDataSource Name:=pathMergeTemplate & "qryMailMerge.txt", LinkToSource:=False

                    Set docWord = Nothing

                Set appWord = Nothing

'------------------------------------------------------------------------------
'End Code Block:
'------------------------------------------------------------------------------

        Finally:
            Exit Function

        Hell:
            MsgBox Err.Description & " " & Err.Number, vbExclamation, APPHELP

        On Error Resume Next
            CurrentDb.QueryDefs.Delete "mmexport"

            qd.Close
            Set qd = Nothing

            Set docWord = Nothing
            Set appWord = Nothing

            Resume Finally

        End Function

Чтобы использовать это, вам нужно настроить подпапку Resources \ Letters и поместить туда файл слова шаблона mailmerge. Вам также нужен ваш «базовый» запрос с определениями полей в приложении Access (в данном примере он называется MailMergeExportQry. Но вы можете назвать его как угодно.

Вам также необходимо выяснить, какую фильтрацию и сортировку вы будете выполнять. В примере это представлено

sqlWhere = GetWhereClause()
sqlOrderBy = GetOrderByClause

Как только вы разберетесь с этими вещами, это будет многократно использоваться.

...