1+ using Syncfusion . DocIO . DLS ;
2+ using System . Collections . Generic ;
3+ using System . Data ;
4+
5+ namespace Apply_custom_formatting_mailmerge_fields
6+ {
7+ class Program
8+ {
9+ public static Dictionary < WParagraph , List < KeyValuePair < int , string > > > paratoModifyNumberFormat
10+ = new Dictionary < WParagraph , List < KeyValuePair < int , string > > > ( ) ;
11+ public static Dictionary < WParagraph , List < KeyValuePair < int , string > > > paratoModifyDateFormat
12+ = new Dictionary < WParagraph , List < KeyValuePair < int , string > > > ( ) ;
13+ public static void Main ( string [ ] args )
14+ {
15+ // Load the existing word document
16+ WordDocument document = new WordDocument ( Path . GetFullPath ( @"Data\Template.docx" ) ) ;
17+ // Enable separate page for each invoice
18+ document . MailMerge . StartAtNewPage = true ;
19+ document . MailMerge . MergeField += new MergeFieldEventHandler ( MergeFieldEvent ) ;
20+ // Perform mail merge
21+ document . MailMerge . ExecuteGroup ( GetInvoiceData ( ) ) ;
22+ // Update the merge field results with formatted values.
23+ UpdateMergeFieldResult ( true ) ;
24+ UpdateMergeFieldResult ( false ) ;
25+ // Save the Word document.
26+ document . Save ( Path . GetFullPath ( @"../../../Output/Output.docx" ) ) ;
27+ // Close the document
28+ document . Close ( ) ;
29+
30+ }
31+ /// <summary>
32+ /// Event handler triggered during mail merge for each merge field.
33+ /// </summary>
34+ /// <param name="sender">The source of the event (MailMerge engine)</param>
35+ /// <param name="args">Provides information about the current merge field.</param>
36+ private static void MergeFieldEvent ( object sender , MergeFieldEventArgs args )
37+ {
38+ // Get the mergefield's Owner paragraph
39+ WParagraph mergeFieldOwnerParagraph = args . CurrentMergeField . OwnerParagraph ;
40+ // Find the index of the current merge field within the paragraph.
41+ int index = mergeFieldOwnerParagraph . ChildEntities . IndexOf ( args . CurrentMergeField ) ;
42+ if ( args . FieldName == "Amount" )
43+ {
44+ // Check if this paragraph already has an entry in the dictionary.
45+ // If not, create a new list to store field index and field value.
46+ if ( ! paratoModifyNumberFormat . TryGetValue ( mergeFieldOwnerParagraph , out var fields ) )
47+ {
48+ fields = new List < KeyValuePair < int , string > > ( ) ;
49+ paratoModifyNumberFormat [ mergeFieldOwnerParagraph ] = fields ;
50+ }
51+ // Add the current merge field's index and field name
52+ fields . Add ( new KeyValuePair < int , string > ( index , args . FieldValue . ToString ( ) ) ) ;
53+ }
54+ else if ( args . FieldName == "InvoiceDate" )
55+ {
56+ // Check if this paragraph already has an entry in the dictionary.
57+ // If not, create a new list to store field index and field value.
58+ if ( ! paratoModifyDateFormat . TryGetValue ( mergeFieldOwnerParagraph , out var fields ) )
59+ {
60+ fields = new List < KeyValuePair < int , string > > ( ) ;
61+ paratoModifyDateFormat [ mergeFieldOwnerParagraph ] = fields ;
62+ }
63+ // Add the current merge field's index and field name
64+ fields . Add ( new KeyValuePair < int , string > ( index , args . FieldValue . ToString ( ) ) ) ;
65+ }
66+ }
67+ /// <summary>
68+ /// Updates the merge fields result after mail merge by applying number and date formatting using IF fields.
69+ /// </summary>
70+ /// <param name="numberType">The boolean denotes current changes as Number format</param>
71+ public static void UpdateMergeFieldResult ( bool numberType )
72+ {
73+ Dictionary < WParagraph , List < KeyValuePair < int , string > > > mergeFieldResults ;
74+ if ( numberType )
75+ mergeFieldResults = paratoModifyNumberFormat ;
76+ else
77+ mergeFieldResults = paratoModifyDateFormat ;
78+ // Iterate the outer dictionary entries
79+ foreach ( KeyValuePair < WParagraph , List < KeyValuePair < int , string > > > dictionaryItem in mergeFieldResults )
80+ {
81+ // Get the merge field result paragraph
82+ WParagraph mergeFieldParagraph = dictionaryItem . Key ;
83+ // The list of (index, fieldValues) pairs for this paragraph.
84+ List < KeyValuePair < int , string > > fieldList = dictionaryItem . Value ;
85+ for ( int i = 0 ; i <= fieldList . Count - 1 ; i ++ )
86+ {
87+ // Get the index and Field values ("Number" or "Date")
88+ int index = fieldList [ i ] . Key ;
89+ string fieldValue = fieldList [ i ] . Value ;
90+ // Get the existing merge field result text at the specified index.
91+ WTextRange mergeFieldText = ( WTextRange ) mergeFieldParagraph . ChildEntities [ index ] ;
92+ if ( mergeFieldText != null )
93+ {
94+ // Create the temporary document and insert the IF field.
95+ WordDocument tempDocument = new WordDocument ( ) ;
96+ WSection section = ( WSection ) tempDocument . AddSection ( ) ;
97+ WParagraph ifFieldParagraph = ( WParagraph ) section . AddParagraph ( ) ;
98+ WIfField field = ( WIfField ) ifFieldParagraph . AppendField ( "IfField" , Syncfusion . DocIO . FieldType . FieldIf ) ;
99+ // Check if the Number field value
100+ if ( numberType )
101+ {
102+ // Format number: 1,234.56
103+ field . FieldCode = $ "IF 1 = 1 \" { fieldValue } \" \" \" \\ # \" #,##0.00";
104+ }
105+ // Update the Date field value
106+ else
107+ {
108+ // Format date: dd/MMM/yyyy
109+ field . FieldCode = $ "IF 1 = 1 \" { fieldValue } \" \" \" \\ @ \" dd/MMM/yyyy\" ";
110+ }
111+ // Update the field and unlink
112+ tempDocument . UpdateDocumentFields ( ) ;
113+ field . Unlink ( ) ;
114+ // Update the Merge field result
115+ WTextRange modifiedText = ( WTextRange ) ifFieldParagraph . ChildEntities [ 0 ] ;
116+ mergeFieldText . Text = modifiedText . Text ;
117+ // close the temp document
118+ tempDocument . Close ( ) ;
119+ }
120+ }
121+ }
122+ if ( numberType )
123+ paratoModifyNumberFormat . Clear ( ) ;
124+ else
125+ paratoModifyDateFormat . Clear ( ) ;
126+ }
127+ private static DataTable GetInvoiceData ( )
128+ {
129+ DataTable table = new DataTable ( "Invoice" ) ;
130+
131+ table . Columns . Add ( "InvoiceNumber" ) ;
132+ table . Columns . Add ( "InvoiceDate" ) ;
133+ table . Columns . Add ( "CustomerName" ) ;
134+ table . Columns . Add ( "ItemDescription" ) ;
135+ table . Columns . Add ( "Amount" ) ;
136+ // First Invoice
137+ table . Rows . Add ( "INV001" , "2024-05-01" , "Andy Bernard" , "Consulting Services" , "3,000.578" ) ;
138+ // Second Invoice
139+ table . Rows . Add ( "INV002" , "2024-05-05" , "Stanley Hudson" , "Software Development" , "4,500.052" ) ;
140+ // Third Invoice
141+ table . Rows . Add ( "INV003" , "2024-05-10" , "Margaret Peacock" , "UI Design Services" , "2,000.600" ) ;
142+
143+ return table ;
144+ }
145+ }
146+ }
0 commit comments