0
votes

I have copied a macro (credits: MailMerge Excel to Word individual files) into Excel where I can mail-merge data from Excel into Word Letter automatically and save the individual files as a pdf in the folder.

Unfortunately my PDFs do not contain any content of the Excel list after using the macro, but stick to the mail merge field name. This applies to all my created files.

Additionally, I would like to use the first line as controller, so I can decide which line is merged (e.g. with an "x" in the first line).

Can someone help me in both cases? Especially my first problem feels like a small mistake, but after hours of searching I gave up.. :-(

Thank you for your help.

 Sub RunMailMerge()

 Dim wdOutputName, wdInputName, PDFFileName As String
 Dim x As Integer
 Dim nRows As Integer

wdInputName = ThisWorkbook.Path & "\Letter.docx"
Const wdFormLetters = 0, wdOpenFormatAuto = 0
Const wdSendToNewDocument = 0, wdDefaultFirstRecord = 1, wdDefaultLastRecord = 3

'This will get you the number of records "-1" accounts for header
nRows = Sheets("Overview").Range("B" & Rows.Count).End(xlUp).Row - 1

' open the mail merge layout file
Dim wdDoc As Object

Set wdDoc = GetObject(wdInputName, "Word.document")

wdDoc.Application.Visible = False


With wdDoc.MailMerge
     .MainDocumentType = wdFormLetters
     .Destination = wdSendToNewDocument
     .SuppressBlankLines = True
      With .DataSource
        .FirstRecord = wdDefaultFirstRecord
        .LastRecord = wdDefaultLastRecord
    End With
     .Execute Pause:=False
End With

For x = 1 To nRows
  With wdDoc.MailMerge.DataSource
     .ActiveRecord = x
     If .ActiveRecord > .LastRecord Then Exit For
  End With

' show and save output file

'cells(x+1,2)references the first cells starting in row 2 and increasing by 1 row with each loop
PDFFileName = ThisWorkbook.Path & "\Letter - " & Sheets("Overview").Cells(x + 1, 2) & ".pdf"

wdDoc.Application.Visible = False
wdDoc.ExportAsFixedFormat PDFFileName, 17   ' This line saves a .pdf-version of the mail merge

Next x

' cleanup
wdDoc.Close SaveChanges:=False
Set wdDoc = Nothing

MsgBox "Your pdf('s) has now been saved!"

End Sub
1
Mmm, the suggestion in that link you give, incorporated in your code, here, makes absolutely no sense. The main merge document is merged to a new document (the Execute method), but then you go back to working with the merge document "template". And that still has the merge fields in it. There are various ways to break up a mail merge result document, the one I use is described at homepage.swissonline.ch/cindymeister/MergFram.htm under "Save each merged letter as a separate file". If that works for you I can put it in an answer, here...Cindy Meister
Hello Cindy, many thanks for your feedback. Your idea would solve my first problem regarding the individual documents, but unfortunately not that of the filter. Macropod has a perfect solution for both topics. But thank you again.MaxP

1 Answers

0
votes

By adding the following macro to your workbook, you can generate one PDF output file per mailmerge record.

Sub RunMailMerge()
'Note: A VBA Reference to the Word Object Model is required, via Tools|References
Dim wdApp As New Word.Application, wdDoc As Word.Document
Dim StrFolder As String, StrName As String, i As Long, j As Long
Dim strWorkbookName As String: strWorkbookName = ThisWorkbook.FullName
Const StrNoChr As String = """*./\:?|": StrName = "Letter.docx"
StrFolder = ThisWorkbook.Path & Application.PathSeparator
If Dir(StrFolder & strDocNm) = "" Then Exit Sub
With wdApp
  'Disable alerts to prevent an SQL prompt
  .DisplayAlerts = wdAlertsNone
  'Display Word - change this to False once the code is running correctly
  .Visible = True
  'Open the mailmerge main document - set Visible:=True for testing
  Set wdDoc = .Documents.Open(Filename:=StrFolder & StrName, ReadOnly:=True, AddToRecentFiles:=False, Visible:=False)
  With wdDoc
    With .MailMerge
      'Define the mailmerge type
      .MainDocumentType = wdFormLetters
      'Define the output
      .Destination = wdSendToNewDocument
      .SuppressBlankLines = True
      'Connect to the data source
      .OpenDataSource Name:=strWorkbookName, ReadOnly:=True, _
        LinkToSource:=False, AddToRecentFiles:=False, _
        Format:=wdOpenFormatAuto, _
        Connection:="Provider=Microsoft.ACE.OLEDB.12.0;" & _
        "User ID=Admin;Data Source=strWorkbookName;" & _
        "Mode=Read;Extended Properties=""HDR=YES;IMEX=1"";", _
        SQLStatement:="SELECT * FROM `Overview$`  WHERE `Filter` = 'x'", _
        SubType:=wdMergeSubTypeAccess
        'Process all eligible records
        For i = 1 To .DataSource.RecordCount
          With .DataSource
            .FirstRecord = i
            .LastRecord = i
            .ActiveRecord = i
            'Exit if the field to be used for the filename is empty
            If Trim(.DataFields("Name")) = "" Then Exit For
            'StrFolder = .DataFields("Folder") & Application.PathSeparator
            StrName = .DataFields("Name")
          End With
        .Execute Pause:=False
        'Clean up the filename
        For j = 1 To Len(StrNoChr)
          StrName = Replace(StrName, Mid(StrNoChr, j, 1), "_")
        Next
        StrName = "Letter - " & Trim(StrName)
        'Save as a PDF
        wdApp.ActiveDocument.SaveAs Filename:=StrFolder & StrName & ".pdf", _
          FileFormat:=wdFormatPDF, AddToRecentFiles:=False
        wdApp.ActiveDocument.Close SaveChanges:=False
      Next i
      'Disconnect from the data source
      .MainDocumentType = wdNotAMergeDocument
    End With
    'Close the mailmerge main document
    .Close False
  End With
  'Restore the Word alerts
  .DisplayAlerts = wdAlertsAll
  'Exit Word
  .Quit
End With
Set wdDoc = Nothing: Set wdApp = Nothing
End Sub

As coded, files are saved to the same folder as the mailmerge main document, using what is assumed to be the 'Name' field in the data source for the filenames (change this to suit your actual field name).

Illegal filename characters (i.e. "*./:?|) are replaced with underscores.

It's not clear what you mean by "I would like to use the first line as controller, so I can decide which line is merged". That said, if you're referring to a column with the 'x' entries, you can use a mailmerge filter to include or exclude those records. The macro assumes the field you're filtering on is named 'Filter' and you want to process those records with a lower-case 'x' against them. Change the details in the SQLStatement line to suit.

Note the comments re adding a Word library reference and re visibility in the code.