Search code examples
c#ms-wordrtftextwriterwpf-extended-toolkit

MS Word shows only first record from a rtf file created by TextWriter


I'm using TextWriter to make a RTF file based on a string.

TextWriter tw = new StreamWriter(@"C:\test\test.rtf",false,Encoding.GetEncoding("iso-8859-1"));
tw.Write(text);

Beneath is the string I feed to TextWriter. I built it using String.Concat<T>(IEnumerable<T>) The values in that collection have been turned into RTF by Xceed.Wpf.Toolkit.RichTextBox

"{\\rtf1\\ansi\\ansicpg1252\\uc1\\htmautsp\\deff2{\\fonttbl{\\f0\\fcharset0 Times New Roman;}{\\f2\\fcharset0 Segoe UI;}}{\\colortbl\

\red0\\green0\\blue0;\\red255\\green255\\blue255;}\\loch\\hich\\dbch\\pard\\plain\\ltrpar\\itap0{\\lang1033\\fs24\\f2\\cf0 \\cf0\\ql{\

\f2 {\\b\\ltrch test.}\\li0\\ri0\\sa0\\sb0\\fi0\\ql\\par}\r\n{\\f2 {\\b\\ltrch (test, test, test, test)}\\li0\\ri0\\sa0\\sb0\\fi0\\ql\

\par}\r\n{\\f2 \\li0\\ri0\\sa0\\sb0\\fi0\\ql\\par}\r\n{\\f2 {\\ltrch test: test}\\li0\\ri0\\sa0\\sb0\\fi0\\ql\\par}\r\n}\r\n}{\\rtf1\

\ansi\\ansicpg1252\\uc1\\htmautsp\\deff2{\\fonttbl{\\f0\\fcharset0 Times New Roman;}{\\f2\\fcharset0 Segoe UI;}}{\\colortbl\\red0\

\green0\\blue0;\\red255\\green255\\blue255;}\\loch\\hich\\dbch\\pard\\plain\\ltrpar\\itap0{\\lang1033\\fs24\\f2\\cf0 \\cf0\\ql{\\f2 {\

\b\\ltrch test.}\\li0\\ri0\\sa0\\sb0\\fi0\\ql\\par}\r\n{\\f2 {\\b\\ltrch (test, test, test, test)}\\li0\\ri0\\sa0\\sb0\\fi0\\ql\\par}\r

\n{\\f2 \\li0\\ri0\\sa0\\sb0\\fi0\\ql\\par}\r\n{\\f2 {\\ltrch test: test}\\li0\\ri0\\sa0\\sb0\\fi0\\ql\\par}\r\n}\r\n}"

This is the RTF file:

{\rtf1\ansi\ansicpg1252\uc1\htmautsp\deff2{\fonttbl{\f0\fcharset0 Times New Roman;}{\f2\fcharset0 Segoe UI;}}{\colortbl

\red0\green0\blue0;\red255\green255\blue255;}\loch\hich\dbch\pard\plain\ltrpar\itap0{\lang1033\fs24\f2\cf0 \cf0\ql{\f2 {\b\ltrch 

test.}\li0\ri0\sa0\sb0\fi0\ql\par}
{\f2 {\b\ltrch (test, test, test, test)}\li0\ri0\sa0\sb0\fi0\ql\par}
{\f2 \li0\ri0\sa0\sb0\fi0\ql\par}
{\f2 {\ltrch test: test}\li0\ri0\sa0\sb0\fi0\ql\par}
}
}{\rtf1\ansi\ansicpg1252\uc1\htmautsp\deff2{\fonttbl{\f0\fcharset0 Times New Roman;}{\f2\fcharset0 Segoe UI;}}{\colortbl

\red0\green0\blue0;\red255\green255\blue255;}\loch\hich\dbch\pard\plain\ltrpar\itap0{\lang1033\fs24\f2\cf0 \cf0\ql{\f2 {\b\ltrch 

test.}\li0\ri0\sa0\sb0\fi0\ql\par}
{\f2 {\b\ltrch (test, test, test, test)}\li0\ri0\sa0\sb0\fi0\ql\par}
{\f2 \li0\ri0\sa0\sb0\fi0\ql\par}
{\f2 {\ltrch test: test}\li0\ri0\sa0\sb0\fi0\ql\par}
}
}

It opens fine in Notepad. But I have to remove 2 curly braces (the }{ just before the 2nd rtf1 tag) to get MS Word to display the whole file:

{\rtf1\ansi\ansicpg1252\uc1\htmautsp\deff2{\fonttbl{\f0\fcharset0 Times New Roman;}{\f2\fcharset0 Segoe UI;}}{\colortbl

\red0\green0\blue0;\red255\green255\blue255;}\loch\hich\dbch\pard\plain\ltrpar\itap0{\lang1033\fs24\f2\cf0 \cf0\ql{\f2 {\b\ltrch 

test.}\li0\ri0\sa0\sb0\fi0\ql\par}
{\f2 {\b\ltrch (test, test, test, test)}\li0\ri0\sa0\sb0\fi0\ql\par}
{\f2 \li0\ri0\sa0\sb0\fi0\ql\par}
{\f2 {\ltrch test: test}\li0\ri0\sa0\sb0\fi0\ql\par}
}
\rtf1\ansi\ansicpg1252\uc1\htmautsp\deff2{\fonttbl{\f0\fcharset0 Times New Roman;}{\f2\fcharset0 Segoe UI;}}{\colortbl

\red0\green0\blue0;\red255\green255\blue255;}\loch\hich\dbch\pard\plain\ltrpar\itap0{\lang1033\fs24\f2\cf0 \cf0\ql{\f2 {\b\ltrch 

test.}\li0\ri0\sa0\sb0\fi0\ql\par}
{\f2 {\b\ltrch (test, test, test, test)}\li0\ri0\sa0\sb0\fi0\ql\par}
{\f2 \li0\ri0\sa0\sb0\fi0\ql\par}
{\f2 {\ltrch test: test}\li0\ri0\sa0\sb0\fi0\ql\par}
}
}

Untill i remove those braces, Word shows only the first record:

test.
(test, test, test, test)

test: test

instead of the whole document:

test.
(test, test, test, test)

test: test
test.
(test, test, test, test)

test: test

I've tried to google a solution, to no avail. Any help would be appreciated.


Solution

  • The {\rtf1 code tells the word processor that the document has begun; after that, it bracket-matches until it finds a matching bracket, which is the first character of your }{ pair. Technically, the reader has done what it's supposed to -- read a complete RTF document -- then it stops reading.

    It would seem to me that you are using your WPF control to construct many complete RTF documents, then concatenating them together, and hoping Word will read them all as if they were a single document, which it doesn't.

    So it's like generating a web page by concatenating together <html> elements;

    <html>
        <head>
        </head>
        <body>
            <p>para 1</para
        </body>
    </html>
    <html>
        <head>
        </head>
        <body>
            <p>para 1</para
        </body>
    </html>
    

    where really you want to concatenate together the contents of the body tags, or avoid concatenating at all.

    My guess is you're converting a batch of text, and the right way would be to load up the control with the complete content. Pseudocode would be something like;

      var ctrl = new Xceed.Wpf.Toolkit.RichTextBox();
      foreach(var textToConvert in input)
      {
           ctrl.AppendText(textToConvert);
      }
    
      var doc = ctrl.Document;
      var content = new TextRange(doc.ContentStart, doc.ContentEnd);
    
      if (content.CanSave(DataFormats.Rtf))
      {
          using (var stream = new MemoryStream())
          {
              content.Save(stream, DataFormats.Rtf);
          }
      }