Skip to content

Commit 95cc582

Browse files
Added sample for replace a merge field with an image from an HTML string in a Word document
1 parent 1ffe70f commit 95cc582

File tree

7 files changed

+175
-0
lines changed

7 files changed

+175
-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>
78.9 KB
Loading
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

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