文書内の変更を追跡する

変更履歴の機能(レビューとも呼ばれます)を使用すると、自分や他のユーザーが行ったコンテンツや書式設定の変更を追跡できます。 Aspose.Wordsのこのトラック変更機能はMicrosoft Wordのトラック変更をサポートします。 この機能を使用すると、ドキュメント内の個々のリビジョンにアクセスし、それらに異なるプロパティを適用できます。

変更の追跡機能を有効にすると、文書の挿入、削除、および変更されたすべての要素が、誰が、いつ、何が変更されたかに関する情報で視覚的に強調表示さ 何が変更されたかに関する情報を保持するオブジェクトは、“変更の追跡"と呼ばれます。 たとえば、文書を確認して重要な変更を加えるとします。 また、いくつかの変更について議論するためにコメントを挿入する必要がある場合があります。 ここで、文書の変更を追跡することができます。

この記事では、同じ文書で多くの査読者が作成した変更を管理および追跡する方法と、変更を追跡するためのプロパティについて説明します。

リビジョンとは何ですか

リビジョンに飛び込む前に、リビジョンの意味を説明しましょう。 revisionはドキュメントの1つのノードで発生する変更ですが、RevisionGroupクラスで表されるリビジョングループは、ドキュメントの多くのノードで発生する連続した 基本的に、リビジョンは変更を追跡するためのツールです。

リビジョンは、変更の追跡機能およびドキュメントの比較機能内で使用され、比較の結果としてリビジョンが表示されます。 そのため、変更の追跡機能内のリビジョンには、誰が何を変更したかが表示されます。

Aspose.Wordsは、挿入、削除、FormatChange、StyleDefinitionChange、移動など、Microsoft Wordと同様に、さまざまなリビジョンタイプをサポートします。 すべてのリビジョンの種類はRevisionType列挙体で表されます。

変更の追跡の開始と停止

通常、文書を編集しても、追跡を開始するまではリビジョンとしてカウントされません。 Aspose.Words簡単な手順で文書内のすべての変更を自動的に追跡できます。 StartTrackRevisionsメソッドを使用すると、変更を追跡するプロセスを簡単に開始できます。 今後の編集がリビジョンと見なされないように変更の追跡プロセスを停止する必要がある場合は、StopTrackRevisionsメソッドを使用する必要があります。

文書の変更の追跡プロセスの最後に、すべてのリビジョンを承認したり、文書を元の形式に戻すために拒否したりすることもできます。 これは、AcceptAllRevisionsまたはRejectAllメソッドを使用することで実現できます。 また、AcceptまたはRejectメソッドを使用して、各リビジョンを個別に承認または拒否することができます。

すべての変更は、プロセスを開始した瞬間から停止した瞬間まで、1回の反復で追跡されます。 追跡プロセスを完了し、いくつかの変更を加えてから、変更の追跡を再度開始します。 このシナリオでは、受け入れなかった、または拒否しなかったすべての変更が再び表示されます。

次のコード例は、変更の追跡を操作する方法を示しています:

