Skip to content

Commit 4f1d745

Browse files
Merge pull request #283 from VijayadharshiniMathiyalagan/ES-891643-How-to-replace-a-merge-field-with-an-image-from-an-HTML-string-in-a-Word-document
Add sample for replace a merge field with an image from an HTML string in a Word document
2 parents 3a44ce5 + 603dca4 commit 4f1d745

File tree

7 files changed

+172
-0
lines changed

7 files changed

+172
-0
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.12.35417.141 d17.12
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Replace-merge-field-with-html-image", "Replace-merge-field-with-html-image\Replace-merge-field-with-html-image.csproj", "{1EA61573-2551-4DF1-A7B0-1CC232452779}"
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+
{1EA61573-2551-4DF1-A7B0-1CC232452779}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15+
{1EA61573-2551-4DF1-A7B0-1CC232452779}.Debug|Any CPU.Build.0 = Debug|Any CPU
16+
{1EA61573-2551-4DF1-A7B0-1CC232452779}.Release|Any CPU.ActiveCfg = Release|Any CPU
17+
{1EA61573-2551-4DF1-A7B0-1CC232452779}.Release|Any CPU.Build.0 = Release|Any CPU
18+
EndGlobalSection
19+
GlobalSection(SolutionProperties) = preSolution
20+
HideSolutionNode = FALSE
21+
EndGlobalSection
22+
EndGlobal
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<html>
2+
<body>
3+
<img src="../../../Data/Logo.png" width="180" height="112" alt="logo" />
4+
</body>
5+
</html>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
using Syncfusion.DocIO.DLS;
2+
using Syncfusion.DocIO;
3+
using System.Data;
4+
5+
//Dictionary to maintain paragraph and corresponding merge field index with HTML content.
6+
Dictionary<WParagraph, Dictionary<int, string>> paraToInsertHTML = new Dictionary<WParagraph, Dictionary<int, string>>();
7+
8+
using (FileStream fileStream = new FileStream(Path.GetFullPath(@"Data/Template.docx"), FileMode.Open, FileAccess.ReadWrite))
9+
{
10+
//Opens the template Word document.
11+
using (WordDocument document = new WordDocument(fileStream, FormatType.Automatic))
12+
{
13+
//Creates the mail merge events handler to replace merge field with HTML.
14+
document.MailMerge.MergeField += new MergeFieldEventHandler(MergeFieldEvent);
15+
//Gets data to perform the mail merge.
16+
DataTable table = GetDataTable();
17+
//Performs the mail merge.
18+
document.MailMerge.Execute(table);
19+
//Append HTML to paragraph.
20+
InsertHtml();
21+
//Removes the mail merge events handler.
22+
document.MailMerge.MergeField -= new MergeFieldEventHandler(MergeFieldEvent);
23+
using (FileStream outputStream = new FileStream(Path.GetFullPath(@"Output/Result.docx"), FileMode.Create, FileAccess.ReadWrite))
24+
{
25+
//Saves the Modified Word document.
26+
document.Save(outputStream, FormatType.Docx);
27+
}
28+
}
29+
}
30+
31+
/// <summary>
32+
/// Handles the MergeField event to replace the merge field with HTML content.
33+
/// </summary>
34+
void MergeFieldEvent(object sender, MergeFieldEventArgs args)
35+
{
36+
if (args.FieldName.Equals("Logo"))
37+
{
38+
//Gets the current merge field owner paragraph.
39+
WParagraph paragraph = args.CurrentMergeField.OwnerParagraph;
40+
//Gets the current merge field index in the current paragraph.
41+
int mergeFieldIndex = paragraph.ChildEntities.IndexOf(args.CurrentMergeField);
42+
//Maintain HTML in collection.
43+
Dictionary<int, string> fieldValues = new Dictionary<int, string>();
44+
fieldValues.Add(mergeFieldIndex, args.FieldValue.ToString());
45+
//Maintain paragraph in collection.
46+
paraToInsertHTML.Add(paragraph, fieldValues);
47+
//Set field value as empty.
48+
args.Text = string.Empty;
49+
}
50+
}
51+
52+
/// <summary>
53+
/// Get a data table for the mail merge operation.
54+
/// </summary>
55+
DataTable GetDataTable()
56+
{
57+
DataTable dataTable = new DataTable("HTML");
58+
dataTable.Columns.Add("CustomerName");
59+
dataTable.Columns.Add("Address");
60+
dataTable.Columns.Add("Phone");
61+
dataTable.Columns.Add("Logo");
62+
63+
//Adds sample data to the DataTable.
64+
DataRow datarow = dataTable.NewRow();
65+
dataTable.Rows.Add(datarow);
66+
datarow["CustomerName"] = "Nancy Davolio";
67+
datarow["Address"] = "59 rue de I'Abbaye, Reims 51100, France";
68+
datarow["Phone"] = "1-888-936-8638";
69+
70+
//Reads HTML string from the file.
71+
string htmlString = File.ReadAllText(Path.GetFullPath(@"Data/File.html"));
72+
datarow["Logo"] = htmlString;
73+
74+
return dataTable;
75+
}
76+
77+
/// <summary>
78+
/// Inserts HTML content into the specified paragraphs and positions within the Word document.
79+
/// </summary>
80+
void InsertHtml()
81+
{
82+
//Iterates through each item in the dictionary.
83+
foreach (KeyValuePair<WParagraph, Dictionary<int, string>> dictionaryItems in paraToInsertHTML)
84+
{
85+
WParagraph paragraph = dictionaryItems.Key as WParagraph;
86+
Dictionary<int, string> values = dictionaryItems.Value as Dictionary<int, string>;
87+
//Iterates through each value in the dictionary.
88+
foreach (KeyValuePair<int, string> valuePair in values)
89+
{
90+
int index = valuePair.Key;
91+
string fieldValue = valuePair.Value;
92+
93+
//Hook the ImageNodeVisited event to resolve images within HTML content.
94+
paragraph.Document.HTMLImportSettings.ImageNodeVisited += OpenImage;
95+
96+
//Inserts an HTML string at the same position of mergefield in a Word document.
97+
paragraph.OwnerTextBody.InsertXHTML(fieldValue, paragraph.OwnerTextBody.ChildEntities.IndexOf(paragraph), index);
98+
99+
//Unhook the ImageNodeVisited event after processing.
100+
paragraph.Document.HTMLImportSettings.ImageNodeVisited -= OpenImage;
101+
}
102+
}
103+
//Clears the dictionary after inserting HTML content.
104+
paraToInsertHTML.Clear();
105+
}
106+
107+
/// <summary>
108+
/// Opens images referenced within HTML content.
109+
/// </summary>
110+
void OpenImage(object sender, ImageNodeVisitedEventArgs args)
111+
{
112+
//Reads the image from the specified URI path and assigns it to the image stream.
113+
args.ImageStream = File.OpenRead(args.Uri);
114+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net8.0</TargetFramework>
6+
<RootNamespace>Replace_merge_field_with_html_image</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\File.html">
17+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
18+
</None>
19+
<None Update="Data\Logo.png">
20+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
21+
</None>
22+
<None Update="Data\Template.docx">
23+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
24+
</None>
25+
<None Update="Output\.gitkeep">
26+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
27+
</None>
28+
</ItemGroup>
29+
30+
</Project>

0 commit comments

Comments
 (0)