ReplaceTextFmt2.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 almost identical to ReplaceTextFmt
    // but uses PersistentRange instead of Range.
    // Its primary purpose is to illustrate the differences between
    // Range and PersistentRange.
    public class ReplaceTextFmt2
    {
        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<PersistentRange> runRanges = new List<PersistentRange>(runs.Count);
            foreach (var run in runs)
                runRanges.Add(run.GetPersistentRange());

            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 pos = 0;
                foreach (Match m in matches)
                {
                    rr.Runs.Add(str.Substring(pos, m.Index - pos)).Font.Color.RGB = color;
                    rr.Runs.Add(tRepl).Font.Color.RGB = Color.Red;
                    pos = m.Index + m.Length;
                }
                rr.Runs.Add(str.Substring(pos)).Font.Color.RGB = color;

                if (!string.IsNullOrEmpty(rr.Runs.First.GetRange().Text))
                    throw new Exception("Unexpected");
                rr.Runs.First.Delete();

                // PersistentRange is kept up to date when the document changes,
                // so it should be disposed when no longer needed to improve
                // performance and reduce memory consumption:
                rr.Dispose();
            }
            // 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;
        }
    }
}