For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C
auto doc = System::MakeObject<Document>();
System::SharedPtr<Body> body = doc->get_FirstSection()->get_Body();
System::SharedPtr<Paragraph> para = body->get_FirstParagraph();
// Add text to the first paragraph, then add two more paragraphs.
para->AppendChild(System::MakeObject<Run>(doc, u"Paragraph 1. "));
body->AppendParagraph(u"Paragraph 2. ");
body->AppendParagraph(u"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(u"John Doe", System::DateTime::get_Now());
// This paragraph is a revision and will have the according "IsInsertRevision" flag set.
para = body->AppendParagraph(u"Paragraph 4. ");
ASSERT_TRUE(para->get_IsInsertRevision());
// Get the document's paragraph collection and remove a paragraph.
System::SharedPtr<ParagraphCollection> paragraphs = body->get_Paragraphs();
ASSERT_EQ(4, paragraphs->get_Count());
para = paragraphs->idx_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.
ASSERT_EQ(4, paragraphs->get_Count());
ASSERT_TRUE(para->get_IsDeleteRevision());
// The delete revision paragraph is removed once we accept changes.
doc->AcceptAllRevisions();
ASSERT_EQ(3, paragraphs->get_Count());
ASSERT_EQ(0, para->get_Count());
// Stopping the tracking of revisions makes this text appear as normal text.
// Revisions are not counted when the document is changed.
doc->StopTrackRevisions();
System::String outputPath = outputDataDir + u"WorkingWithRevisions.AcceptRevisions.doc";
doc->Save(outputPath);

次のコード例は、追跡されたドキュメント内でノードが移動されたときにリビジョンが生成される方法を示しています:

For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C
auto doc = System::MakeObject<Document>();
auto builder = System::MakeObject<DocumentBuilder>(doc);
builder->Writeln(u"Paragraph 1");
builder->Writeln(u"Paragraph 2");
builder->Writeln(u"Paragraph 3");
builder->Writeln(u"Paragraph 4");
builder->Writeln(u"Paragraph 5");
builder->Writeln(u"Paragraph 6");
System::SharedPtr<Body> body = doc->get_FirstSection()->get_Body();
std::cout << "Paragraph count: " << body->get_Paragraphs()->get_Count() << std::endl;
// Start tracking revisions.
doc->StartTrackRevisions(u"Author", System::DateTime(2020, 12, 23, 14, 0, 0));
// Generate revisions when moving a node from one location to another.
System::SharedPtr<Node> node = body->get_Paragraphs()->idx_get(3);
System::SharedPtr<Node> endNode = body->get_Paragraphs()->idx_get(5)->get_NextSibling();
System::SharedPtr<Node> referenceNode = body->get_Paragraphs()->idx_get(0);
while (node != endNode)
{
System::SharedPtr<Node> nextNode = node->get_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.
std::cout << "Paragraph count: " << body->get_Paragraphs()->get_Count() << std::endl;
System::String outputPath = outputDataDir + u"WorkingWithRevisions.MoveNodeInTrackedDocument.pdf";
doc->Save(outputPath);

変更をリビジョンとして管理および保存する

以前の変更の追跡機能を使用すると、ドキュメントで行われた変更と、それらの変更を行ったユーザーを理解できます。 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-C
auto doc = System::MakeObject<Document>();
// Insert an inline shape without tracking revisions.
ASSERT_FALSE(doc->get_TrackRevisions());
auto shape = System::MakeObject<Shape>(doc, ShapeType::Cube);
shape->set_WrapType(WrapType::Inline);
shape->set_Width(100.0);
shape->set_Height(100.0);
doc->get_FirstSection()->get_Body()->get_FirstParagraph()->AppendChild(shape);
// Start tracking revisions and then insert another shape.
doc->StartTrackRevisions(u"John Doe");
shape = System::MakeObject<Shape>(doc, ShapeType::Sun);
shape->set_WrapType(WrapType::Inline);
shape->set_Width(100.0);
shape->set_Height(100.0);
doc->get_FirstSection()->get_Body()->get_FirstParagraph()->AppendChild(shape);
// Get the document's shape collection which includes just the two shapes we added.
auto shapes = doc->GetChildNodes(NodeType::Shape, true)->LINQ_Cast<System::SharedPtr<Shape>>()->LINQ_ToList();
ASSERT_EQ(2, shapes->get_Count());
// Remove the first shape.
shapes->idx_get(0)->Remove();
// Because we removed that shape while changes were being tracked, the shape counts as a delete revision.
ASSERT_EQ(ShapeType::Cube, shapes->idx_get(0)->get_ShapeType());
ASSERT_TRUE(shapes->idx_get(0)->get_IsDeleteRevision());
// And we inserted another shape while tracking changes, so that shape will count as an insert revision.
ASSERT_EQ(ShapeType::Sun, shapes->idx_get(1)->get_ShapeType());
ASSERT_TRUE(shapes->idx_get(1)->get_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 = System::MakeObject<Document>(inputDataDir + u"Revision shape.docx");
shapes = doc->GetChildNodes(NodeType::Shape, true)->LINQ_Cast<System::SharedPtr<Shape>>()->LINQ_ToList();
ASSERT_EQ(4, shapes->get_Count());
// This is the move to revision, also the shape at its arrival destination.
ASSERT_FALSE(shapes->idx_get(0)->get_IsMoveFromRevision());
ASSERT_TRUE(shapes->idx_get(0)->get_IsMoveToRevision());
// This is the move from revision, which is the shape at its original location.
ASSERT_TRUE(shapes->idx_get(1)->get_IsMoveFromRevision());
ASSERT_FALSE(shapes->idx_get(1)->get_IsMoveToRevision());