https://docx.codeplex.com/workitem/13827 - to preserve Formatting during replace operations https://docx.codeplex.com/workitem/13831 - proper RegEx support allowing RegEx search pattern and substitutions in ReplaceTextmaster
| return uniqueResults.Keys.ToList(); // return the unique list of results | return uniqueResults.Keys.ToList(); // return the unique list of results | ||||
| } | } | ||||
| public virtual void ReplaceText(string searchValue, string newValue, bool trackChanges = false, RegexOptions options = RegexOptions.None, Formatting newFormatting = null, Formatting matchFormatting = null, MatchFormattingOptions formattingOptions = MatchFormattingOptions.SubsetMatch) | |||||
| public virtual void ReplaceText(string searchValue, string newValue, bool trackChanges = false, RegexOptions options = RegexOptions.None, Formatting newFormatting = null, Formatting matchFormatting = null, MatchFormattingOptions formattingOptions = MatchFormattingOptions.SubsetMatch, bool escapeRegEx = true, bool useRegExSubstitutions = false) | |||||
| { | { | ||||
| if (string.IsNullOrEmpty(searchValue)) | if (string.IsNullOrEmpty(searchValue)) | ||||
| throw new ArgumentException("oldValue cannot be null or empty", "searchValue"); | throw new ArgumentException("oldValue cannot be null or empty", "searchValue"); | ||||
| foreach (var header in headerList) | foreach (var header in headerList) | ||||
| if (header != null) | if (header != null) | ||||
| foreach (var paragraph in header.Paragraphs) | foreach (var paragraph in header.Paragraphs) | ||||
| paragraph.ReplaceText(searchValue, newValue, trackChanges, options, newFormatting, matchFormatting, formattingOptions); | |||||
| paragraph.ReplaceText(searchValue, newValue, trackChanges, options, newFormatting, matchFormatting, formattingOptions, escapeRegEx, useRegExSubstitutions); | |||||
| // ReplaceText int main body of document. | // ReplaceText int main body of document. | ||||
| foreach (var paragraph in Paragraphs) | foreach (var paragraph in Paragraphs) | ||||
| paragraph.ReplaceText(searchValue, newValue, trackChanges, options, newFormatting, matchFormatting, formattingOptions); | |||||
| paragraph.ReplaceText(searchValue, newValue, trackChanges, options, newFormatting, matchFormatting, formattingOptions, escapeRegEx, useRegExSubstitutions); | |||||
| // ReplaceText in Footers of the document. | // ReplaceText in Footers of the document. | ||||
| var footerList = new List<Footer> { Document.Footers.first, Document.Footers.even, Document.Footers.odd }; | var footerList = new List<Footer> { Document.Footers.first, Document.Footers.even, Document.Footers.odd }; | ||||
| foreach (var footer in footerList) | foreach (var footer in footerList) | ||||
| if (footer != null) | if (footer != null) | ||||
| foreach (var paragraph in footer.Paragraphs) | foreach (var paragraph in footer.Paragraphs) | ||||
| paragraph.ReplaceText(searchValue, newValue, trackChanges, options, newFormatting, matchFormatting, formattingOptions); | |||||
| paragraph.ReplaceText(searchValue, newValue, trackChanges, options, newFormatting, matchFormatting, formattingOptions, escapeRegEx, useRegExSubstitutions); | |||||
| } | } | ||||
| /// <summary> | /// <summary> |
| /// </summary> | /// </summary> | ||||
| public class Formatting : IComparable | public class Formatting : IComparable | ||||
| { | { | ||||
| private XElement rPr; | |||||
| private bool hidden; | |||||
| private bool bold; | |||||
| private bool italic; | |||||
| private StrikeThrough strikethrough; | |||||
| private Script script; | |||||
| private Highlight highlight; | |||||
| private double? size; | |||||
| private Color? fontColor; | |||||
| private Color? underlineColor; | |||||
| private UnderlineStyle underlineStyle; | |||||
| private Misc misc; | |||||
| private CapsStyle capsStyle; | |||||
| private FontFamily fontFamily; | |||||
| private int? percentageScale; | |||||
| private int? kerning; | |||||
| private int? position; | |||||
| private double? spacing; | |||||
| private CultureInfo language; | |||||
| private XElement rPr; | |||||
| private bool? hidden; | |||||
| private bool? bold; | |||||
| private bool? italic; | |||||
| private StrikeThrough? strikethrough; | |||||
| private Script? script; | |||||
| private Highlight? highlight; | |||||
| private double? size; | |||||
| private Color? fontColor; | |||||
| private Color? underlineColor; | |||||
| private UnderlineStyle? underlineStyle; | |||||
| private Misc? misc; | |||||
| private CapsStyle? capsStyle; | |||||
| private FontFamily fontFamily; | |||||
| private int? percentageScale; | |||||
| private int? kerning; | |||||
| private int? position; | |||||
| private double? spacing; | |||||
| private CultureInfo language; | |||||
| /// <summary> | /// <summary> | ||||
| /// A text formatting. | /// A text formatting. | ||||
| /// </summary> | /// </summary> | ||||
| public Formatting() | public Formatting() | ||||
| { | { | ||||
| capsStyle = CapsStyle.none; | |||||
| strikethrough = StrikeThrough.none; | |||||
| script = Script.none; | |||||
| highlight = Highlight.none; | |||||
| underlineStyle = UnderlineStyle.none; | |||||
| misc = Misc.none; | |||||
| capsStyle = Novacode.CapsStyle.none; | |||||
| strikethrough = Novacode.StrikeThrough.none; | |||||
| script = Novacode.Script.none; | |||||
| highlight = Novacode.Highlight.none; | |||||
| underlineStyle = Novacode.UnderlineStyle.none; | |||||
| misc = Novacode.Misc.none; | |||||
| // Use current culture by default | // Use current culture by default | ||||
| language = CultureInfo.CurrentCulture; | language = CultureInfo.CurrentCulture; | ||||
| } | } | ||||
| } | } | ||||
| public static Formatting Parse(XElement rPr) | |||||
| /// <summary> | |||||
| /// Returns a new identical instance of Formatting. | |||||
| /// </summary> | |||||
| /// <returns></returns> | |||||
| public Formatting Clone() | |||||
| { | |||||
| Formatting newf = new Formatting(); | |||||
| newf.Bold = bold; | |||||
| newf.CapsStyle = capsStyle; | |||||
| newf.FontColor = fontColor; | |||||
| newf.FontFamily = fontFamily; | |||||
| newf.Hidden = hidden; | |||||
| newf.Highlight = highlight; | |||||
| newf.Italic = italic; | |||||
| if (kerning.HasValue) { newf.Kerning = kerning; } | |||||
| newf.Language = language; | |||||
| newf.Misc = misc; | |||||
| if (percentageScale.HasValue) { newf.PercentageScale = percentageScale; } | |||||
| if (position.HasValue) { newf.Position = position; } | |||||
| newf.Script = script; | |||||
| if (size.HasValue) { newf.Size = size; } | |||||
| if (spacing.HasValue) { newf.Spacing = spacing; } | |||||
| newf.StrikeThrough = strikethrough; | |||||
| newf.UnderlineColor = underlineColor; | |||||
| newf.UnderlineStyle = underlineStyle; | |||||
| return newf; | |||||
| } | |||||
| public static Formatting Parse(XElement rPr) | |||||
| { | { | ||||
| Formatting formatting = new Formatting(); | Formatting formatting = new Formatting(); | ||||
| ); | ); | ||||
| } | } | ||||
| if(hidden) | |||||
| rPr.Add(new XElement(XName.Get("vanish", DocX.w.NamespaceName))); | |||||
| if (bold) | |||||
| rPr.Add(new XElement(XName.Get("b", DocX.w.NamespaceName))); | |||||
| if (italic) | |||||
| rPr.Add(new XElement(XName.Get("i", DocX.w.NamespaceName))); | |||||
| switch (underlineStyle) | |||||
| { | |||||
| case UnderlineStyle.none: | |||||
| break; | |||||
| case UnderlineStyle.singleLine: | |||||
| rPr.Add(new XElement(XName.Get("u", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), "single"))); | |||||
| break; | |||||
| case UnderlineStyle.doubleLine: | |||||
| rPr.Add(new XElement(XName.Get("u", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), "double"))); | |||||
| break; | |||||
| default: | |||||
| rPr.Add(new XElement(XName.Get("u", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), underlineStyle.ToString()))); | |||||
| break; | |||||
| } | |||||
| if (hidden.HasValue && hidden.Value) | |||||
| rPr.Add(new XElement(XName.Get("vanish", DocX.w.NamespaceName))); | |||||
| if (bold.HasValue && bold.Value) | |||||
| rPr.Add(new XElement(XName.Get("b", DocX.w.NamespaceName))); | |||||
| if (italic.HasValue && italic.Value) | |||||
| rPr.Add(new XElement(XName.Get("i", DocX.w.NamespaceName))); | |||||
| if (underlineStyle.HasValue) | |||||
| { | |||||
| switch (underlineStyle) | |||||
| { | |||||
| case Novacode.UnderlineStyle.none: | |||||
| break; | |||||
| case Novacode.UnderlineStyle.singleLine: | |||||
| rPr.Add(new XElement(XName.Get("u", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), "single"))); | |||||
| break; | |||||
| case Novacode.UnderlineStyle.doubleLine: | |||||
| rPr.Add(new XElement(XName.Get("u", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), "double"))); | |||||
| break; | |||||
| default: | |||||
| rPr.Add(new XElement(XName.Get("u", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), underlineStyle.ToString()))); | |||||
| break; | |||||
| } | |||||
| } | |||||
| if(underlineColor.HasValue) | if(underlineColor.HasValue) | ||||
| { | { | ||||
| // If an underlineColor has been set but no underlineStyle has been set | // If an underlineColor has been set but no underlineStyle has been set | ||||
| if (underlineStyle == UnderlineStyle.none) | |||||
| if (underlineStyle == Novacode.UnderlineStyle.none) | |||||
| { | { | ||||
| // Set the underlineStyle to the default | // Set the underlineStyle to the default | ||||
| underlineStyle = UnderlineStyle.singleLine; | |||||
| underlineStyle = Novacode.UnderlineStyle.singleLine; | |||||
| rPr.Add(new XElement(XName.Get("u", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), "single"))); | rPr.Add(new XElement(XName.Get("u", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), "single"))); | ||||
| } | } | ||||
| rPr.Element(XName.Get("u", DocX.w.NamespaceName)).Add(new XAttribute(XName.Get("color", DocX.w.NamespaceName), underlineColor.Value.ToHex())); | rPr.Element(XName.Get("u", DocX.w.NamespaceName)).Add(new XAttribute(XName.Get("color", DocX.w.NamespaceName), underlineColor.Value.ToHex())); | ||||
| } | } | ||||
| switch (strikethrough) | |||||
| { | |||||
| case StrikeThrough.none: | |||||
| break; | |||||
| case StrikeThrough.strike: | |||||
| rPr.Add(new XElement(XName.Get("strike", DocX.w.NamespaceName))); | |||||
| break; | |||||
| case StrikeThrough.doubleStrike: | |||||
| rPr.Add(new XElement(XName.Get("dstrike", DocX.w.NamespaceName))); | |||||
| break; | |||||
| default: | |||||
| break; | |||||
| } | |||||
| switch (script) | |||||
| { | |||||
| case Script.none: | |||||
| break; | |||||
| default: | |||||
| rPr.Add(new XElement(XName.Get("vertAlign", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), script.ToString()))); | |||||
| break; | |||||
| } | |||||
| if (size.HasValue) | |||||
| if (strikethrough.HasValue) | |||||
| { | |||||
| switch (strikethrough) | |||||
| { | |||||
| case Novacode.StrikeThrough.none: | |||||
| break; | |||||
| case Novacode.StrikeThrough.strike: | |||||
| rPr.Add(new XElement(XName.Get("strike", DocX.w.NamespaceName))); | |||||
| break; | |||||
| case Novacode.StrikeThrough.doubleStrike: | |||||
| rPr.Add(new XElement(XName.Get("dstrike", DocX.w.NamespaceName))); | |||||
| break; | |||||
| default: | |||||
| break; | |||||
| } | |||||
| } | |||||
| if (script.HasValue) | |||||
| { | |||||
| switch (script) | |||||
| { | |||||
| case Novacode.Script.none: | |||||
| break; | |||||
| default: | |||||
| rPr.Add(new XElement(XName.Get("vertAlign", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), script.ToString()))); | |||||
| break; | |||||
| } | |||||
| } | |||||
| if (size.HasValue) | |||||
| { | { | ||||
| rPr.Add(new XElement(XName.Get("sz", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), (size * 2).ToString()))); | rPr.Add(new XElement(XName.Get("sz", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), (size * 2).ToString()))); | ||||
| rPr.Add(new XElement(XName.Get("szCs", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), (size * 2).ToString()))); | rPr.Add(new XElement(XName.Get("szCs", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), (size * 2).ToString()))); | ||||
| if(fontColor.HasValue) | if(fontColor.HasValue) | ||||
| rPr.Add(new XElement(XName.Get("color", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), fontColor.Value.ToHex()))); | rPr.Add(new XElement(XName.Get("color", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), fontColor.Value.ToHex()))); | ||||
| switch (highlight) | |||||
| { | |||||
| case Highlight.none: | |||||
| break; | |||||
| default: | |||||
| rPr.Add(new XElement(XName.Get("highlight", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), highlight.ToString()))); | |||||
| break; | |||||
| } | |||||
| switch (capsStyle) | |||||
| { | |||||
| case CapsStyle.none: | |||||
| break; | |||||
| default: | |||||
| rPr.Add(new XElement(XName.Get(capsStyle.ToString(), DocX.w.NamespaceName))); | |||||
| break; | |||||
| } | |||||
| switch (misc) | |||||
| { | |||||
| case Misc.none: | |||||
| break; | |||||
| case Misc.outlineShadow: | |||||
| rPr.Add(new XElement(XName.Get("outline", DocX.w.NamespaceName))); | |||||
| rPr.Add(new XElement(XName.Get("shadow", DocX.w.NamespaceName))); | |||||
| break; | |||||
| case Misc.engrave: | |||||
| rPr.Add(new XElement(XName.Get("imprint", DocX.w.NamespaceName))); | |||||
| break; | |||||
| default: | |||||
| rPr.Add(new XElement(XName.Get(misc.ToString(), DocX.w.NamespaceName))); | |||||
| break; | |||||
| } | |||||
| return rPr; | |||||
| if (highlight.HasValue) | |||||
| { | |||||
| switch (highlight) | |||||
| { | |||||
| case Novacode.Highlight.none: | |||||
| break; | |||||
| default: | |||||
| rPr.Add(new XElement(XName.Get("highlight", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), highlight.ToString()))); | |||||
| break; | |||||
| } | |||||
| } | |||||
| if (capsStyle.HasValue) | |||||
| { | |||||
| switch (capsStyle) | |||||
| { | |||||
| case Novacode.CapsStyle.none: | |||||
| break; | |||||
| default: | |||||
| rPr.Add(new XElement(XName.Get(capsStyle.ToString(), DocX.w.NamespaceName))); | |||||
| break; | |||||
| } | |||||
| } | |||||
| if (misc.HasValue) | |||||
| { | |||||
| switch (misc) | |||||
| { | |||||
| case Novacode.Misc.none: | |||||
| break; | |||||
| case Novacode.Misc.outlineShadow: | |||||
| rPr.Add(new XElement(XName.Get("outline", DocX.w.NamespaceName))); | |||||
| rPr.Add(new XElement(XName.Get("shadow", DocX.w.NamespaceName))); | |||||
| break; | |||||
| case Novacode.Misc.engrave: | |||||
| rPr.Add(new XElement(XName.Get("imprint", DocX.w.NamespaceName))); | |||||
| break; | |||||
| default: | |||||
| rPr.Add(new XElement(XName.Get(misc.ToString(), DocX.w.NamespaceName))); | |||||
| break; | |||||
| } | |||||
| } | |||||
| return rPr; | |||||
| } | } | ||||
| } | } | ||||
| /// <summary> | /// <summary> | ||||
| /// This formatting will apply Bold. | /// This formatting will apply Bold. | ||||
| /// </summary> | /// </summary> | ||||
| public bool Bold { get { return bold; } set { bold = value;} } | |||||
| public bool? Bold { get { return bold; } set { bold = value;} } | |||||
| /// <summary> | /// <summary> | ||||
| /// This formatting will apply Italic. | /// This formatting will apply Italic. | ||||
| /// </summary> | /// </summary> | ||||
| public bool Italic { get { return italic; } set { italic = value; } } | |||||
| public bool? Italic { get { return italic; } set { italic = value; } } | |||||
| /// <summary> | /// <summary> | ||||
| /// This formatting will apply StrickThrough. | /// This formatting will apply StrickThrough. | ||||
| /// </summary> | /// </summary> | ||||
| public StrikeThrough StrikeThrough { get { return strikethrough; } set { strikethrough = value; } } | |||||
| public StrikeThrough? StrikeThrough { get { return strikethrough; } set { strikethrough = value; } } | |||||
| /// <summary> | /// <summary> | ||||
| /// The script that this formatting should be, normal, superscript or subscript. | /// The script that this formatting should be, normal, superscript or subscript. | ||||
| /// </summary> | /// </summary> | ||||
| public Script Script { get { return script; } set { script = value; } } | |||||
| public Script? Script { get { return script; } set { script = value; } } | |||||
| /// <summary> | /// <summary> | ||||
| /// The Size of this text, must be between 0 and 1638. | /// The Size of this text, must be between 0 and 1638. | ||||
| /// <summary> | /// <summary> | ||||
| /// Highlight colour. | /// Highlight colour. | ||||
| /// </summary> | /// </summary> | ||||
| public Highlight Highlight { get { return highlight; } set { highlight = value; } } | |||||
| public Highlight? Highlight { get { return highlight; } set { highlight = value; } } | |||||
| /// <summary> | /// <summary> | ||||
| /// The Underline style that this formatting applies. | /// The Underline style that this formatting applies. | ||||
| /// </summary> | /// </summary> | ||||
| public UnderlineStyle UnderlineStyle { get { return underlineStyle; } set { underlineStyle = value; } } | |||||
| public UnderlineStyle? UnderlineStyle { get { return underlineStyle; } set { underlineStyle = value; } } | |||||
| /// <summary> | /// <summary> | ||||
| /// The underline colour. | /// The underline colour. | ||||
| /// <summary> | /// <summary> | ||||
| /// Misc settings. | /// Misc settings. | ||||
| /// </summary> | /// </summary> | ||||
| public Misc Misc { get { return misc; } set { misc = value; } } | |||||
| public Misc? Misc { get { return misc; } set { misc = value; } } | |||||
| /// <summary> | /// <summary> | ||||
| /// Is this text hidden or visible. | /// Is this text hidden or visible. | ||||
| /// </summary> | /// </summary> | ||||
| public bool Hidden { get { return hidden; } set { hidden = value; } } | |||||
| public bool? Hidden { get { return hidden; } set { hidden = value; } } | |||||
| /// <summary> | /// <summary> | ||||
| /// Capitalization style. | /// Capitalization style. | ||||
| /// </summary> | /// </summary> | ||||
| public CapsStyle CapsStyle { get { return capsStyle; } set { capsStyle = value; } } | |||||
| public CapsStyle? CapsStyle { get { return capsStyle; } set { capsStyle = value; } } | |||||
| /// <summary> | /// <summary> | ||||
| /// The font familt of this formatting. | |||||
| /// The font family of this formatting. | |||||
| /// </summary> | /// </summary> | ||||
| /// <!-- | /// <!-- | ||||
| /// Bug found and fixed by krugs525 on August 12 2009. | /// Bug found and fixed by krugs525 on August 12 2009. |
| // Get the first run effected by this Insert | // Get the first run effected by this Insert | ||||
| Run run = GetFirstRunEffectedByEdit(index); | Run run = GetFirstRunEffectedByEdit(index); | ||||
| if (run == null) | |||||
| { | |||||
| object insert; | |||||
| if (formatting != null) | |||||
| insert = HelperFunctions.FormatInput(value, formatting.Xml); | |||||
| else | |||||
| insert = HelperFunctions.FormatInput(value, null); | |||||
| if (trackChanges) | |||||
| insert = CreateEdit(EditType.ins, insert_datetime, insert); | |||||
| Xml.Add(insert); | |||||
| } | |||||
| else | |||||
| { | |||||
| object newRuns; | |||||
| if (formatting != null) | |||||
| newRuns = HelperFunctions.FormatInput(value, formatting.Xml); | |||||
| else | |||||
| newRuns = HelperFunctions.FormatInput(value, run.Xml.Element(XName.Get("rPr", DocX.w.NamespaceName))); | |||||
| if (run == null) | |||||
| { | |||||
| object insert; | |||||
| if (formatting != null) //not sure how to get original formatting here when run == null | |||||
| insert = HelperFunctions.FormatInput(value, formatting.Xml); | |||||
| else | |||||
| insert = HelperFunctions.FormatInput(value, null); | |||||
| if (trackChanges) | |||||
| insert = CreateEdit(EditType.ins, insert_datetime, insert); | |||||
| Xml.Add(insert); | |||||
| } | |||||
| else | |||||
| { | |||||
| object newRuns; | |||||
| var rprel = run.Xml.Element(XName.Get("rPr", DocX.w.NamespaceName)); | |||||
| if (formatting != null) | |||||
| { | |||||
| //merge 2 formattings properly | |||||
| Formatting finfmt = null; | |||||
| Formatting oldfmt = null; | |||||
| if (rprel != null) | |||||
| { | |||||
| oldfmt = Formatting.Parse(rprel); | |||||
| } | |||||
| if (oldfmt != null) | |||||
| { | |||||
| finfmt = oldfmt.Clone(); | |||||
| if (formatting.Bold.HasValue) { finfmt.Bold = formatting.Bold; } | |||||
| if (formatting.CapsStyle.HasValue) { finfmt.CapsStyle = formatting.CapsStyle; } | |||||
| if (formatting.FontColor.HasValue) { finfmt.FontColor = formatting.FontColor; } | |||||
| finfmt.FontFamily = formatting.FontFamily; | |||||
| if (formatting.Hidden.HasValue) { finfmt.Hidden = formatting.Hidden; } | |||||
| if (formatting.Highlight.HasValue) { finfmt.Highlight = formatting.Highlight; } | |||||
| if (formatting.Italic.HasValue) { finfmt.Italic = formatting.Italic; } | |||||
| if (formatting.Kerning.HasValue) { finfmt.Kerning = formatting.Kerning; } | |||||
| finfmt.Language = formatting.Language; | |||||
| if (formatting.Misc.HasValue) { finfmt.Misc = formatting.Misc; } | |||||
| if (formatting.PercentageScale.HasValue) { finfmt.PercentageScale = formatting.PercentageScale; } | |||||
| if (formatting.Position.HasValue) { finfmt.Position = formatting.Position; } | |||||
| if (formatting.Script.HasValue) { finfmt.Script = formatting.Script; } | |||||
| if (formatting.Size.HasValue) { finfmt.Size = formatting.Size; } | |||||
| if (formatting.Spacing.HasValue) { finfmt.Spacing = formatting.Spacing; } | |||||
| if (formatting.StrikeThrough.HasValue) { finfmt.StrikeThrough = formatting.StrikeThrough; } | |||||
| if (formatting.UnderlineColor.HasValue) { finfmt.UnderlineColor = formatting.UnderlineColor; } | |||||
| if (formatting.UnderlineStyle.HasValue) { finfmt.UnderlineStyle = formatting.UnderlineStyle; } | |||||
| } | |||||
| else { | |||||
| finfmt = formatting; | |||||
| } | |||||
| newRuns = HelperFunctions.FormatInput(value, finfmt.Xml); | |||||
| } | |||||
| else | |||||
| { | |||||
| newRuns = HelperFunctions.FormatInput(value, rprel); | |||||
| } | |||||
| // The parent of this Run | // The parent of this Run | ||||
| XElement parentElement = run.Xml.Parent; | XElement parentElement = run.Xml.Parent; | ||||
| RemoveText(index, Text.Length - index, trackChanges); | RemoveText(index, Text.Length - index, trackChanges); | ||||
| } | } | ||||
| /// <summary> | |||||
| /// Replaces all occurrences of a specified System.String in this instance, with another specified System.String. | |||||
| /// </summary> | |||||
| /// <example> | |||||
| /// <code> | |||||
| /// // Load a document using a relative filename. | |||||
| /// using (DocX document = DocX.Load(@"C:\Example\Test.docx")) | |||||
| /// { | |||||
| /// // The formatting to match. | |||||
| /// Formatting matchFormatting = new Formatting(); | |||||
| /// matchFormatting.Size = 10; | |||||
| /// matchFormatting.Italic = true; | |||||
| /// matchFormatting.FontFamily = new FontFamily("Times New Roman"); | |||||
| /// | |||||
| /// // The formatting to apply to the inserted text. | |||||
| /// Formatting newFormatting = new Formatting(); | |||||
| /// newFormatting.Size = 22; | |||||
| /// newFormatting.UnderlineStyle = UnderlineStyle.dotted; | |||||
| /// newFormatting.Bold = true; | |||||
| /// | |||||
| /// // Iterate through the paragraphs in this document. | |||||
| /// foreach (Paragraph p in document.Paragraphs) | |||||
| /// { | |||||
| /// /* | |||||
| /// * Replace all instances of the string "wrong" with the string "right" and ignore case. | |||||
| /// * Each inserted instance of "wrong" should use the Formatting newFormatting. | |||||
| /// * Only replace an instance of "wrong" if it is Size 10, Italic and Times New Roman. | |||||
| /// * SubsetMatch means that the formatting must contain all elements of the match formatting, | |||||
| /// * but it can also contain additional formatting for example Color, UnderlineStyle, etc. | |||||
| /// * ExactMatch means it must not contain additional formatting. | |||||
| /// */ | |||||
| /// p.ReplaceText("wrong", "right", false, RegexOptions.IgnoreCase, newFormatting, matchFormatting, MatchFormattingOptions.SubsetMatch); | |||||
| /// } | |||||
| /// | |||||
| /// // Save all changes made to this document. | |||||
| /// document.Save(); | |||||
| /// }// Release this document from memory. | |||||
| /// </code> | |||||
| /// </example> | |||||
| /// <seealso cref="Paragraph.RemoveText(int, int, bool)"/> | |||||
| /// <seealso cref="Paragraph.RemoveText(int, bool)"/> | |||||
| /// <seealso cref="Paragraph.InsertText(int, string, bool, Formatting)"/> | |||||
| /// <seealso cref="Paragraph.InsertText(string, bool, Formatting)"/> | |||||
| /// <param name="newValue">A System.String to replace all occurances of oldValue.</param> | |||||
| /// <param name="oldValue">A System.String to be replaced.</param> | |||||
| /// <param name="options">A bitwise OR combination of RegexOption enumeration options.</param> | |||||
| /// <param name="trackChanges">Track changes</param> | |||||
| /// <param name="newFormatting">The formatting to apply to the text being inserted.</param> | |||||
| /// <param name="matchFormatting">The formatting that the text must match in order to be replaced.</param> | |||||
| /// <param name="fo">How should formatting be matched?</param> | |||||
| public void ReplaceText(string oldValue, string newValue, bool trackChanges = false, RegexOptions options = RegexOptions.None, Formatting newFormatting = null, Formatting matchFormatting = null, MatchFormattingOptions fo = MatchFormattingOptions.SubsetMatch) | |||||
| /// <summary> | |||||
| /// Replaces all occurrences of a specified System.String in this instance, with another specified System.String. | |||||
| /// </summary> | |||||
| /// <example> | |||||
| /// <code> | |||||
| /// // Load a document using a relative filename. | |||||
| /// using (DocX document = DocX.Load(@"C:\Example\Test.docx")) | |||||
| /// { | |||||
| /// // The formatting to match. | |||||
| /// Formatting matchFormatting = new Formatting(); | |||||
| /// matchFormatting.Size = 10; | |||||
| /// matchFormatting.Italic = true; | |||||
| /// matchFormatting.FontFamily = new FontFamily("Times New Roman"); | |||||
| /// | |||||
| /// // The formatting to apply to the inserted text. | |||||
| /// Formatting newFormatting = new Formatting(); | |||||
| /// newFormatting.Size = 22; | |||||
| /// newFormatting.UnderlineStyle = UnderlineStyle.dotted; | |||||
| /// newFormatting.Bold = true; | |||||
| /// | |||||
| /// // Iterate through the paragraphs in this document. | |||||
| /// foreach (Paragraph p in document.Paragraphs) | |||||
| /// { | |||||
| /// /* | |||||
| /// * Replace all instances of the string "wrong" with the string "right" and ignore case. | |||||
| /// * Each inserted instance of "wrong" should use the Formatting newFormatting. | |||||
| /// * Only replace an instance of "wrong" if it is Size 10, Italic and Times New Roman. | |||||
| /// * SubsetMatch means that the formatting must contain all elements of the match formatting, | |||||
| /// * but it can also contain additional formatting for example Color, UnderlineStyle, etc. | |||||
| /// * ExactMatch means it must not contain additional formatting. | |||||
| /// */ | |||||
| /// p.ReplaceText("wrong", "right", false, RegexOptions.IgnoreCase, newFormatting, matchFormatting, MatchFormattingOptions.SubsetMatch); | |||||
| /// } | |||||
| /// | |||||
| /// // Save all changes made to this document. | |||||
| /// document.Save(); | |||||
| /// }// Release this document from memory. | |||||
| /// </code> | |||||
| /// </example> | |||||
| /// <seealso cref="Paragraph.RemoveText(int, int, bool)"/> | |||||
| /// <seealso cref="Paragraph.RemoveText(int, bool)"/> | |||||
| /// <seealso cref="Paragraph.InsertText(int, string, bool, Formatting)"/> | |||||
| /// <seealso cref="Paragraph.InsertText(string, bool, Formatting)"/> | |||||
| /// <param name="newValue">A System.String to replace all occurrences of oldValue.</param> | |||||
| /// <param name="oldValue">A System.String to be replaced.</param> | |||||
| /// <param name="options">A bitwise OR combination of RegexOption enumeration options.</param> | |||||
| /// <param name="trackChanges">Track changes</param> | |||||
| /// <param name="newFormatting">The formatting to apply to the text being inserted.</param> | |||||
| /// <param name="matchFormatting">The formatting that the text must match in order to be replaced.</param> | |||||
| /// <param name="fo">How should formatting be matched?</param> | |||||
| /// <param name="escapeRegEx">True if the oldValue needs to be escaped, otherwise false. If it represents a valid RegEx pattern this should be false.</param> | |||||
| /// <param name="useRegExSubstitutions">True if RegEx-like replace should be performed, i.e. if newValue contains RegEx substitutions. Does not perform named-group substitutions (only numbered groups).</param> | |||||
| public void ReplaceText(string oldValue, string newValue, bool trackChanges = false, RegexOptions options = RegexOptions.None, Formatting newFormatting = null, Formatting matchFormatting = null, MatchFormattingOptions fo = MatchFormattingOptions.SubsetMatch, bool escapeRegEx = true, bool useRegExSubstitutions = false) | |||||
| { | { | ||||
| MatchCollection mc = Regex.Matches(Text, Regex.Escape(oldValue), options); | |||||
| string tText = Text; | |||||
| MatchCollection mc = Regex.Matches(tText, escapeRegEx ? Regex.Escape(oldValue) : oldValue, options); | |||||
| // Loop through the matches in reverse order | // Loop through the matches in reverse order | ||||
| foreach (Match m in mc.Cast<Match>().Reverse()) | foreach (Match m in mc.Cast<Match>().Reverse()) | ||||
| // If the formatting matches, do the replace. | // If the formatting matches, do the replace. | ||||
| if (formattingMatch) | if (formattingMatch) | ||||
| { | { | ||||
| InsertText(m.Index + oldValue.Length, newValue, trackChanges, newFormatting); | |||||
| string repl = newValue; | |||||
| //perform RegEx substitutions. Only named groups are not supported. Everything else is supported. However character escapes are not covered. | |||||
| if (useRegExSubstitutions) | |||||
| { | |||||
| repl = repl.Replace("$&", m.Value); | |||||
| if (m.Groups.Count > 0) | |||||
| { | |||||
| int lastcap = 0; | |||||
| for (int k = 0; k < m.Groups.Count; k++) | |||||
| { | |||||
| var g = m.Groups[k]; | |||||
| if ((g == null) || (g.Value == "")) | |||||
| continue; | |||||
| repl = repl.Replace("$" + k.ToString(), g.Value); | |||||
| lastcap = k; | |||||
| //cannot get named groups ATM | |||||
| } | |||||
| repl = repl.Replace("$+", m.Groups[lastcap].Value); | |||||
| } | |||||
| if (m.Index > 0) | |||||
| { | |||||
| repl = repl.Replace("$`", tText.Substring(0, m.Index)); | |||||
| } | |||||
| if ((m.Index + m.Length) < tText.Length) | |||||
| { | |||||
| repl = repl.Replace("$'", tText.Substring(m.Index + m.Length)); | |||||
| } | |||||
| repl = repl.Replace("$_", tText); | |||||
| repl = repl.Replace("$$", "$"); | |||||
| } | |||||
| InsertText(m.Index + m.Length, repl, trackChanges, newFormatting); | |||||
| RemoveText(m.Index, m.Length, trackChanges); | RemoveText(m.Index, m.Length, trackChanges); | ||||
| } | } | ||||
| } | } |