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:
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;
}