Skip to content

Commit

Permalink
Merge pull request #326 from SyncfusionExamples/889581-Two-records-pe…
Browse files Browse the repository at this point in the history
…r-page

889581-Add sample Two-records-per-page
  • Loading branch information
MohanaselvamJothi authored Feb 14, 2025
2 parents e195557 + 37ee367 commit 2cc04a6
Show file tree
Hide file tree
Showing 7 changed files with 241 additions and 0 deletions.
22 changes: 22 additions & 0 deletions Mail-Merge/Two-records-per-page/.NET/Two-records-per-page.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.12.35527.113 d17.12
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Two-records-per-page", "Two-records-per-page\Two-records-per-page.csproj", "{59087513-6357-48C0-BBBA-FBF94F3627C0}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{59087513-6357-48C0-BBBA-FBF94F3627C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{59087513-6357-48C0-BBBA-FBF94F3627C0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{59087513-6357-48C0-BBBA-FBF94F3627C0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{59087513-6357-48C0-BBBA-FBF94F3627C0}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"Employees": [
{
"NAME": "Nancy",
"DESIGNATION": "Software Engineer",
"COUNTRY": "USA"
},
{
"NAME": "Janet",
"DESIGNATION": "Project Manager",
"COUNTRY": "Canada"
},
{
"NAME": "Andrew",
"DESIGNATION": "UI/UX Designer",
"COUNTRY": "UK"
},
{
"NAME": "Maria",
"DESIGNATION": "QA Engineer",
"COUNTRY": "Australia"
},
{
"NAME": "Antonio",
"DESIGNATION": "Business Analyst",
"COUNTRY": "India"
},
{
"NAME": "Thomas",
"DESIGNATION": "DevOps Engineer",
"COUNTRY": "Germany"
},
{
"NAME": "Elizabeth",
"DESIGNATION": "Product Owner",
"COUNTRY": "USA"
},
{
"NAME": "James",
"DESIGNATION": "Data Scientist",
"COUNTRY": "France"
}
]
}
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Binary file not shown.
146 changes: 146 additions & 0 deletions Mail-Merge/Two-records-per-page/.NET/Two-records-per-page/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
using Syncfusion.DocIO.DLS;
using Syncfusion.DocIO;
using System.Data;
using Newtonsoft.Json.Linq;
using System;
using System.IO;

namespace Two_records_per_page
{
internal class Program
{
static int count = 0; // Counter for page breaks.
static WParagraph endPara; // Variable to store the end paragraph.
static int index; // Index for the beginning paragraph.

static void Main(string[] args)
{
// Opens the template document
using (FileStream fileStreamPath = new FileStream(Path.GetFullPath(@"Data/Template.docx"), FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
using (WordDocument document = new WordDocument(fileStreamPath, FormatType.Automatic))
{
// Get the beginning paragraph where group starts.
TextSelection selection = document.Find("BeginGroup:Employees", true, true);
WParagraph beginPara = selection.GetAsOneRange().OwnerParagraph;

// Get the end paragraph where group ends.
TextSelection endSelection = document.Find("EndGroup:Employees", true, true);
endPara = endSelection.GetAsOneRange().OwnerParagraph.NextSibling as WParagraph;

// Start each record on a new page during mail merge.
document.MailMerge.StartAtNewPage = true;

// Execute the group mail merge
document.MailMerge.ExecuteGroup(GetDataTable());

// Get index of the beginning paragraph for iteration.
index = beginPara.OwnerTextBody.ChildEntities.IndexOf(beginPara);

// Remove odd page breaks in document.
IterateTextBody(beginPara.OwnerTextBody);

// Save the result to a file.
using (FileStream outputFileStream = new FileStream(Path.GetFullPath(@"Output/Result.docx"), FileMode.Create, FileAccess.ReadWrite))
{
document.Save(outputFileStream, FormatType.Docx);
}
}
}
}

// Method to iterate through the text body and handle elements.
static void IterateTextBody(WTextBody textBody)
{
// Loop through each entity in the text body (paragraphs, tables, etc.).
for (int i = index; i < textBody.ChildEntities.Count; i++)
{
IEntity bodyItemEntity = textBody.ChildEntities[i];

switch (bodyItemEntity.EntityType)
{
case EntityType.Paragraph:
WParagraph paragraph = bodyItemEntity as WParagraph;
// Process paragraph unless it's the end paragraph.
if (paragraph != endPara)
IterateParagraph(paragraph.Items, paragraph);
break;
case EntityType.Table:
// Process tables.
IterateTable(bodyItemEntity as WTable);
break;
case EntityType.BlockContentControl:
BlockContentControl blockContentControl = bodyItemEntity as BlockContentControl;
// Iterate through body items in block content control.
IterateTextBody(blockContentControl.TextBody);
break;
}
}
}

// Method to iterate through the table rows and cells.
static void IterateTable(WTable table)
{
// Loop through rows and cells in a table.
foreach (WTableRow row in table.Rows)
{
foreach (WTableCell cell in row.Cells)
{
// Reuse text body iteration logic for table cells.
IterateTextBody(cell);
}
}
}

// Method to iterate through paragraphs and remove page breaks.
static void IterateParagraph(ParagraphItemCollection paraItems, WParagraph paragraph)
{
if (paragraph != null)
{
// Loop through the paragraph items in reverse order to check for page breaks.
for (int i = paraItems.Count - 1; i >= 0; i--)
{
ParagraphItem item = paraItems[i];
if (item is Break && (item as Break).BreakType == BreakType.PageBreak)
{
count++; // Count the page break.
if (count % 2 != 0)
paraItems.Remove(item); // Remove the page break if count is odd.
}
}
}
}

// Method to get data from a JSON file and convert it to a DataTable for mail merge.
private static DataTable GetDataTable()
{
string jsonString = File.ReadAllText(Path.GetFullPath(@"../../../Data/Data.json"));
DataTable dataTable = new DataTable("Employees");
JObject json = JObject.Parse(jsonString);

bool columnsAdded = false;
foreach (var item in json["Employees"])
{
// Add columns once.
if (!columnsAdded)
{
foreach (JProperty property in item)
{
dataTable.Columns.Add(property.Name, typeof(string));
}
columnsAdded = true;
}

// Add rows to DataTable.
DataRow row = dataTable.NewRow();
foreach (JProperty property in item)
{
row[property.Name] = property.Value.ToString();
}
dataTable.Rows.Add(row);
}

return dataTable;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<RootNamespace>Two_records_per_page</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Syncfusion.DocIO.Net.Core" Version="*" />
</ItemGroup>

<ItemGroup>
<None Update="Data\Data.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Data\Template.docx">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Output\.gitkeep">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>

0 comments on commit 2cc04a6

Please sign in to comment.