title: Programmatically search formatted text in Word document and surround with tags
body: <p>I'm using Word interop with C# to convert a set of Word documents to HTML. These conversions require a couple of manual interventions which is why I'm creating this "middle station" where the necessary adjustments can be made. And all the fully automatic conversion tools I've find create a lot of inline styling and other things I don't want. One thing I'd like to handle automatically, though, is to find all text parts in italics and surround them by &lt; em > tags (or maybe rather replace them with the same text surrounded by tags).</p>
  
  <p>I have read what they have to say here: <a href="http://msdn.microsoft.com/en-us/library/f1f367bx.aspx" rel="nofollow">http://msdn.microsoft.com/en-us/library/f1f367bx.aspx</a> (for example "Use a Find object to loop through a Microsoft Office Word document and search for specific text, formatting, or style") and I know how to find one text and replace it with another, but I haven't been able to figure out how to find formatting to begin with, let alone how to insert other text around it. Any pointers would be appreciated.</p>
  
  <p>Edit: I tried a regex (<a href="https://support.office.com/en-ca/article/Find-and-replace-text-by-using-regular-expressions-Advanced-eeaa03b0-e9f3-4921-b1e8-85b0ad1c427f" rel="nofollow">https://support.office.com/en-ca/article/Find-and-replace-text-by-using-regular-expressions-Advanced-eeaa03b0-e9f3-4921-b1e8-85b0ad1c427f</a>) but it doesn't seem like placeholders work in interop. Otherwise something like this could have worked (if the placeholder hadn't been interpreted as an unknown escape sequence):</p>
  
  <pre><code>findObject.Text = "(*)";
  findObject.Font.Italic = 1;
  findObject.Replacement.Text = "&lt;em&gt;\1&lt;/em&gt;";
  </code></pre>
  
  <p>Edit 2:
  I may be on the right track, but there are two problems left. This code shows me each italic word one after another:</p>
  
  <pre><code>Range rng = doc.Range();
  rng.Find.ClearFormatting();
  object missing = Type.Missing;
  rng.Find.Font.Italic = 1;
  
  while(rng.Find.Execute("&lt;*&gt;",
      ref missing, ref missing, true, ref missing, ref missing, ref missing,
      ref missing, true, ref missing, ref missing, ref missing, ref missing,
      ref missing, ref missing)) {
          rng.Select();
          string txt = application.Selection.Text;
          application.Selection.Text.Replace(txt, "&lt;em&gt;" + txt + "&lt;/em&gt;");
          application.Selection.InsertBefore("&lt;em&gt;");
          MessageBox.Show(application.Selection.Text);
  }
  </code></pre>
  
  <p>Then I assumed that I could do something like this:</p>
  
  <pre><code>application.Selection.InsertBefore("&lt;em&gt;");
  application.Selection.InsertAfter("&lt;/em&gt;");
  </code></pre>
  
  <p>or this:</p>
  
  <pre><code>string txt = application.Selection.Text;
  application.Selection.Text.Replace(txt, "&lt;em&gt;" + txt + "&lt;/em&gt;");
  </code></pre>
  
  <p>But in the first case Visual Studio basically freezes (or takes forever), in the second case nothing is replaced.</p>
  
  <p>So problem No 1 is how to replace the selection in this context.
  Problem No 2 is how to make the regex select complete italic strings, not just single words. Using @ after * to indicate "one or more" returns one character at a time and it doesn't seem to be possible to make it greedier. But the second problem is easy to solve afterwards (in post-interop mode) if I just get those tags into the text.</p>
  
  <p>Yet another edit:</p>
  
  <p>application.Selection.InsertBefore("X"); does indeed work if I stick to letters and numbers. As soon as I try to insert &lt; or other special characters used in Word-style regular expressions it becomes extremely slow. So maybe I'll just use some guaranteed unique combinations and replace them later, such as "ssttaarrtt" and "eenndd". Silly. :)</p>