How can you catch or test for VBA error 5825 in a Word 365 document?

Viewed 167

This macro (with minor changes, it likely originated on a Stack Exchange site) is fairly popular with authors that need to convert lots of tracked changes to regular text that has been colored blue:

Sub accept_changes()
    tempState = ActiveDocument.TrackRevisions

    ActiveDocument.TrackRevisions = False
    For Each Revision In ActiveDocument.Revisions
        Set Change = Revision.Range
        Change.Revisions.AcceptAll
        Change.Font.Color = 12611584
    Next
    
    ActiveDocument.TrackRevisions = tempState
End Sub

However, when using other macros or plug-ins such as Zotero it generates errors such as the following one:

Run-time error '5825': Object has been deleted

On the line with Set Change = Revision.Range, watching the code at debug shows that the Revision variable is of type Variant/Empty and all of the values (e.g., Revision.Range) are set to <Object has been deleted> in the Watches window. The field code encoding in the document at the point where the error occurs is ({ REF Ref87607402 \h \* MERGEFORMAT }).

Based upon stepping through the code this error seems to arise when citations or cross reference codes are inserted into the text, rendering creation of a SSCCE extremely difficult since the error has the properties of a heisenbug. However, for a document with 100's of changes, even being able to just bypass the error to move on to the next error would be useful.

Accordingly, how can you test for a deleted object in VBA, or conversely, bypass a deleted object to move onto the next revision in the document?

2 Answers

This occurs when you loop through a collection to perform an operation that will result in items being deleted from the collection. When you delete the first item the second becomes the new number 1, and the last index is empty (the number of items to process is set when the For Each is processed). This gets repeated with each item you delete. By the time you have processed half the collection the other half no longer exists.

To avoid this, you need to process the collection in reverse.

Sub accept_changes()
    tempState = ActiveDocument.TrackRevisions

    ActiveDocument.TrackRevisions = False
    Dim index As Long, Change As Range
    For index = ActiveDocument.Revisions.Count To 1 Step -1
        Set Change = ActiveDocument.Revisions(index).Range
        Change.Revisions.AcceptAll
        Change.Font.Color = 12611584
    Next
    
    ActiveDocument.TrackRevisions = tempState
End Sub

You also need to get out of the habit of not declaring variables. It will help you if you add Option Explicit at the top of the code module. This will prevent your code from compiling when you have undeclared variables. To add this automatically to new modules open the VBE and go to Tools | Options. In the Options dialog ensure that Require Variable Declaration is checked.

enter image description here

Also, be careful when naming variables. For Each Revision In ActiveDocument.Revisions is bad practice as Revision is the name of an object in Word's object model.

With a bit of hunting around and viewing of the field codes used by Word, it appears that this error was due to a corrupted field code. There's some evidence in the Microsoft support forum that this might be a known, but infrequent error that can be addressed by showing field codes.

Testing against my document that generated the error, the following macro runs correctly and did not generate any errors.

Option Explicit

Sub accept_changes()
    Dim tempState As Boolean, count As Integer, change As Range, thisRevision As Revision

    ' Check if there is work to do
    count = ActiveDocument.Revisions.count
    If count = 0 Then
        MsgBox "No revisions to process", vbInformation
        Exit Sub
    End If
    
    ' Disable screen updating for performance
    Application.ScreenUpdating = False

    With ActiveDocument
    
        ' Note the current state of revision tracking and disable them
        tempState = .TrackRevisions
        .TrackRevisions = False
                
        ' Show field codes incase any are corrupted
        .ActiveWindow.View.ShowFieldCodes = True
                
        ' Iterate through each revision, accept them and highlgiht the range in blue
        For Each thisRevision In .Revisions
            Set change = thisRevision.Range
            change.Revisions.AcceptAll
            change.Font.Color = 12611584
        Next
        
        ' Restore application state
        .ActiveWindow.View.ShowFieldCodes = False
        .TrackRevisions = tempState
    
    End With
    
    ' Reenable screen updating
    Application.ScreenUpdating = True
    
    ' Let the user know we are done
    MsgBox "Accpeted " + Str(count) + " revision(s)", vbInformation
    
End Sub
Related