Sometimes there is need to edit an .rtf file. To my knowledge, exept the PIA Interop word, there is no free and effective tools to edit such a file. The word Interop problem is performance and also their integration in web applications which often causes problems.
I discovered by accident that the WPF RichTextBox control (exept the fact that it allows to read and write a .RTF document) allows you to edit an .RTF document programmatically. The purpose of this article is to see the possibilities offered by this control.
For this, I created a WPF application to read an .RTF document, insert a row in a table, edit and add text in a paragraph. The interface looks like this:

First, open the .RTF document:
' Open the rtf document
Public Function OpenRtf() As Boolean
' Check the file path
If Not File.Exists(Me._rtfFilePath) Then Throw New ArgumentException("The rtf file does not exist")
' With two TextPointer positions as the beginning and end positions for the new Range
Dim range As New TextRange(Me._rtb.Document.ContentStart, Me._rtb.Document.ContentEnd)
' Exposes a stream around the .RTF File for opening the file
Using fStream As New FileStream(Me._rtfFilePath, FileMode.OpenOrCreate)
' Load the current selection (In this case all the .Rtf file content)
range.Load(fStream, DataFormats.Rtf)
End Using
Return True
End FunctionThe function to insert a row in a table in the document:
' Insert a row at a specified table index and rows index
Public Function InsertRow(ByVal tableIndex As Integer, ByVal rowIndex As Integer) As Boolean
Dim i As Integer
Dim table1 As Table = Nothing
For j = 0 To Me._rtb.Document.Blocks.Count - 1
' Is the current object type a Tabel ?
If Not TypeOf (Me._rtb.Document.Blocks(j)) Is Table Then Continue For
i += 1
' Is the current table a second one ?
If i < tableIndex Then Continue For
' Get the table at index = tableIndex
table1 = Me._rtb.Document.Blocks(j)
Exit For
Next
' Is there no table in the Rtf file ?
If table1 Is Nothing Then Return False
' Add a new row after a specified row index
table1.RowGroups(0).Rows.Insert(rowIndex, New TableRow())
Dim currentRow As TableRow = table1.RowGroups(0).Rows(rowIndex)
' Global formatting for the row.
currentRow.FontSize = 12
currentRow.FontWeight = FontWeights.Normal
' Add cells with content to the new row.
currentRow.Cells.Add(New TableCell(New Paragraph(New Run("Paris"))))
currentRow.Cells.Add(New TableCell(New Paragraph(New Run("France"))))
currentRow.Cells.Add(New TableCell(New Paragraph(New Run("$50,0"))))
currentRow.Cells.Add(New TableCell(New Paragraph(New Run("$50,0"))))
currentRow.Cells.Add(New TableCell(New Paragraph(New Run("$5,0"))))
' Bold the cells content.
For i = 0 To currentRow.Cells.Count - 1
currentRow.Cells(i).FontWeight = FontWeights.Bold
currentRow.Cells(i).SetValue(TableCell.BorderThicknessProperty, New Thickness(1D))
currentRow.Cells(i).SetValue(TableCell.BorderBrushProperty, Brushes.Black)
Next
Return True
End FunctionThe "System.Windows.Documents.Block" object is useful to take all document objects, so we get a BlockCollection. Table, Paragraph, List and others inherits from Block Object
Then, to change a paragraph and edit it we do the following:
' Edit a specified paragraph
Public Function EditParagraph(ByVal paragraphIndex As Integer) As Boolean
Dim i As Integer
Dim pgh As Paragraph = Nothing
For j = 0 To Me._rtb.Document.Blocks.Count - 1
' Is the current object type a Tabel ?
If Not TypeOf (Me._rtb.Document.Blocks(j)) Is Paragraph Then Continue For
i += 1
' Is the current paragraph a second one ?
If i < 7 Then Continue For
' Get the third paragraph
pgh = Me._rtb.Document.Blocks(j)
Exit For
Next
' Is there no paragraph in the Rtf file ?
If pgh Is Nothing Then Return False
' Create two TextPointers that will specify the text range the Span will cover
Dim myTextPointer1 As TextPointer = pgh.ContentStart.GetPositionAtOffset(10)
Dim myTextPointer2 As TextPointer = pgh.ContentEnd.GetPositionAtOffset(-5)
' Create a Span that covers the range between the two TextPointers.
Dim mySpan As Span = New Span(myTextPointer1, myTextPointer2)
mySpan.Background = Brushes.Red
' Add some text
pgh.Inlines.Add(New Run(". Some others informations can be found here: "))
' Add a link
Dim run3 As New Run("MSDN")
Dim hyperl As New Hyperlink(run3)
hyperl.NavigateUri = New Uri("http://msdn.microsoft.com/fr-fr/library/ms754030%28v=VS.100%29.aspx")
pgh.Inlines.Add(hyperl)
Return True
End FunctionFinally, we save the document:
' Save the rtf document
Public Function SaveRtf() As Boolean
'initializes a new instance of TextRange
Dim range As New TextRange(Me._rtb.Document.ContentStart, Me._rtb.Document.ContentEnd)
' Exposes a stream around the .RTF File for opening the file
Using fStream As New FileStream(Me._rtfFilePath, FileMode.OpenOrCreate)
' Save the current selection (In this case all the document)
range.Save(fStream, DataFormats.Rtf)
End Using
Return True
End FunctionIn this article, we reviewed how to edit an .RTF document without using a third-party tool.
The following links are useful for understanding the extent of possibiltés offered by the "System.Windows.Documents" namespace:
MSDN "System.Windows.Documents Namespace"
Kirupa.Chinnathambi Article
WpfRTBToRTF.zip - 100 Kio


