Отслеживать изменения в документе

Функция отслеживания изменений, также известная как проверка, позволяет отслеживать изменения в содержании и форматировании, внесенные вами или другими пользователями. Эта функция отслеживания изменений с помощью Aspose.Words поддерживает отслеживание изменений с помощью Microsoft Word. С помощью этой функции вы можете получить доступ к отдельным редакциям вашего документа и применить к ним различные свойства.

Когда вы включите функцию отслеживания изменений, все вставленные, удаленные и измененные элементы документа будут визуально выделены с информацией о том, кем, когда и что было изменено. Объекты, которые содержат информацию о том, что было изменено, называются “отслеживаемыми изменениями”. Например, предположим, что вы хотите просмотреть документ и внести в него важные изменения – это может означать, что вам необходимо внести правки. Кроме того, вам может потребоваться вставить комментарии для обсуждения некоторых изменений. Вот где пригодится отслеживание изменений в документах.

В этой статье объясняется, как управлять изменениями, внесенными многими рецензентами в один и тот же документ, и отслеживать их, а также свойства для отслеживания изменений.

Что такое Пересмотр

Прежде чем перейти к рассмотрению изменений, давайте объясним значение изменений. revision - это изменение, которое происходит в одном узле документа, в то время как группа изменений, представленная классом RevisionGroup, представляет собой группу последовательных изменений, которые происходят во многих узлах документа. Ревизия - это инструмент для отслеживания изменений.

Изменения используются в функции отслеживания изменений и в функции сравнения документов, где изменения отображаются в результате сравнения. Таким образом, изменения в функции отслеживания изменений показывают, кем и что было изменено.

Aspose.Words поддерживает различные типы редакций, как и в Microsoft Word, такие как вставка, удаление, FormatChange, StyleDefinitionChange и перемещение. Все типы редакций представлены перечислением RevisionType.

Запуск и остановка отслеживания изменений

Редактирование документа обычно не считается доработкой, пока вы не начнете его отслеживать. Aspose.Words позволяет автоматически отслеживать все изменения в вашем документе с помощью простых шагов. Вы можете легко запустить процесс отслеживания изменений, используя метод StartTrackRevisions. Если вам нужно остановить процесс отслеживания изменений, чтобы любые будущие правки не считались ревизиями, вам нужно будет использовать метод StopTrackRevisions.

В конце процесса отслеживания изменений в вашем документе у вас будет возможность даже принять все изменения или отклонить их, чтобы вернуть документ к его первоначальному виду. Этого можно достичь, используя метод AcceptAllRevisions или RejectAll. Кроме того, вы можете принять или отклонить каждую редакцию отдельно, используя метод Accept или Reject.

Все изменения будут отслеживаться в течение одной итерации с момента запуска процесса до момента его остановки. Связь между различными итерациями представлена в виде следующего сценария: вы завершаете процесс отслеживания, затем вносите некоторые изменения и снова начинаете отслеживать изменения. В этом случае все изменения, которые вы не приняли или отклонили, будут отображены снова.

