如何捕获或测试 Word 365 文档中的 VBA 错误 5825?

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

这个宏(稍作改动,它可能起源于 Stack Exchange 站点)在需要将大量跟踪更改转换为蓝色常规文本的作者中非常受欢迎:

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

但是,当使用其他宏或插件时,例如 Zotero,它会产生如下错误:

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

在与 Set Change = Revision.Range 的行中,查看调试时的代码显示 Revision 变量的类型为 Variant/Empty 并且所有值(例如 Revision.Range ) 在手表 window 中设置为 <Object has been deleted>。文档中错误点的字段编码编码为({ REF Ref87607402 \h \* MERGEFORMAT }).

基于单步执行代码,当在文本中插入引用或交叉引用代码时,似乎会出现此错误,呈现 SSCCE extremely difficult since the error has the properties of a heisenbug 的创建。但是,对于具有 100 处更改的文档,即使能够绕过错误继续下一个错误也是有用的。

因此,您如何测试 VBA 中已删除的对象,或者相反,绕过已删除的对象以移动到文档中的下一个修订版?

当您循环遍历集合以执行将导致项目从集合中删除的操作时,会发生这种情况。当您删除第一项时,第二项变为新编号 1,最后一个索引为空(要处理的项目数在处理 For Each 时设置)。您删除的每个项目都会重复此操作。当您处理完一半的集合时,另一半已不存在。

为避免这种情况,您需要反向处理集合。

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

你还需要改掉不声明变量的习惯。如果您在代码模块的顶部添加 Option Explicit ,它将对您有所帮助。当您有未声明的变量时,这将阻止您的代码编译。要将其自动添加到新模块,请打开 VBE 并转到工具 |选项。在“选项”对话框中,确保选中“要求变量声明”。

另外,命名变量时要小心。 For Each Revision In ActiveDocument.Revisions 是不好的做法,因为 Revision 是 Word 对象模型中对象的名称。

通过搜索和查看 Word 使用的域代码,该错误似乎是由损坏的域代码引起的。 Microsoft 支持论坛中有一些证据表明,这个 might be a known, but infrequent error 可以通过显示字段代码来解决。

针对我生成错误的文档进行测试,以下宏运行正确并且没有生成任何错误。

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