跟踪文档中的更改
跟踪更改功能(也称为审阅)允许您跟踪您或其他用户对内容和格式所做的更改。 Aspose.Words 的跟踪更改功能支持 Microsoft Word 中的跟踪更改。通过此功能,您可以访问文档中的各个修订版本并对它们应用不同的属性。
当您启用跟踪更改功能时,文档中所有插入、删除和修改的元素都将在视觉上突出显示,并包含有关更改者、更改时间和更改内容的信息。携带有关更改内容的信息的对象称为"跟踪更改"。例如,假设您想要审阅一份文档并进行重要更改 - 这可能意味着您需要进行修订。此外,您可能需要插入评论来讨论某些更改。这就是跟踪文档更改的用武之地。
本文介绍如何管理和跟踪多个审阅者对同一文档创建的更改,以及用于跟踪更改的属性。
什么是修订
在深入讨论修订之前,我们先解释一下修订的含义。 revision 是在文档的一个节点中发生的更改,而由 RevisionGroup 类表示的修订组是在文档的许多节点中发生的一组连续修订。基本上,修订是跟踪更改的工具。
修订用于跟踪更改功能和比较文档功能,其中修订作为比较的结果出现。因此,跟踪更改功能中的修订会显示更改者和内容。
Aspose.Words 支持不同的修订类型以及 Microsoft Word,例如插入、删除、格式更改、样式定义更改和移动。所有修订类型均用 RevisionType 枚举表示。
开始和停止跟踪更改
在您开始跟踪文档之前,编辑文档通常不算作修订。 Aspose.Words 允许您通过简单的步骤自动跟踪文档中的所有更改。您可以使用 StartTrackRevisions 方法轻松开始跟踪更改的过程。如果您需要停止跟踪更改的过程,以便将来的任何编辑都不会被视为修订,则需要使用 StopTrackRevisions 方法。
StartTrackingRevisions
方法不会更改 TrackRevisions 属性的状态,并且不会将其值用于修订跟踪的目的。此外,如果节点在跟踪文档内从一个位置移动到另一个位置,则将创建移动修订,包括移自和移至范围。
在文档中的跟踪更改过程结束时,您甚至可以接受所有修订或拒绝它们以将文档恢复为其原始形式。这可以通过使用 AcceptAllRevisions 或 RejectAll 方法来实现。此外,您可以使用 Accept 或 Reject 方法分别接受或拒绝每个修订。
从您开始流程的那一刻到您停止流程的那一刻,所有更改都将被跟踪一次迭代。不同迭代之间的联系表示为以下场景:您完成跟踪过程,然后进行一些更改,然后再次开始跟踪更改。在这种情况下,您未接受或拒绝的所有更改都将再次显示。
AcceptAllRevisions
方法类似于 Microsoft Word 中的"接受所有更改"。
以下代码示例展示了如何跟踪更改:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET | |
Document doc = new Document(); | |
Body body = doc.FirstSection.Body; | |
Paragraph para = body.FirstParagraph; | |
// Add text to the first paragraph, then add two more paragraphs. | |
para.AppendChild(new Run(doc, "Paragraph 1. ")); | |
body.AppendParagraph("Paragraph 2. "); | |
body.AppendParagraph("Paragraph 3. "); | |
// We have three paragraphs, none of which registered as any type of revision | |
// If we add/remove any content in the document while tracking revisions, | |
// they will be displayed as such in the document and can be accepted/rejected. | |
doc.StartTrackRevisions("John Doe", DateTime.Now); | |
// This paragraph is a revision and will have the according "IsInsertRevision" flag set. | |
para = body.AppendParagraph("Paragraph 4. "); | |
Assert.True(para.IsInsertRevision); | |
// Get the document's paragraph collection and remove a paragraph. | |
ParagraphCollection paragraphs = body.Paragraphs; | |
Assert.AreEqual(4, paragraphs.Count); | |
para = paragraphs[2]; | |
para.Remove(); | |
// Since we are tracking revisions, the paragraph still exists in the document, will have the "IsDeleteRevision" set | |
// and will be displayed as a revision in Microsoft Word, until we accept or reject all revisions. | |
Assert.AreEqual(4, paragraphs.Count); | |
Assert.True(para.IsDeleteRevision); | |
// The delete revision paragraph is removed once we accept changes. | |
doc.AcceptAllRevisions(); | |
Assert.AreEqual(3, paragraphs.Count); | |
Assert.That(para, Is.Empty); | |
// Stopping the tracking of revisions makes this text appear as normal text. | |
// Revisions are not counted when the document is changed. | |
doc.StopTrackRevisions(); | |
// Save the document. | |
doc.Save(ArtifactsDir + "WorkingWithRevisions.AcceptRevisions.docx"); |
以下代码示例显示了在跟踪文档中移动节点时如何生成修订:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET | |
Document doc = new Document(); | |
DocumentBuilder builder = new DocumentBuilder(doc); | |
builder.Writeln("Paragraph 1"); | |
builder.Writeln("Paragraph 2"); | |
builder.Writeln("Paragraph 3"); | |
builder.Writeln("Paragraph 4"); | |
builder.Writeln("Paragraph 5"); | |
builder.Writeln("Paragraph 6"); | |
Body body = doc.FirstSection.Body; | |
Console.WriteLine("Paragraph count: {0}", body.Paragraphs.Count); | |
// Start tracking revisions. | |
doc.StartTrackRevisions("Author", new DateTime(2020, 12, 23, 14, 0, 0)); | |
// Generate revisions when moving a node from one location to another. | |
Node node = body.Paragraphs[3]; | |
Node endNode = body.Paragraphs[5].NextSibling; | |
Node referenceNode = body.Paragraphs[0]; | |
while (node != endNode) | |
{ | |
Node nextNode = node.NextSibling; | |
body.InsertBefore(node, referenceNode); | |
node = nextNode; | |
} | |
// Stop the process of tracking revisions. | |
doc.StopTrackRevisions(); | |
// There are 3 additional paragraphs in the move-from range. | |
Console.WriteLine("Paragraph count: {0}", body.Paragraphs.Count); | |
doc.Save(ArtifactsDir + "WorkingWithRevisions.MoveNodeInTrackedDocument.docx"); |
管理更改并将其存储为修订
通过以前的跟踪更改功能,您可以了解文档中进行了哪些更改以及谁进行了这些更改。使用 TrackRevisions 功能时,您可以强制将文档中的任何更改存储为修订版本。
Aspose.Words 允许您使用 HasRevision 属性检查文档是否有修订。如果不需要通过 StartTrackRevisions 和 StopTrackRevisions 方法自动跟踪文档中的更改,则可以使用 TrackRevisions
属性来检查在以 Microsoft Word 格式编辑文档时是否跟踪更改并将其存储为修订版本。
TrackRevisions
功能进行修订而不是真正的 DOM 更改。但修订本身是分开的。例如,如果删除任何段落,Aspose.Words 会将其作为修订,将其标记为删除,而不是删除它。
此外,Aspose.Words 允许您使用 IsDeleteRevision、IsFormatRevision、IsInsertRevision、IsMoveFromRevision 和 IsMoveToRevision 属性检查对象是否被插入、删除或更改格式。
TrackRevisions
属性之间没有任何联系。此外,无论跟踪更改功能如何,您都可以接受/拒绝修订。
以下代码示例展示了如何应用不同的属性和修订版:
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET | |
Document doc = new Document(); | |
// Insert an inline shape without tracking revisions. | |
Assert.False(doc.TrackRevisions); | |
Shape shape = new Shape(doc, ShapeType.Cube); | |
shape.WrapType = WrapType.Inline; | |
shape.Width = 100.0; | |
shape.Height = 100.0; | |
doc.FirstSection.Body.FirstParagraph.AppendChild(shape); | |
// Start tracking revisions and then insert another shape. | |
doc.StartTrackRevisions("John Doe"); | |
shape = new Shape(doc, ShapeType.Sun); | |
shape.WrapType = WrapType.Inline; | |
shape.Width = 100.0; | |
shape.Height = 100.0; | |
doc.FirstSection.Body.FirstParagraph.AppendChild(shape); | |
// Get the document's shape collection which includes just the two shapes we added. | |
List<Shape> shapes = doc.GetChildNodes(NodeType.Shape, true).Cast<Shape>().ToList(); | |
Assert.AreEqual(2, shapes.Count); | |
// Remove the first shape. | |
shapes[0].Remove(); | |
// Because we removed that shape while changes were being tracked, the shape counts as a delete revision. | |
Assert.AreEqual(ShapeType.Cube, shapes[0].ShapeType); | |
Assert.True(shapes[0].IsDeleteRevision); | |
// And we inserted another shape while tracking changes, so that shape will count as an insert revision. | |
Assert.AreEqual(ShapeType.Sun, shapes[1].ShapeType); | |
Assert.True(shapes[1].IsInsertRevision); | |
// The document has one shape that was moved, but shape move revisions will have two instances of that shape. | |
// One will be the shape at its arrival destination and the other will be the shape at its original location. | |
doc = new Document(MyDir + "Revision shape.docx"); | |
shapes = doc.GetChildNodes(NodeType.Shape, true).Cast<Shape>().ToList(); | |
Assert.AreEqual(2, shapes.Count); | |
// This is the move to revision, also the shape at its arrival destination. | |
Assert.False(shapes[0].IsMoveFromRevision); | |
Assert.True(shapes[0].IsMoveToRevision); | |
// This is the move from revision, which is the shape at its original location. | |
Assert.True(shapes[1].IsMoveFromRevision); | |
Assert.False(shapes[1].IsMoveToRevision); |