Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug with Open XML SDK #1853

Open
ChandrasekarML opened this issue Dec 24, 2024 · 3 comments
Open

Bug with Open XML SDK #1853

ChandrasekarML opened this issue Dec 24, 2024 · 3 comments
Assignees

Comments

@ChandrasekarML
Copy link

ChandrasekarML commented Dec 24, 2024

Describe the bug
how to track changes in a word document with inserted and deleted word by word along with color Inserted updating track changes, but deleted not updating track changes.

Sample code:
public void TrackChangesInWord(string filePath, string newText, string oldText)
{
    using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(filePath, true))
    {
        var mainPart = wordDoc.MainDocumentPart;
        var body = mainPart.Document.Body;

        foreach (var paragraph in body.Elements<Paragraph>())
        {
            var runs = paragraph.Elements<Run>().ToList();
            string combinedText = string.Join("", runs.Select(r => r.GetFirstChild<Text>()?.Text ?? string.Empty));

            if (combinedText.Contains(oldText))
            {
                // Find the start index of the old text
                int startIndex = combinedText.IndexOf(oldText);

                // Remove all existing runs
                foreach (var run in runs)
                {
                    run.Remove();
                }

                // Add text before the old word
                if (startIndex > 0)
                {
                    string beforeText = combinedText.Substring(0, startIndex);
                    paragraph.AppendChild(new Run(new Text(beforeText)));
                }

                // Add deleted text as a tracked change
                var deletedRun = new DeletedRun
                {
                    Author = "AuthorName",
                    Date = DateTime.Now
                };
                var deletedTextRun = new Run
                {
                    RunProperties = new RunProperties(new Color { Val = "FF0000" }) // Red for deleted
                };
                deletedTextRun.AppendChild(new Text(oldText));
                deletedRun.AppendChild(deletedTextRun);
                paragraph.AppendChild(deletedRun);

                // Add inserted text as a tracked change
                var insertedRun = new InsertedRun
                {
                    Author = "AuthorName",
                    Date = DateTime.Now
                };
                var insertedTextRun = new Run
                {
                    RunProperties = new RunProperties(new Color { Val = "00FF00" }) // Green for inserted
                };
                insertedTextRun.AppendChild(new Text(newText));
                insertedRun.AppendChild(insertedTextRun);
                paragraph.AppendChild(insertedRun);

                // Add text after the old word
                string afterText = combinedText.Substring(startIndex + oldText.Length);
                if (!string.IsNullOrEmpty(afterText))
                {
                    paragraph.AppendChild(new Run(new Text(afterText)));
                }
            }
        }

        mainPart.Document.Save();
    }
}
@ChandrasekarML
Copy link
Author

I have turned on the track changes (revisions) option in Word and made some changes and found all the track changes were being tracked and found all track changes in the openxml content. but I am not seeing the deleted track changes in openxml content, and the listnum values are continued from the next paragraph. So how can I track/get the deleted track changes in openXML?

@tomjebo
Copy link
Collaborator

tomjebo commented Jan 19, 2025

Hi @ChandrasekarML,

There are two problems with your code. First, and this is actually optional but Word uses it, in your DeletedRun and InsertedRun ctors, you should add an Id attribute like this:

                // Add deleted text as a tracked change
                var deletedRun = new DeletedRun
                {
                    Author = "AuthorName",
                    Date = DateTime.Now,
                    Id = "0" // <= Add the id here.
                };

and

                // Add inserted text as a tracked change
                var insertedRun = new InsertedRun
                {
                    Author = "AuthorName",
                    Date = DateTime.Now,
                    Id = "1" // <= Add the id here.
                };

Secondly, and this seems to be causing Word to fail to open although no validation errors are seen, in the Run you create you append a Text (w:t) element. Word is expecting a w:delText element because of the w:del element indicating that this will be deleted text shown in the track changes view. You need to change Text to DeletedText to satisfy Word like this:

                var deletedTextRun = new Run
                {
                    RunProperties = new RunProperties(new Color { Val = "FF0000" }) // Red for deleted
                };
                deletedTextRun.AppendChild(new DeletedText(oldText)); // <= Use DeletedText instead of Text.
                deletedRun.AppendChild(deletedTextRun);
                paragraph.AppendChild(deletedRun);

If you make these changes, Word should be happy and display the tracked changes successfully. Here is the full sample based on your code:

void TrackChangesInWord(string filePath, string newText, string oldText)
{
    using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(filePath, true))
    {
        var mainPart = wordDoc.MainDocumentPart;
        var body = mainPart.Document.Body;

        foreach (var paragraph in body.Elements<Paragraph>())
        {
            var runs = paragraph.Elements<Run>().ToList();
            string combinedText = string.Join("", runs.Select(r => r.GetFirstChild<Text>()?.Text ?? string.Empty));

            if (combinedText.Contains(oldText))
            {
                // Find the start index of the old text
                int startIndex = combinedText.IndexOf(oldText);

                // Remove all existing runs
                foreach (var run in runs)
                {
                    run.Remove();
                }

                // Add text before the old word
                if (startIndex > 0)
                {
                    string beforeText = combinedText.Substring(0, startIndex);
                    paragraph.AppendChild(new Run(new Text(beforeText)));
                }

                // Add deleted text as a tracked change
                var deletedRun = new DeletedRun
                {
                    Author = "AuthorName",
                    Date = DateTime.Now,
                    Id = "0"
                };
                var deletedTextRun = new Run
                {
                    RunProperties = new RunProperties(new Color { Val = "FF0000" }) // Red for deleted
                };
                deletedTextRun.AppendChild(new DeletedText(oldText));
                deletedRun.AppendChild(deletedTextRun);
                paragraph.AppendChild(deletedRun);

                // Add inserted text as a tracked change
                var insertedRun = new InsertedRun
                {
                    Author = "AuthorName",
                    Date = DateTime.Now,
                    Id = "1"
                };
                var insertedTextRun = new Run
                {
                    RunProperties = new RunProperties(new Color { Val = "00FF00" }) // Green for inserted
                };
                insertedTextRun.AppendChild(new Text(newText));
                insertedRun.AppendChild(insertedTextRun);
                paragraph.AppendChild(insertedRun);

                // Add text after the old word
                string afterText = combinedText.Substring(startIndex + oldText.Length);
                if (!string.IsNullOrEmpty(afterText))
                {
                    paragraph.AppendChild(new Run(new Text(afterText)));
                }
            }
        }

        mainPart.Document.Save();
    }
}

@ChandrasekarML
Copy link
Author

I add an both deleted and Inserted ID attribute like this: but it is still deleted Run is not working; hide track changes. Kindly provide a solution.

// Add deleted text as a tracked change
            var deletedRun = new DeletedRun
            {
                Author = "AuthorName",
                Date = DateTime.Now,
                Id = "0"
            };

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants