Skip to content

Commit 7046f21

Browse files
Merge pull request #470 from SyncfusionExamples/965454-Execute-GroupMailMerge-FirstOccurrenceOnly
965454 - Add sample for executing GroupMailMerge at first occurrence
2 parents ca32778 + 956921d commit 7046f21

File tree

7 files changed

+207
-0
lines changed

7 files changed

+207
-0
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.14.36518.9 d17.14
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Execute-GroupMailMerge-FirstOccurrenceOnly", "Execute-GroupMailMerge-FirstOccurrenceOnly\Execute-GroupMailMerge-FirstOccurrenceOnly.csproj", "{EC618C0E-D312-43D3-AC08-B7673F7A4750}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|Any CPU = Debug|Any CPU
11+
Release|Any CPU = Release|Any CPU
12+
EndGlobalSection
13+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
14+
{EC618C0E-D312-43D3-AC08-B7673F7A4750}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15+
{EC618C0E-D312-43D3-AC08-B7673F7A4750}.Debug|Any CPU.Build.0 = Debug|Any CPU
16+
{EC618C0E-D312-43D3-AC08-B7673F7A4750}.Release|Any CPU.ActiveCfg = Release|Any CPU
17+
{EC618C0E-D312-43D3-AC08-B7673F7A4750}.Release|Any CPU.Build.0 = Release|Any CPU
18+
EndGlobalSection
19+
GlobalSection(SolutionProperties) = preSolution
20+
HideSolutionNode = FALSE
21+
EndGlobalSection
22+
GlobalSection(ExtensibilityGlobals) = postSolution
23+
SolutionGuid = {87877196-7EA7-43C8-98D5-B81300155D80}
24+
EndGlobalSection
25+
EndGlobal
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace Execute_GroupMailMerge_FirstOccurrenceOnly
8+
{
9+
internal class EmployeeDetails
10+
{
11+
public string EmployeeName { get; }
12+
public string EmployeeID { get; }
13+
public string JoinedDate { get; }
14+
15+
public EmployeeDetails(string employeeName, string employeeID, string joinedDate)
16+
{
17+
EmployeeName = employeeName;
18+
EmployeeID = employeeID;
19+
JoinedDate = joinedDate;
20+
}
21+
}
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net8.0</TargetFramework>
6+
<RootNamespace>Execute_GroupMailMerge_FirstOccurrenceOnly</RootNamespace>
7+
<ImplicitUsings>enable</ImplicitUsings>
8+
<Nullable>enable</Nullable>
9+
</PropertyGroup>
10+
11+
<ItemGroup>
12+
<PackageReference Include="Syncfusion.DocIO.Net.Core" Version="*" />
13+
</ItemGroup>
14+
15+
<ItemGroup>
16+
<None Update="Data\Template.docx">
17+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
18+
</None>
19+
<None Update="Output\.gitkeep">
20+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
21+
</None>
22+
</ItemGroup>
23+
24+
</Project>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace Execute_GroupMailMerge_FirstOccurrenceOnly
8+
{
9+
internal class Organization
10+
{
11+
public string BranchName { get; }
12+
public string Address { get; }
13+
public string Country { get; }
14+
public List<EmployeeDetails> Employees { get; }
15+
16+
public Organization(string branchName, string address, string country, List<EmployeeDetails> employees)
17+
{
18+
BranchName = branchName;
19+
Address = address;
20+
Country = country;
21+
Employees = employees;
22+
}
23+
}
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
using Syncfusion.DocIO;
2+
using Syncfusion.DocIO.DLS;
3+
using System;
4+
using System.Collections.Generic;
5+
using System.IO;
6+
7+
namespace Execute_GroupMailMerge_FirstOccurrenceOnly
8+
{
9+
class Program
10+
{
11+
static void Main()
12+
{
13+
// Load the Word template document
14+
WordDocument document = new WordDocument(Path.GetFullPath(@"Data/Template.docx"));
15+
// Get all merge field names from the document
16+
string[] mergeGroupNames = document.MailMerge.GetMergeFieldNames();
17+
// Create a dictionary to count how many times each merge field appears
18+
Dictionary<string, int> groupNameCounts = new Dictionary<string, int>();
19+
foreach (string groupName in mergeGroupNames)
20+
{
21+
// Increase count if field already exists, else add it
22+
if (groupNameCounts.ContainsKey(groupName))
23+
groupNameCounts[groupName]++;
24+
else
25+
groupNameCounts[groupName] = 1;
26+
}
27+
// Remove duplicate merge field groups
28+
foreach (var groupEntry in groupNameCounts)
29+
{
30+
string groupName = groupEntry.Key;
31+
// Skip if the field appears only once
32+
if (groupEntry.Value <= 1)
33+
continue;
34+
// Find all merge fields with the same name
35+
List<Entity> mergeGroups = document.FindAllItemsByProperty(EntityType.MergeField, "FieldName", groupName);
36+
// Start from second occurrence to remove duplicates
37+
for (int i = 1; i < mergeGroups.Count; i++)
38+
{
39+
WMergeField mergeField = mergeGroups[i] as WMergeField;
40+
// Check if it's a group start field
41+
if (mergeField.FieldCode.Contains("TableStart") || mergeField.FieldCode.Contains("BeginGroup"))
42+
{
43+
// Add bookmark start before the group
44+
BookmarkStart bkmkStart = new BookmarkStart(document, groupName);
45+
WParagraph startPara = mergeField.OwnerParagraph;
46+
int mergeFieldIndex = startPara.ChildEntities.IndexOf(mergeField);
47+
startPara.ChildEntities.Insert(mergeFieldIndex, bkmkStart);
48+
// Add bookmark end after the group
49+
WMergeField endField = mergeGroups[i + 1] as WMergeField;
50+
BookmarkEnd bkmkEnd = new BookmarkEnd(document, groupName);
51+
WParagraph endPara = endField.OwnerParagraph;
52+
int endFieldIndex = endPara.ChildEntities.IndexOf(endField);
53+
endPara.ChildEntities.Insert(endFieldIndex + 1, bkmkEnd);
54+
// Delete content inside the bookmark
55+
BookmarksNavigator navigator = new BookmarksNavigator(document);
56+
navigator.MoveToBookmark(groupName);
57+
navigator.DeleteBookmarkContent(false);
58+
document.Bookmarks.Remove(navigator.CurrentBookmark);
59+
// Remove owner table if applicable
60+
if (startPara.OwnerTextBody.Owner.EntityType == EntityType.TableRow)
61+
{
62+
WTableRow tableRow = startPara.OwnerTextBody.Owner as WTableRow;
63+
WTable ownerTable = tableRow.Owner as WTable;
64+
Entity currentEntity = ownerTable;
65+
// Traverse up to find the section and remove the table
66+
while (currentEntity != null)
67+
{
68+
if (currentEntity is WSection section)
69+
{
70+
section.Body.ChildEntities.Remove(ownerTable);
71+
break;
72+
}
73+
currentEntity = currentEntity.Owner;
74+
}
75+
}
76+
}
77+
}
78+
}
79+
// Prepare nested mail merge data
80+
List<Organization> organizationList = GetOrganizations();
81+
MailMergeDataTable dataTable = new MailMergeDataTable("Organizations", organizationList);
82+
// Execute nested mail merge using the data
83+
document.MailMerge.ExecuteNestedGroup(dataTable);
84+
// Save the result
85+
document.Save(Path.GetFullPath(@"../../../Output/Result.docx"));
86+
// Close the document
87+
document.Close();
88+
}
89+
90+
/// <summary>
91+
/// Create sample organization and employee data
92+
/// </summary>
93+
/// <returns>Return the organization list</returns>
94+
public static List<Organization> GetOrganizations()
95+
{
96+
// Create a list of employees
97+
List<EmployeeDetails> employees = new List<EmployeeDetails>
98+
{
99+
new EmployeeDetails("Thomas Hardy", "1001", "05/27/1996"),
100+
new EmployeeDetails("Maria Anders", "1002", "04/10/1998")
101+
};
102+
// Create a list of organizations with employee data
103+
List<Organization> organizations = new List<Organization>
104+
{
105+
new Organization("UK Office", "120 Hanover Sq.", "UK", employees)
106+
};
107+
// Return the organization list
108+
return organizations;
109+
}
110+
}
111+
}

0 commit comments

Comments
 (0)