Skip to main content

Track Changes

  • 5 minutes to read

The Word Processing Document API allows you to retrieve, accept or reject revisions made to a document via Track Changes.

The RichEditDocumentServer supports Track Changes in the following formats:

  • DOCX;
  • DOC;
  • RTF;
  • WordML;
  • HTML;
  • PDF (export only).

Enable Track Changes in the Document

Use the following API to enable Track Changes and specify the revision options:

API Description
Document.TrackChanges Provides access to the document’s tracking options (DocumentTrackChangesOptions).
DocumentTrackChangesOptions.Enabled Enables tracking in the document. When tracking is enabled, new edits in the document are added as revisions.
DocumentTrackChangesOptions.TrackFormatting
DocumentTrackChangesOptions.TrackMoves
Specifies whether to track formatting changes (character, paragraph, section and table properties’ changes) or content movements.

The code sample below shows how to enable Track Changes and change formatting options for the specified range. As a result, a new revision is added to the collection:

View Example: Manage Tracked Changes in the Document

DocumentTrackChangesOptions documentTrackChangesOptions = documentProcessor.Document.TrackChanges;
documentTrackChangesOptions.Enabled = true;
documentTrackChangesOptions.TrackFormatting = true;
documentTrackChangesOptions.TrackMoves = true;

//Format the specific phrase in the document:
//This modification is added an a new revision:
DocumentRange[] targetPhrases = documentProcessor.Document.FindAll("We measured hard disk space as a function of USB key space on an IBM PC Junior.", SearchOptions.None);
CharacterProperties characterProperties = documentProcessor.Document.BeginUpdateCharacters(targetPhrases[0]);
characterProperties.FontName = "Arial";
characterProperties.Italic = true;
documentProcessor.Document.EndUpdateCharacters(characterProperties);

Change Display Options for Revisions

The TrackChangesOptions class properties allow you to specify revision display options. You can specify a color and format for each revision type and change the review mode. These options are applied when the document is printed or exported to PDF.

Access these properties via the documentProcessor.Options.Annotations.TrackChanges notation.

Tip

Set the TrackChangesOptions.DisplayForReviewMode property to DisplayForReviewMode.NoMarkup to hide changes when the document is printed or exported to PDF.

TrackChangesOptions trackChangesOptions = documentProcessor.Options.Annotations.TrackChanges;

//Change review mode:
trackChangesOptions.DisplayForReviewMode = DisplayForReviewMode.SimpleMarkup;

//Change display options for insertions and format changes:
trackChangesOptions.DisplayFormatting = DisplayFormatting.ColorOnly;
trackChangesOptions.FormattingColor = RevisionColor.ClassicBlue;
trackChangesOptions.DisplayInsertionStyle = DisplayInsertionStyle.Underline;
trackChangesOptions.InsertionColor = RevisionColor.DarkRed;

Access Revisions

The Document.Revisions property provides access to the read-only collection of document revisions.

Call the RevisionCollection.Get method to retrieve revisions related to a document part (main body, header, footer, and text box). Pass the target SubDocument instance as the method’s parameter. The following properties allow you to access a specific document part’s SubDocument:

Document Part Property
Main Body RichEditDocumentServer.Document
Header or Footer Section.BeginUpdateHeader
Section.BeginUpdateFooter
Text Box TextBox.Document

The RevisionCollection.Get(DocumentRange) method overload allows you to retrieve revisions made to a document range.

The code sample below shows how to retrieve revisions made in the first section’s header and in the first paragraph:

//Get revisions from the header:
SubDocument header = richEditControl.Document.Sections[0].BeginUpdateHeader(HeaderFooterType.First);
var sectionRevisions = richEditControl.Document.Revisions.Get(header);
richEditControl.Document.Sections[0].EndUpdateHeader(header);

//Get revisions from the first paragraph:
Paragraph firstParagraph = richEditControl.Document.Paragraphs[0];
var paragraphRevisions = richEditControl.Document.Revisions.Get(firstParagraph.Range);

Accept and Reject Revisions

Use the Revision object’s properties to obtain the revision’s date, author, and type. The Revision.Range property provides access to the document range to which the revision is applied.

Call the Revision.Reject or Revision.Accept method to reject or accept a specific revision.

Use the RevisionCollection.AcceptAll or RevisionCollection.RejectAll method to manage all revisions in the document or in specific document part.

The code sample below shows how to reject all revisions on the first page’s header:

SubDocument header = documentProcessor.Document.Sections[0].BeginUpdateHeader(HeaderFooterType.First);
documentRevisions.RejectAll(header);
documentProcessor.Document.Sections[0].EndUpdateHeader(header);

Pass the Predicate<T> object as one of the method’s parameter to accept or reject all revisions that meet the given criteria.

The code sample below rejects all revisions in the first section from the specific author.

//Reject all revisions in the first section from the specific author:
var sectionRevisions = documentRevisions.Get(documentProcessor.Document.Sections[0].Range).Where(x => x.Author == "Janet Leverling");

foreach (Revision revision in sectionRevisions)
        revision.Reject();

Revision Conflicts

When you move text, change it, and then reject this move, a conflict occurs that fires Document.TrackedMovesConflict and RichEditDocumentServer.TrackedMovesConflict events. Handle one of the events to specify the version of the text you want to keep (the ResolveMode property).

Use the OriginalLocationRange and NewLocationRange properties to obtain the original and new location range, and the Revision property to retrieve the revision that fired this event.

The code sample below shows how to handle the TrackedMovesConflict event:

private void WordProcessor_TrackedMovesConflict(object sender, TrackedMovesConflictEventArgs e)
{
  //Compare the length of the original and new location ranges
  //Keep text from the location whose range is the smallest
  e.ResolveMode = (e.OriginalLocationRange.Length <= e.NewLocationRange.Length) ? TrackedMovesConflictResolveMode.KeepOriginalLocationText : TrackedMovesConflictResolveMode.KeepNewLocationText;
}