В следующем примере кода показано, как работать с отслеживанием изменений:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-Java
Document doc = new Document();
Body body = doc.getFirstSection().getBody();
Paragraph para = body.getFirstParagraph();
// 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", new Date());
// This paragraph is a revision and will have the according "IsInsertRevision" flag set.
para = body.appendParagraph("Paragraph 4. ");
if(para.isInsertRevision())
System.out.println("isInsertRevision:" + para.isInsertRevision());
// Get the document's paragraph collection and remove a paragraph.
ParagraphCollection paragraphs = body.getParagraphs();
if(4 == paragraphs.getCount())
System.out.println("count:" + paragraphs.getCount());
para = paragraphs.get(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.
if(4 == paragraphs.getCount())
System.out.println("count:" + paragraphs.getCount());
if(para.isDeleteRevision())
System.out.println("isDeleteRevision:" + para.isDeleteRevision());
// The delete revision paragraph is removed once we accept changes.
doc.acceptAllRevisions();
if(3 == paragraphs.getCount())
System.out.println("count:" + paragraphs.getCount());
// 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(dataDir + "Document.Revisions.docx");

В следующем примере кода показано, как генерируются изменения при перемещении узла в отслеживаемом документе:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-Java
// Generate document contents.
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.getFirstSection().getBody();
System.out.println("Paragraph count:" + body.getParagraphs().getCount());
// Start tracking revisions.
doc.startTrackRevisions("Author", new Date());
// Generate revisions when moving a node from one location to another.
Node node = body.getParagraphs().get(3);
Node endNode = body.getParagraphs().get(5).getNextSibling();
Node referenceNode = body.getParagraphs().get(0);
while (node != endNode)
{
Node nextNode = node.getNextSibling();
body.insertBefore(node, referenceNode);
node = nextNode;
}
// Stop the process of tracking revisions.
doc.stopTrackRevisions();
// There are 3 additional paragraphs in the move-from range.
System.out.println("Paragraph count: " + body.getParagraphs().getCount());
doc.save(dataDir + "out.docx");

Управление изменениями и их хранение в виде ревизий

С помощью функции отслеживания предыдущих изменений вы можете понять, какие изменения были внесены в ваш документ и кто внес эти изменения. В то время как с помощью функции TrackRevisions вы принудительно сохраняете любые изменения в вашем документе в виде ревизий.

Aspose.Words позволяет проверить, есть ли в документе редакция или нет, используя свойство HasRevision. Если вам не нужно автоматически отслеживать изменения в вашем документе с помощью методов StartTrackRevisions и StopTrackRevisions, то вы можете использовать свойство TrackRevisions, чтобы проверить, отслеживаются ли изменения при редактировании документа в Microsoft Word и сохраняются ли они как ревизии.

Функция TrackRevisions вносит правки вместо реальных изменений DOM. Но сами правки являются отдельными. Например, если вы удаляете какой-либо абзац, Aspose.Words внесите его в качестве правки, пометив как удаленный, вместо того, чтобы удалять его.

Кроме того, Aspose.Words позволяет проверить, был ли объект вставлен, удален или изменено форматирование, используя свойства IsDeleteRevision, IsFormatRevision, IsInsertRevision, IsMoveFromRevision, и IsMoveToRevision.

В следующем примере кода показано, как применять различные свойства с помощью ревизий:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-Java
// Open a blank document.
Document doc = new Document();
// Insert an inline shape without tracking revisions.
Shape shape = new Shape(doc, ShapeType.CUBE);
shape.setWrapType(WrapType.INLINE);
shape.setWidth(100.0);
shape.setHeight(100.0);
doc.getFirstSection().getBody().getFirstParagraph().appendChild(shape);
// Start tracking revisions and then insert another shape.
doc.startTrackRevisions("John Doe");
shape = new Shape(doc, ShapeType.SUN);
shape.setWrapType(WrapType.INLINE);
shape.setWidth(100.0);
shape.setHeight(100.0);
doc.getFirstSection().getBody().getFirstParagraph().appendChild(shape);
// Get the document's shape collection which includes just the two shapes we added.
Node[] shapes = doc.getChildNodes(NodeType.SHAPE, true).toArray();
if(2 == shapes.length)
System.out.println("Shapes Count:" + shapes.length);
// Remove the first shape.
shapes[0].remove();
Shape sh = (Shape) shapes[0];
// Because we removed that shape while changes were being tracked, the shape counts as a delete revision.
if(ShapeType.CUBE == sh.getShapeType())
System.out.println("Shape is CUBE");
if(sh.isDeleteRevision())
System.out.println("isDeleteRevision:" + sh.isDeleteRevision());
// And we inserted another shape while tracking changes, so that shape will count as an insert revision.
sh = (Shape) shapes[1];
if(ShapeType.SUN == sh.getShapeType())
System.out.println("Shape is SUN");
if(sh.isInsertRevision())
System.out.println("IsInsertRevision:" + sh.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(dataDir + "Revision shape.docx");
Node[] nc = doc.getChildNodes(NodeType.SHAPE, true).toArray();
if(4 == nc.length)
System.out.println("Shapes Count:" + nc.length);
Shape mvr = (Shape) nc[0];
// This is the move to revision, also the shape at its arrival destination.
if(mvr.isMoveFromRevision())
System.out.println("isMoveFromRevision:" + mvr.isMoveFromRevision());
if(mvr.isMoveToRevision())
System.out.println("isMoveToRevision:" + mvr.isMoveToRevision());
mvr = (Shape) nc[1];
// This is the move from revision, which is the shape at its original location.
if(mvr.isMoveFromRevision())
System.out.println("isMoveFromRevision:" + mvr.isMoveFromRevision());
if(mvr.isMoveToRevision())
System.out.println("isMoveToRevision:" + mvr.isMoveToRevision());