dotnet / Open-XML-SDK

Open XML SDK by Microsoft
https://www.nuget.org/packages/DocumentFormat.OpenXml/
MIT License
4.03k stars 547 forks source link

How to Track changes Insert new word and old word with Open XML SDK #1817

Open ChandrasekarML opened 4 days ago

ChandrasekarML commented 4 days ago

have issue with Track changes new word and old word in the word document. But Inserted Run newword working properly, but detetion not working prolerly.

Source Code i have tried it.

public void WordUpdate3(string filePath) { string newWord = "NewWord"; string wordToDelete = "POWERUP";

 using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(filePath, true))
 {
     Body body = wordDoc.MainDocumentPart.Document.Body;

     ReplaceWordWithTracking2(body, wordToDelete, newWord);

     wordDoc.MainDocumentPart.Document.Save();
 }

}

private void ReplaceWordWithTracking2(Body body, string targetWord, string newWord) { Paragraph targetParagraph = body.Elements() .FirstOrDefault(p => p.InnerText.Contains(targetWord));

 if (targetParagraph != null)
 {
     Run targetRun = targetParagraph.Elements<Run>()
                                    .FirstOrDefault(r => r.InnerText.Contains(targetWord));

     if (targetRun != null)
     {
         // Step 1: Create a DeletedRun for tracking the deletion
         DeletedRun deletedRun = new DeletedRun();

         // Set author and date attributes on the DeletedRun
         deletedRun.SetAttribute(new OpenXmlAttribute("author", "http://schemas.openxmlformats.org/wordprocessingml/2006/main", "AuthorName"));
         deletedRun.SetAttribute(new OpenXmlAttribute("date", "http://schemas.openxmlformats.org/wordprocessingml/2006/main", DateTime.Now.ToString("s")));

         // Add the deleted word with strikethrough formatting and color
         RunProperties runProperties = new RunProperties();
         Color color = new Color() { Val = "FF0000" }; // Red color for deleted text
         runProperties.Append(color);
         runProperties.Append(new Strike()); // Strikethrough for deletion

         Run deletedWordRun = new Run(runProperties, new Text(targetWord));
         deletedRun.Append(deletedWordRun); // Append the deleted word run to DeletedRun

         // Insert the DeletedRun before the target run
         targetRun.Parent.InsertBefore(deletedRun, targetRun);

         // Step 2: Remove the original target run
         targetRun.Remove();

         // Step 3: Create an InsertedRun for tracking the insertion
         InsertedRun insertedRun = new InsertedRun();

         // Set author and date attributes on the InsertedRun
         insertedRun.SetAttribute(new OpenXmlAttribute("author", "http://schemas.openxmlformats.org/wordprocessingml/2006/main", "AuthorName"));
         insertedRun.SetAttribute(new OpenXmlAttribute("date", "http://schemas.openxmlformats.org/wordprocessingml/2006/main", DateTime.Now.ToString("s")));

         // Add the new word with color formatting
         Run insertedWordRun = new Run(new Text(newWord))
         {
             RunProperties = new RunProperties(new Color { Val = "00FF00" }) // Green color for inserted word
         };
         insertedRun.Append(insertedWordRun); // Append the inserted word run to InsertedRun

         // Insert the InsertedRun after the DeletedRun
         deletedRun.Parent.InsertAfter(insertedRun, deletedRun);
     }
     else
     {
         Console.WriteLine("Target Run is null.");
     }
 }
 else
 {
     Console.WriteLine("Target Paragraph is null.");
 }

}

ChandrasekarML commented 4 days ago

have issue with Track changes new word and old word in the word document. But Inserted Run newword working properly, but detetion not working prolerly.

Source Code i have tried it.

public void WordUpdate3(string filePath) { string newWord = "NewWord"; string wordToDelete = "POWERUP";

using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(filePath, true)) { Body body = wordDoc.MainDocumentPart.Document.Body;

 ReplaceWordWithTracking2(body, wordToDelete, newWord);

 wordDoc.MainDocumentPart.Document.Save();

} }

private void ReplaceWordWithTracking2(Body body, string targetWord, string newWord) { Paragraph targetParagraph = body.Elements() .FirstOrDefault(p => p.InnerText.Contains(targetWord));

if (targetParagraph != null) { Run targetRun = targetParagraph.Elements() .FirstOrDefault(r => r.InnerText.Contains(targetWord));

 if (targetRun != null)
 {
     // Step 1: Create a DeletedRun for tracking the deletion
     DeletedRun deletedRun = new DeletedRun();

     // Set author and date attributes on the DeletedRun
     deletedRun.SetAttribute(new OpenXmlAttribute("author", "http://schemas.openxmlformats.org/wordprocessingml/2006/main", "AuthorName"));
     deletedRun.SetAttribute(new OpenXmlAttribute("date", "http://schemas.openxmlformats.org/wordprocessingml/2006/main", DateTime.Now.ToString("s")));

     // Add the deleted word with strikethrough formatting and color
     RunProperties runProperties = new RunProperties();
     Color color = new Color() { Val = "FF0000" }; // Red color for deleted text
     runProperties.Append(color);
     runProperties.Append(new Strike()); // Strikethrough for deletion

     Run deletedWordRun = new Run(runProperties, new Text(targetWord));
     deletedRun.Append(deletedWordRun); // Append the deleted word run to DeletedRun

     // Insert the DeletedRun before the target run
     targetRun.Parent.InsertBefore(deletedRun, targetRun);

     // Step 2: Remove the original target run
     targetRun.Remove();

     // Step 3: Create an InsertedRun for tracking the insertion
     InsertedRun insertedRun = new InsertedRun();

     // Set author and date attributes on the InsertedRun
     insertedRun.SetAttribute(new OpenXmlAttribute("author", "http://schemas.openxmlformats.org/wordprocessingml/2006/main", "AuthorName"));
     insertedRun.SetAttribute(new OpenXmlAttribute("date", "http://schemas.openxmlformats.org/wordprocessingml/2006/main", DateTime.Now.ToString("s")));

     // Add the new word with color formatting
     Run insertedWordRun = new Run(new Text(newWord))
     {
         RunProperties = new RunProperties(new Color { Val = "00FF00" }) // Green color for inserted word
     };
     insertedRun.Append(insertedWordRun); // Append the inserted word run to InsertedRun

     // Insert the InsertedRun after the DeletedRun
     deletedRun.Parent.InsertAfter(insertedRun, deletedRun);
 }
 else
 {
     Console.WriteLine("Target Run is null.");
 }

} else { Console.WriteLine("Target Paragraph is null."); } } TEST.docx

ThomasBarnekow commented 2 days ago

@ChandrasekarML, this is a question that you should ask on stackoverflow.

As a general hint, you should create a Word document with whatever content, formatting, or tracked changes that you would like to generate using the Open XML SDK. Next, you should open that document with an Open XML viewer and look at the markup created by the Word app. That markup is what you must create using the Open XML SDK. Your markup is simply not correct for your purpose.

As a bonus hint, you should use the classes (e.g., W) of the DocumentFormat.OpenXml.Linq namespace and the fields provided by those classes (e.g., W.p, W.r) rather than the strongly typed classes because you'll be able to easily mimic what Word has created without having to translate that to some class name (e.g., Paragraph, Run).