ReplaceTextFmt.cs
//
// This code is part of GrapeCity Documents for Word samples.
// Copyright (c) GrapeCity, Inc. All rights reserved.
//
using System;
using System.IO;
using System.Drawing;
using System.Text;
using System.Linq;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using GrapeCity.Documents.Word;

namespace GcWordWeb.Samples
{
    // This sample loads an existing document, finds all occurrences
    // of a certain string in it, and replaces that string with another one,
    // also changing the character format of the replacement string.
    // This sample is similar to ReplaceText, with the addition of
    // formatting change, and has the same limitation - it only finds
    // occurrences of the search string that are completely within a single run.
    // See ReplaceTextFmt2 for an example of using PersistentRange in the
    // same scenario.
    public class ReplaceTextFmt
    {
        public GcWordDocument CreateDocx()
        {
            // The document to replace text in:
            var path = Path.Combine("Resources", "WordDocs", "JsFrameworkExcerpt.docx");
            // The text to find:
            const string tFind = "javascript";
            // The replacement:
            const string tRepl = "ArabicaScroll";

            var doc = new GcWordDocument();
            doc.Load(path);

            var runs = doc.Body.Runs;
            List<Range> runRanges = new List<Range>(runs.Count);
            foreach (var run in runs)
                runRanges.Add(run.GetRange());

            foreach (var rr in runRanges)
            {
                var str = rr.Text;
                var matches = Regex.Matches(str, tFind, RegexOptions.IgnoreCase);
                if (matches.Count == 0)
                    continue;

                var color = rr.ParentRun.Font.Color.RGB;
                rr.Clear();
                var r = rr.Runs.Last;
                var pos = 0;
                foreach (Match m in matches)
                {
                    r = r.GetRange().Runs.Insert(str.Substring(pos, m.Index - pos), InsertLocation.After);
                    r.Font.Color.RGB = color;
                    r = r.GetRange().Runs.Insert(tRepl, InsertLocation.After);
                    r.Font.Color.RGB = Color.Red;
                    pos = m.Index + m.Length;
                }
                r = r.GetRange().Runs.Insert(str.Substring(pos), InsertLocation.After);
                r.Font.Color.RGB = color;
                if (!string.IsNullOrEmpty(rr.Runs.First.GetRange().Text))
                    throw new Exception("Unexpected");
                rr.Runs.First.Delete();
            }
            // Not strictky necessary but a good practice:
            runRanges.Clear();

            // Add a note at the end of the document:
            doc.Body.Sections.Last.GetRange().Paragraphs.Add(
                $"GcWord replaced '{tFind}' with '{tRepl}' on {DateTime.Now}.");

            // Done:
            return doc;
        }
    }
}