Tenere traccia delle modifiche in un documento

La funzionalità di tenere traccia delle modifiche, nota anche come revisione, consente di tenere traccia delle modifiche al contenuto e alla formattazione apportate dall’utente o da altri utenti. Questa funzione traccia modifiche con Aspose.Words supporta traccia modifiche in Microsoft Word. Con questa funzionalità, è possibile accedere a singole revisioni nel documento e applicarvi proprietà diverse.

Quando si attiva la funzione Traccia modifiche, tutti gli elementi inseriti, eliminati e modificati del documento verranno evidenziati visivamente con informazioni su chi, quando e cosa è stato modificato. Gli oggetti che contengono le informazioni su ciò che è stato modificato sono chiamati “modifiche di tracciamento”. Ad esempio, si supponga di voler rivedere un documento e apportare modifiche importanti: ciò potrebbe significare che è necessario apportare revisioni. Inoltre, potrebbe essere necessario inserire commenti per discutere alcune delle modifiche. È qui che entrano in gioco le modifiche ai documenti.

Questo articolo spiega come gestire e tenere traccia delle modifiche create da molti revisori sullo stesso documento, nonché le proprietà per il monitoraggio delle modifiche.

Cos’è una revisione

Prima di approfondire le revisioni, spieghiamo il significato delle revisioni. Un revision è una modifica che si verifica in un nodo di un documento mentre un gruppo di revisione, rappresentato dalla classe RevisionGroup, è un gruppo di revisioni sequenziali che si verificano in molti nodi di un documento. Fondamentalmente, la revisione è uno strumento per tracciare le modifiche.

Le revisioni vengono utilizzate nella funzione Monitoraggio modifiche e nella funzione Confronta documenti, in cui le revisioni vengono visualizzate come risultato del confronto. Quindi, le revisioni all’interno della funzione di monitoraggio delle modifiche mostrano da chi e cosa è stato modificato.

Aspose.Words supporta diversi tipi di revisione, così come in Microsoft Word, come Inserimento, Eliminazione, FormatChange, StyleDefinitionChange e Spostamento. Tutti i tipi di revisione sono rappresentati con l’enumerazione RevisionType.

Avviare e interrompere le modifiche di monitoraggio

La modifica di un documento di solito non viene considerata una revisione fino a quando non si inizia a monitorarlo. Aspose.Words consente di monitorare automaticamente tutte le modifiche nel documento con semplici passaggi. È possibile avviare facilmente il processo di tracciamento delle modifiche utilizzando il metodo StartTrackRevisions. Se è necessario interrompere il processo di tracciamento delle modifiche in modo che eventuali modifiche future non siano considerate revisioni, è necessario utilizzare il metodo StopTrackRevisions.

Al termine del processo di tracciamento delle modifiche nel documento, si avrà la possibilità di accettare anche tutte le revisioni o rifiutarle per ripristinare il documento nella sua forma originale. Questo può essere ottenuto usando il metodo AcceptAllRevisions o RejectAll. Inoltre, è possibile accettare o rifiutare ogni revisione separatamente utilizzando il metodo Accept o Reject.

Tutte le modifiche verranno monitorate per un’iterazione dal momento in cui si avvia il processo al momento in cui lo si interrompe. La connessione tra diverse iterazioni è rappresentata come lo scenario seguente: si completa il processo di tracciamento, quindi si apportano alcune modifiche e si ricomincia a tracciare le modifiche. Con questo scenario, tutte le modifiche che non hai accettato o rifiutato verranno visualizzate di nuovo.

Il seguente esempio di codice mostra come lavorare con le modifiche di monitoraggio:

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);

L’esempio di codice seguente mostra come vengono generate le revisioni quando un nodo viene spostato all’interno di un documento tracciato:

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);

Gestire e archiviare le modifiche come revisioni

Con la funzione di monitoraggio delle modifiche precedenti, è possibile capire quali modifiche sono state apportate nel documento e chi ha apportato tali modifiche. Con la funzione TrackRevisions, è possibile forzare l’archiviazione di eventuali modifiche all’interno del documento come revisioni.

Aspose.Words consente di verificare se un documento ha una revisione o meno utilizzando la proprietà HasRevision. Se non è necessario tenere traccia automaticamente delle modifiche nel documento tramite i metodi StartTrackRevisions e StopTrackRevisions, è possibile utilizzare la proprietà TrackRevisions per verificare se le modifiche vengono tracciate durante la modifica di un documento in Microsoft Word e archiviate come revisioni.

La funzione TrackRevisions effettua revisioni anziché modifiche reali del DOM. Ma le revisioni stesse sono separate. Ad esempio, se si elimina un paragrafo, Aspose.Words renderlo come revisione, contrassegnandolo come eliminazione, invece di eliminarlo.

Inoltre, Aspose.Words consente di verificare se un oggetto è stato inserito, eliminato o modificato IsDeleteRevision, IsFormatRevision, IsInsertRevision, IsMoveFromRevision, e IsMoveToRevision proprietà.

Il seguente esempio di codice mostra come applicare diverse proprietà con le revisioni:

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());