Available for: UI for ASP.NET MVC | UI for ASP.NET AJAX | UI for Blazor | UI for WPF | UI for WinForms | UI for Xamarin | UI for WinUI | UI for ASP.NET Core | UI for .NET MAUI

New to Telerik Document Processing? Download free 30-day trial

Mail Merge

Mail merge is functionality allowing to produce personalized documents from a template holding fixed content and variables. The variables are called Merge Fields and are replaced through the merge process with content from a specified data source.

Inserting Merge Fields

Merge fields are a type of Fields and can be added in a template document via RadFlowDocumentEditor's InsertField() method. The method requires the code representation of the field and the result which is shown in the template before the document is mail-merged.

The code snippet in Example 1 shows how to initialize a RadFlodDocumentEditor instance and insert a merge field.

Example 1: Insert a merge field

RadFlowDocument document = CreateDocument(); 
RadFlowDocumentEditor editor = new RadFlowDocumentEditor(document); 
editor.InsertField("MERGEFIELD FirstName", ""); 

Additionally, a field can be added to a Paragraph manually by creating a FieldInfo instance and placing its start, code, separator, result and end in the block. Example 2 shows the manual approach for adding a merge field.

Example 2: Add a merge field manually

FieldInfo field = new FieldInfo(document); 
 
paragraph.Inlines.Add(field.Start); 
paragraph.Inlines.AddRun("MERGEFIELD LastName"); 
paragraph.Inlines.Add(field.Separator); 
paragraph.Inlines.AddRun(""); 
paragraph.Inlines.Add(field.End); 

Performing Mail Merge

Mail merge can be performed over a template document containing merge fields. For this action the MailMerge() method of RadFlowDocument needs to be used. The method accepts a collection of elements as a parameter.

During the operation, each MergeField is replaced with the corresponding information from the data source record in a new RadFlowDocument instance. Every subsequent entry in the data source is appended to a single resulting document which is returned by the method. The original template stays unmodified.

Example 3 shows a simple example data source.

Example 3: Sample data source

List<MailMergeRecord> mailMergeDataSource = new List<MailMergeRecord>() 
{ 
    new MailMergeRecord() 
    { 
        FirstName = "Andrew", 
        LastName = "Fuller" 
    }, 
    new MailMergeRecord() 
    { 
        FirstName = "Nancy", 
        LastName = "Davolio" 
    }, 
}; 

Example 4 performs the mail merge operation over a previously defined template document using the data source from Example 3.

Example 4: Perform mail merge

RadFlowDocument mailMergeResult = document.MailMerge(mailMergeDataSource); 

Nested Mail Merge

The nested mail merge functionality is supported from R1 2022. It allows you to merge data sources that contain nested data. For example, your business object can contain a list of other objects and this functionality allows accessing the properties of the underlying objects. In order to use the underlying objects, you need to declare a group. Currently, the following group tags are supported:

  • BeginGroup/EndGroup
  • TableStart/TableEnd
  • RangeStart/RangeEnd
  • GroupStart/GroupEnd

Currently, all tag pairs work equally and more than one option exists in order to improve the readability of the documents.

Exception: When a table row has only one cell, using the TableStart/TableEnd tags over the whole content of that cell will create a new row for each value. Every other pair of tags (BeginGroup/EndGroup, RangeStart/RangeEnd, GroupStart/GroupEnd) are interchangeable and will put the values on the same row inside that cell.

A single cell (spanning the whole row) with TableStart/TableEnd tags:

Rad Words Processing mail merge

A single cell (spanning the whole row) with a tag group different than TableStart/TableEnd:

Rad Words Processing mail merge

The following example demonstrates how you can use the nested mail merge:

First you need to define a data source that contains an IEnumerable of objects.

Example 5: Nested mail merge data source

public List<Team> GetTeams() 
{ 
    var teams = new List<Team>(); 
    var team1 = new Team(); 
    team1.TeamName = "Team 1"; 
    team1.Players.Add(new Player() { FirstName = "John", LastName = "Baker" }); 
    team1.Players.Add(new Player() { FirstName = "Sam ", LastName = "Wayne" }); 
    teams.Add(team1); 
 
    var team2 = new Team(); 
    team2.TeamName = "Team 2"; 
    team2.Players.Add(new Player() { FirstName = "Patrick", LastName = "Gibbs" }); 
    team2.Players.Add(new Player() { FirstName = "Oscar", LastName = "Stevens" }); 
    teams.Add(team2); 
 
    return teams; 
} 
 
public class Team 
{ 
    public string TeamName { get; set; } 
 
    public List<Player> Players { get; set; } 
 
    public Team() 
    { 
        this.Players = new List<Player>(); 
    } 
} 
public class Player 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
} 
Now you need to add the fields using the specific supported names. In this example, we are adding the fields to the table and we will use the TableStart/TableEnd tags, but this is not mandatory and you can use a tag of your choosing.

Example 6: Perform nested mail merge

var document = new RadFlowDocument(); 
var editor = new RadFlowDocumentEditor(document); 
 
editor.InsertParagraph(); 
editor.InsertField("MERGEFIELD TeamName", ""); 
editor.InsertParagraph(); 
editor.InsertText("Players:");  
 
var playersTable = editor.InsertTable(2, 2); 
playersTable.PreferredWidth = new TableWidthUnit(TableWidthUnitType.Percent, 100); 
document.StyleRepository.AddBuiltInStyle(BuiltInStyleNames.TableGridStyleId); 
playersTable.StyleId = BuiltInStyleNames.TableGridStyleId; 
 
playersTable.Rows[0].Cells[0].Blocks.AddParagraph().Inlines.AddRun("First Name"); 
playersTable.Rows[0].Cells[1].Blocks.AddParagraph().Inlines.AddRun("Last Name"); 
 
var firstNameParagraph = playersTable.Rows[1].Cells[0].Blocks.AddParagraph(); 
editor.MoveToParagraphStart(firstNameParagraph); 
editor.InsertField("MERGEFIELD TableStart:Players", ""); 
editor.InsertField("MERGEFIELD FirstName", ""); 
 
var lastNameParagraph = playersTable.Rows[1].Cells[1].Blocks.AddParagraph(); 
editor.MoveToParagraphStart(lastNameParagraph); 
editor.InsertField("MERGEFIELD LastName", ""); 
editor.InsertField("MERGEFIELD TableEnd:Players", ""); 
 
RadFlowDocument mailMergeResult = document.MailMerge(GetTeams()); 

One Row vs Multiline Mail Merge

With the nested mail merge functionality, it is possible to add all items to a single line. This is achieved by adding the group and regular fields to a single paragraph.

Figure 1: Mail Merging on a single row and the results

Rad Words Processing mail merge

If you want to separate the items into several rows you need to close the group on the next row

Figure 2: Mail Merging on multiple rows row and the results

Rad Words Processing mail merge

See Also

In this article