How to use multiple documents as data sources for mail merge in a Word document?
Syncfusion DocIO is a .NET Core Word library used to create, read, and edit Word documents programmatically without Microsoft Word or interop dependencies. Using this library, you can use multiple documents as data sources for mail merge in a Word document using C#.
To achieve this, you can follow the below steps:
- Get the mail merge data
- Execute mail merge
- Using MergeField event, insert a bookmark at the merge field.
- Maintain a dictionary with the inserted bookmark name and the document name to be merged in place of that merge field.
- After executing the mail merge, replace the inserted bookmarks with the corresponding document’s content from the dictionary using the ReplaceContent API.
Steps to use multiple documents as data sources for mail merge in a Word document
-
Create a new C# .NET Core console application project.
-
Install the Syncfusion.DocIO.Net.Core NuGet package as a reference to your project from Nuget.org.
Starting with v16.2.0.x, if you reference Syncfusion assemblies from trial setup or from the NuGet feed, include a license key in your projects. Refer to the link to learn about generating and registering a Syncfusion license key in your application to use the components without trail message.
- Include the following namespace in the Program.cs file.
C#
using Syncfusion.DocIO;
using Syncfusion.DocIO.DLS;
- Include the below code snippet in Program.cs to mail merge with another document content in Word document.
C#
// Declare and initialize a static counter.
static int count = 0;
// Declare and initialize a dictionary for bookmarks
static Dictionary<string, string> BookmarksAdded = new Dictionary<string, string>();
//Open an existing Word document.
using (FileStream fileStream = new FileStream("../../../Data/Template.docx", FileMode.Open, FileAccess.ReadWrite))
{
using (WordDocument document = new WordDocument(fileStream, FormatType.Docx))
{
//Get the subscription details as “IEnumerable” collection.
List<CategoryList> categoryLists = GetCategoryList();
//Create an instance of “MailMergeDataTable” by specifying mail merge group name and “IEnumerable” collection.
MailMergeDataTable dataTable = new MailMergeDataTable("Categories", categoryLists);
//Mail merge event.
document.MailMerge.MergeField += MailMerge_MergeField;
//Perform Mail merge.
document.MailMerge.ExecuteNestedGroup(dataTable);
//Replace the field with another document content.
ReplaceBookmarks(document);
//Save the Word document to file stream.
using (FileStream outputStream = new FileStream(Path.GetFullPath(@"../../../Data/Output.docx"), FileMode.Create, FileAccess.ReadWrite))
{
document.Save(outputStream, FormatType.Docx);
}
}
}
- Add the following method to handle the Mail Merge event.
C#
//Mail merge event.
private static void MailMerge_MergeField(object sender, MergeFieldEventArgs args)
{
if(args.FieldName == "Description")
{
//Get the owner paragraph
WParagraph para = args.CurrentMergeField.OwnerParagraph;
//Get the index of current field
int index = para.Items.IndexOf(args.CurrentMergeField);
//Add the bookmark to the begining of the field
string bkmkName = "Bkmk_" + count;
BookmarkStart bkmkStart = new BookmarkStart(para.Document, bkmkName);
Bookmark bookmark = new Bookmark(bkmkStart);
para.Items.Insert(index, bkmkStart);
BookmarkEnd bkmkEnd = new BookmarkEnd(para.Document, bkmkName);
para.Items.Insert(index + 1, bkmkEnd);
//Add the bookmark name and the document path to the dictionary.
BookmarksAdded.Add(bkmkName, args.FieldValue.ToString());
//Increment the count
count++;
//Remove the field value i.e., document path given.
args.Text = "";
}
}
- Add the following method to replace the field with another document content.
C#
//Replace the field with another document content.
private static void ReplaceBookmarks(WordDocument document)
{
foreach(string bkmkName in BookmarksAdded.Keys)
{
using (FileStream fileStream = new FileStream(Path.GetFullPath(BookmarksAdded.GetValueOrDefault(bkmkName)), FileMode.Open, FileAccess.ReadWrite))
{
//Open the document for content.
using (WordDocument tempDoc = new WordDocument(fileStream, FormatType.Automatic))
{
//Get the bookmark using bookmark navigator
BookmarksNavigator nav = new BookmarksNavigator(document);
nav.MoveToBookmark(bkmkName);
//Load the document as WordDocumentPart
WordDocumentPart part = new WordDocumentPart();
part.Load(tempDoc);
//Replace the bookmark content.
nav.ReplaceContent(part);
//Remove the bookmark
Bookmark bkmk = document.Bookmarks.FindByName(bkmkName);
document.Bookmarks.Remove(bkmk);
}
}
}
}
- Add the following helper methods to retrieve a list of category items.
C#
// Retrieve a list of category items.
public static List<CategoryList> GetCategoryList()
{
List<FieldList> field = new List<FieldList>();
field.Add(new FieldList("Field1", "Value1"));
field.Add(new FieldList("Field2", "Value2"));
field.Add(new FieldList("Field3", "Value3"));
List<ItemsList> items = new List<ItemsList>();
items.Add(new ItemsList("Title1", "../../../Data/one.html", field));
field = new List<FieldList>();
field.Add(new FieldList("Field4", "Value4"));
field.Add(new FieldList("Field5", "Value5"));
field.Add(new FieldList("Field6", "Value6"));
items.Add(new ItemsList("Title2", "../../../Data/Two.docx", field));
List<CategoryList> categories = new List<CategoryList>();
categories.Add(new CategoryList("Category1", items));
return categories;
}
- Add the following helper class to create the category items.
C#
// Represent a category with a name and a list of items.
public class CategoryList
{
public string CategoryName { get; set; }
public List<ItemsList> Items { get; set; }
public CategoryList(string categoryName, List<ItemsList> items)
{
CategoryName = categoryName;
Items = items;
}
}
// Represent an item with a title, description, and a list of fields.
public class ItemsList
{
public string ItemTitle { get; set; }
public string Description { get; set; }
public List<FieldList> Field { get; set; }
public ItemsList(string itemTitle, string description, List<FieldList> field)
{
ItemTitle = itemTitle;
Description = description;
Field = field;
}
}
// Represent a field with a name and a value.
public class FieldList
{
public string FieldName { get; set; }
public string FieldValue { get; set; }
public FieldList(string name, string value)
{
FieldName = name;
FieldValue = value;
}
}
A complete working sample to perform mail merge with another document content in Word document can be downloaded from GitHub.
By executing the program, you will get the Word document as follows.
Take a moment to peruse the [documentation](https where you can find basic Word document processing options along with the features like mail merge, merge, split, and compare documents, find and replace text in the Word document, protect the Word documents, and most importantly, the PDF and Image conversions with code examples.
Conclusion
I hope you enjoyed learning about how to use multiple documents as data sources for mail merge in a Word document.
You can refer to our ASP.NET Core DocIO feature tour page to know about its other groundbreaking feature representations and documentation, and how to quickly get started for configuration specifications. You can also explore our ASP.NET Core DocIO example to understand how to create and manipulate data.
For current customers, you can check out our components from the License and Downloads page. If you are new to Syncfusion, you can try our 30-day free trial to check out our other controls.
If you have any queries or require clarifications, please let us know in the comments section below. You can also contact us through our support forums, Direct-Trac, or feedback portal. We are always happy to assist you!