Is there a way to programmatically reject changes to a word document using python, while not deleting comments from it?

Viewed 671

I have old version of a few word documents (word document with '.doc' extension) all of which have a lot of tracked changes in them. Most of the changes have comments associated with them.

I need to figure out a way to use python to reject all the changes that have been made in the documents, while retaining the comments.

I tried this with the new versions of word document('.docx' files) and faced no issues. All the changes were rejected and the word document still had all the comments in it. But when I tried to do it with the older versions of word document, all my comments got deleted.

I was using the following function at first with few different versions of the word file.

def reject_changes(path):

    doc = word.Documents.Open(path)
    doc.Activate()
    word.ActiveDocument.TrackRevisions = False     
    word.ActiveDocument.Revisions.RejectAll()

    word.ActiveDocument.Save()
    doc.Close(False)
  1. I tried to use the above function with the original word document
  2. I changed the extension of the file to '.docx' and tried the above function
  3. I made a copy of the document and saved it in '.docx' format.

In all these cases the comments were deleted.

I then tried the following code:

def reject_changes(path):
    doc = word.Documents.Open(path)
    doc.Activate()
    word.ActiveDocument.TrackRevisions = False
    nextRev = word.Selection.NextRevision()    
    while nextRev:
        nextRev.Reject()
        nextRev = word.Selection.NextRevision()
    word.ActiveDocument.Save()
    doc.Close(False)

For some reason this code was almost working. But on checking few of the documents again, I found that while most of the comments remained a couple of them were still deleted.

I think that since the comments are being deleted, they are probably a part of Revisions, in that case, is it possible to check if the revision is a comment or not. If not, can someone please suggest a way to ensure that no comments are deleted in the document on rejecting the changes.



Edit:
So, I found out that the comments that were getting deleted were added to the document when the 'Track Changes' option was active. I guess it made the comments as a part of the revision. So my first function works pretty well in case the comments are made once the 'Track Changes' option was not active.

But then, I have about more then twenty word documents (all of them a mix of doc and docx files), each of them have at least fifteen pages and over fifty comments.

I am using win32com.client. I am not too familiar with other packages that work with MS word. Any help would be appreciated.
Thanks!

1 Answers

Okay, so I was able to get a workaround for this by:

  1. Creating a selection object and selecting the scope of the text marked by the comment.
  2. Saving the range of the commented text into a range object.
  3. Rejecting the tracked changes for the selected text.
  4. Getting the new text based on the range object that was created in step 2.

This method takes a lot of time, though and the easiest way to extract the marked text is to ensure that comments are made when the word is not tracking the changes.

This is the code I am using now.

def reject_changes(path, doc_names):
    word = win32.gencache.EnsureDispatch('Word.Application')
    rejected_changes = []

    for doc in doc_names:
    #open the word document
        wb = word.Documents.Open(rejected_doc)
        wb.Activate()
        current_doc = word.ActiveDocument
        current_doc.TrackRevisions = False

        text = ''

    #iterating over the comments
        for c in current_doc.Comments:
            sentence_range = c.Scope    #returns a range object of the text marked by comment
            select_sentence = sentence_range.Select() #select the sentence marked by sentence_range

            nextRev = word.Selection.NextRevision() #checks for the next revision in word

            while nextRev:
                #if the next revision is not within the sentence_range then skip.
                if nextRev.Range.Start < sentence_range.Start or nextRev.Range.End > sentence_range.End:    
                    break
                else:
                    nextRev.Reject()    
                    new_range = current_doc.Range(sentence_range.Start, sentence_range.End)
                    text = new_range.Text
                nextRev = word.Selection.NextRevision()

            author = c.Author

            rejected_changes.append((doc,author,text,path))
        current_doc.Save()
        wb.Close(False)
    return rejected_changes
Related