|
| 1 | +using Syncfusion.DocIO.DLS; |
| 2 | +using Syncfusion.DocIO; |
| 3 | +using System.Data; |
| 4 | +using Newtonsoft.Json.Linq; |
| 5 | +using System; |
| 6 | +using System.IO; |
| 7 | + |
| 8 | +namespace Two_records_per_page |
| 9 | +{ |
| 10 | + internal class Program |
| 11 | + { |
| 12 | + static int count = 0; // Counter for page breaks. |
| 13 | + static WParagraph endPara; // Variable to store the end paragraph. |
| 14 | + static int index; // Index for the beginning paragraph. |
| 15 | + |
| 16 | + static void Main(string[] args) |
| 17 | + { |
| 18 | + // Opens the template document |
| 19 | + using (FileStream fileStreamPath = new FileStream(Path.GetFullPath(@"Data/Template.docx"), FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) |
| 20 | + { |
| 21 | + using (WordDocument document = new WordDocument(fileStreamPath, FormatType.Automatic)) |
| 22 | + { |
| 23 | + // Get the beginning paragraph where group starts. |
| 24 | + TextSelection selection = document.Find("BeginGroup:Employees", true, true); |
| 25 | + WParagraph beginPara = selection.GetAsOneRange().OwnerParagraph; |
| 26 | + |
| 27 | + // Get the end paragraph where group ends. |
| 28 | + TextSelection endSelection = document.Find("EndGroup:Employees", true, true); |
| 29 | + endPara = endSelection.GetAsOneRange().OwnerParagraph.NextSibling as WParagraph; |
| 30 | + |
| 31 | + // Start each record on a new page during mail merge. |
| 32 | + document.MailMerge.StartAtNewPage = true; |
| 33 | + |
| 34 | + // Execute the group mail merge |
| 35 | + document.MailMerge.ExecuteGroup(GetDataTable()); |
| 36 | + |
| 37 | + // Get index of the beginning paragraph for iteration. |
| 38 | + index = beginPara.OwnerTextBody.ChildEntities.IndexOf(beginPara); |
| 39 | + |
| 40 | + // Remove odd page breaks in document. |
| 41 | + IterateTextBody(beginPara.OwnerTextBody); |
| 42 | + |
| 43 | + // Save the result to a file. |
| 44 | + using (FileStream outputFileStream = new FileStream(Path.GetFullPath(@"Output/Result.docx"), FileMode.Create, FileAccess.ReadWrite)) |
| 45 | + { |
| 46 | + document.Save(outputFileStream, FormatType.Docx); |
| 47 | + } |
| 48 | + } |
| 49 | + } |
| 50 | + } |
| 51 | + |
| 52 | + // Method to iterate through the text body and handle elements. |
| 53 | + static void IterateTextBody(WTextBody textBody) |
| 54 | + { |
| 55 | + // Loop through each entity in the text body (paragraphs, tables, etc.). |
| 56 | + for (int i = index; i < textBody.ChildEntities.Count; i++) |
| 57 | + { |
| 58 | + IEntity bodyItemEntity = textBody.ChildEntities[i]; |
| 59 | + |
| 60 | + switch (bodyItemEntity.EntityType) |
| 61 | + { |
| 62 | + case EntityType.Paragraph: |
| 63 | + WParagraph paragraph = bodyItemEntity as WParagraph; |
| 64 | + // Process paragraph unless it's the end paragraph. |
| 65 | + if (paragraph != endPara) |
| 66 | + IterateParagraph(paragraph.Items, paragraph); |
| 67 | + break; |
| 68 | + case EntityType.Table: |
| 69 | + // Process tables. |
| 70 | + IterateTable(bodyItemEntity as WTable); |
| 71 | + break; |
| 72 | + case EntityType.BlockContentControl: |
| 73 | + BlockContentControl blockContentControl = bodyItemEntity as BlockContentControl; |
| 74 | + // Iterate through body items in block content control. |
| 75 | + IterateTextBody(blockContentControl.TextBody); |
| 76 | + break; |
| 77 | + } |
| 78 | + } |
| 79 | + } |
| 80 | + |
| 81 | + // Method to iterate through the table rows and cells. |
| 82 | + static void IterateTable(WTable table) |
| 83 | + { |
| 84 | + // Loop through rows and cells in a table. |
| 85 | + foreach (WTableRow row in table.Rows) |
| 86 | + { |
| 87 | + foreach (WTableCell cell in row.Cells) |
| 88 | + { |
| 89 | + // Reuse text body iteration logic for table cells. |
| 90 | + IterateTextBody(cell); |
| 91 | + } |
| 92 | + } |
| 93 | + } |
| 94 | + |
| 95 | + // Method to iterate through paragraphs and remove page breaks. |
| 96 | + static void IterateParagraph(ParagraphItemCollection paraItems, WParagraph paragraph) |
| 97 | + { |
| 98 | + if (paragraph != null) |
| 99 | + { |
| 100 | + // Loop through the paragraph items in reverse order to check for page breaks. |
| 101 | + for (int i = paraItems.Count - 1; i >= 0; i--) |
| 102 | + { |
| 103 | + ParagraphItem item = paraItems[i]; |
| 104 | + if (item is Break && (item as Break).BreakType == BreakType.PageBreak) |
| 105 | + { |
| 106 | + count++; // Count the page break. |
| 107 | + if (count % 2 != 0) |
| 108 | + paraItems.Remove(item); // Remove the page break if count is odd. |
| 109 | + } |
| 110 | + } |
| 111 | + } |
| 112 | + } |
| 113 | + |
| 114 | + // Method to get data from a JSON file and convert it to a DataTable for mail merge. |
| 115 | + private static DataTable GetDataTable() |
| 116 | + { |
| 117 | + string jsonString = File.ReadAllText(Path.GetFullPath(@"../../../Data/Data.json")); |
| 118 | + DataTable dataTable = new DataTable("Employees"); |
| 119 | + JObject json = JObject.Parse(jsonString); |
| 120 | + |
| 121 | + bool columnsAdded = false; |
| 122 | + foreach (var item in json["Employees"]) |
| 123 | + { |
| 124 | + // Add columns once. |
| 125 | + if (!columnsAdded) |
| 126 | + { |
| 127 | + foreach (JProperty property in item) |
| 128 | + { |
| 129 | + dataTable.Columns.Add(property.Name, typeof(string)); |
| 130 | + } |
| 131 | + columnsAdded = true; |
| 132 | + } |
| 133 | + |
| 134 | + // Add rows to DataTable. |
| 135 | + DataRow row = dataTable.NewRow(); |
| 136 | + foreach (JProperty property in item) |
| 137 | + { |
| 138 | + row[property.Name] = property.Value.ToString(); |
| 139 | + } |
| 140 | + dataTable.Rows.Add(row); |
| 141 | + } |
| 142 | + |
| 143 | + return dataTable; |
| 144 | + } |
| 145 | + } |
| 146 | +} |
0 commit comments