Example T1280328
Visible to All Users

Word Processing Document API - Iterate through all Sub-documents in a Document

This example implements an extension method for RichEditDocumentServer.Document and specify a delegate that will be executed for each SubDocument in a document. This approach allows you to modify the entire document content in a single place.

Implementation Details

RichEditDocumentServer's document is split into logical parts - SubDocuments. The document body, text boxes, comments, headers and footers for different document sections are stored in separate SubDocuments. Each SubDocument contains its own textual content, fields, bookmarks, hyperlinks, images, and shapes. In scenarios when such document elements should be edited for the entire document, it's necessary to get all document SubDocuments and edit each SubDocument separately.

Files to Review

C# Visual Basic
Program.cs Program.vb
SubDocumentHelper.cs SubDocumentHelper.vb

Documentation

Does this example address your development requirements/objectives?

(you will be redirected to DevExpress.com to submit your response)

Example Code

Program.cs(vb)
C#
using System; using DevExpress.XtraRichEdit.API.Native; using DevExpress.XtraRichEdit; using System.Drawing; using System.Diagnostics; namespace SubDocumentIterator { class Program { /// <summary> /// The main entry point for the application. /// </summary> static void Main() { using (RichEditDocumentServer wordProcessor = new RichEditDocumentServer()) { wordProcessor.LoadDocument("template.docx"); Document document = wordProcessor.Document; AskAction(document); wordProcessor.SaveDocument("Modified.docx", DocumentFormat.OpenXml); } var p = new Process(); p.StartInfo = new ProcessStartInfo(@"Modified.docx") { UseShellExecute = true }; p.Start(); } static private void AskAction(Document document) { Console.WriteLine("Enter a command's index.\r\nAvailable commands:\r\n1. Update Fields\r\n2. Remove Bookmarks\r\n3. Replace Text\r\n4. Highlight Text"); var answer = Console.ReadLine(); switch (answer) { case "1": { document.ForEachSubDocument((subdoc => { subdoc.Fields.Update(); })); break; } case "2": { document.ForEachSubDocument((subdoc => { for (int i = subdoc.Bookmarks.Count - 1; i >= 0; i--) subdoc.Bookmarks.Remove(subdoc.Bookmarks[i]); })); break; } case "3": { document.ForEachSubDocument((subdoc => { subdoc.ReplaceAll("test text", "Hello!!!", SearchOptions.None); })); break; } case "4": { document.ForEachSubDocument((subdoc => { DocumentRange[] ranges = subdoc.FindAll("time", SearchOptions.None); foreach (DocumentRange range in ranges) { CharacterProperties cp = subdoc.BeginUpdateCharacters(range); cp.ForeColor = Color.Red; cp.BackColor = Color.Lavender; subdoc.EndUpdateCharacters(cp); } })); break; } } Console.WriteLine("Do you want to perform another action? If no, the document is saved and opened in the Word. Y/N"); var answerReply = Console.ReadLine()?.ToLower(); if (answerReply == "y") { AskAction(document); } } } }
SubDocumentHelper.cs(vb)
C#
using DevExpress.XtraRichEdit.API.Native; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace SubDocumentIterator { public static class SubDocumentHelper { public delegate void SubDocumentDelegate(SubDocument subDocument); public static void ForEachSubDocument(this Document document, SubDocumentDelegate subDocumentProcessor) { subDocumentProcessor(document); ProcessShapes(document.Shapes, subDocumentProcessor); ProcessComments(document.Comments, subDocumentProcessor); foreach (Section section in document.Sections) { ProcessSection(section, HeaderFooterType.First, subDocumentProcessor); ProcessSection(section, HeaderFooterType.Odd, subDocumentProcessor); ProcessSection(section, HeaderFooterType.Even, subDocumentProcessor); } } private static void ProcessSection(Section section, HeaderFooterType headerFooterType, SubDocumentDelegate subDocumentProcessor) { if (section.HasHeader(headerFooterType)) { SubDocument header = section.BeginUpdateHeader(headerFooterType); subDocumentProcessor(header); ProcessShapes(header.Shapes, subDocumentProcessor); section.EndUpdateHeader(header); } if (section.HasFooter(headerFooterType)) { SubDocument footer = section.BeginUpdateFooter(headerFooterType); subDocumentProcessor(footer); ProcessShapes(footer.Shapes, subDocumentProcessor); section.EndUpdateFooter(footer); } } private static void ProcessShapes(ShapeCollection shapes, SubDocumentDelegate subDocumentProcessor) { foreach (Shape shape in shapes) if (shape.ShapeFormat.TextBox != null) subDocumentProcessor(shape.ShapeFormat.TextBox.Document); } private static void ProcessComments(CommentCollection comments, SubDocumentDelegate subDocumentProcessor) { foreach (Comment comment in comments) { SubDocument commentSubDocument = comment.BeginUpdate(); subDocumentProcessor(commentSubDocument); comment.EndUpdate(commentSubDocument); } } } }

Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.

Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.