Complext Mail Merge with VBA
Hello,
I'm trying to realize a complex Word mail merge with VBA.
GOAL
I've got a data source that needs to be grouped.
Let's say I've got a list of orders need to be grouped by the customer ID
who made them.
Imagine my data source has a structure like this:
- customerID
- customer description
- customer address
- orderID
- order description
- order total amount
Every customerID can have one to many orders contiguous records,
each record with the same structure described above.
The merge should produce a letter like this for each customer:
- un introductory header with customer personal information (description and
address)
- a table listing every customer's order
- a greeting footer
- a fill-in pre-compiled form. I'd need a form for each customer's order.
- a fill-in blank courtesy form
SOLUTION
First I tried to solve my problem with Microsoft KB
(http://support.microsoft.com/default.aspx/kb/294686), but
It didn't help since I need to put data source details after customer footer.
I then decided to write application event procedures.
I created 6 Word document:
- docMain containing the VBA code
- docA containg customer's header
- docB contains orders' list
- docC containing customer footer
- docD containing fill-in pre-compiled form
- docE containing fill-in blank courtesy form
Every document is a mail merge document connected with the same data source.
docMain contains 2 class modules:
- MergeApplication that models the behaviour of docMain merge
- SubMergeApplication that models the behaviour of subdocuments(docA, docB,
docC, docD and docE) merge
When docMain opens, the merge events is fired and the control of merging is
given to MergeApplication.
The BeforeRecordMerge event of MergeApplication detect which is the active
record and the changing of customer ID
to fire the right subdocument merge. After each subdocument merge, the sub
merged file is pasted and copied
into the main document.
The code is shown below:
' save the customerId to detect when the Id changes
rottura1 = arrangeRottura(doc, ThisDocument.strFieldsRottura)
' checks active record is the data source first
If (doc.MailMerge.DataSource.activeRecord = 1) Then
' MERGE DOCUMENTO A
Set subdoc = Documents.Open(ThisDocument.docA)
mergeAndCopy subdoc, doc, activeRecord, activeRecord
mainMergedDoc.Activate
' MERGE DOCUMENTO B
Set subdoc = Documents.Open(ThisDocument.docB)
mergeAndCopy subdoc, doc, activeRecord, activeRecord
mainMergedDoc.Activate
recordDa = activeRecord
Else
' checks customerID is changed
If (rottura1 <> rottura2) Then
' MERGE DOCUMENTO C
Set subdoc = Documents.Open(ThisDocument.docC)
mergeAndCopy subdoc, doc, activeRecord, activeRecord
mainMergedDoc.Activate
Selection.InsertBreak Type:=wdPageBreak
Selection.Collapse direction:=wdCollapseEnd
recordA = activeRecord - 1
' MERGE DOCUMENTO D
Set subdoc = Documents.Open(ThisDocument.docD)
mergeAndCopy subdoc, doc, recordDa, recordA
mainMergedDoc.Activate
recordDa = activeRecord
' MERGE DOCUMENTO E
Set subdoc = Documents.Open(ThisDocument.docE)
mergeAndCopy subdoc, doc, activeRecord, activeRecord
mainMergedDoc.Activate
' fine documento singolo con interruzione sezione
Selection.InsertBreak Type:=wdSectionBreakNextPage
Selection.Collapse direction:=wdCollapseEnd
' MERGE DOCUMENTO A
Set subdoc = Documents.Open(ThisDocument.docA)
mergeAndCopy subdoc, doc, activeRecord, activeRecord
mainMergedDoc.Activate
' MERGE DOCUMENTO B
Set subdoc = Documents.Open(ThisDocument.docB)
mergeAndCopy subdoc, doc, activeRecord, activeRecord
mainMergedDoc.Activate
Else
' MERGE DOCUMENTO B
Set subdoc = Documents.Open(ThisDocument.docB)
mergeAndCopy subdoc, doc, activeRecord, activeRecord
mainMergedDoc.Activate
End If
End If
' checks active record is the last
If (doc.MailMerge.DataSource.activeRecord = ThisDocument.totMMRecord) Then
' MERGE DOCUMENTO C
Set subdoc = Documents.Open(ThisDocument.docC)
mergeAndCopy subdoc, doc, activeRecord, activeRecord
mainMergedDoc.Activate
Selection.InsertBreak Type:=wdPageBreak
Selection.Collapse direction:=wdCollapseEnd
recordA = doc.MailMerge.DataSource.activeRecord
' MERGE DOCUMENTO D
Set subdoc = Documents.Open(ThisDocument.docD)
mergeAndCopy subdoc, doc, recordDa, recordA
mainMergedDoc.Activate
' MERGE DOCUMENTO E
Set subdoc = Documents.Open(ThisDocument.docE)
mergeAndCopy subdoc, doc, activeRecord, activeRecord
mainMergedDoc.Activate
doc.MailMerge.DataSource.activeRecord = wdLastDataSourceRecord
End If
' save the customerId to detect when the Id changes
rottura2 = arrangeRottura(doc, ThisDocument.strFieldsRottura)
I develop my solution on Word 2002 and everything worked fine.
I then switched to Word 2003 and 2007 and my merge seems not to move from
the first data source record.
It seems like the two nested merge interfere with each other.
I hope I was able to explain the problem clearly enough.
Thanks in advace for help.
Francesca Arecco
date: Fri, 8 Feb 2008 08:26:09 -0800
author: fiensi