【问题标题】:MS Word Macro for converting "track changes" markup into text用于将“跟踪更改”标记转换为文本的 MS Word 宏
【发布时间】:2015-12-15 02:26:15
【问题描述】:

我需要将 MS Word 文档提交给无法识别“跟踪更改”标记的第三方软件。但是我仍然需要保留划掉的文本和新添加的文本,以便我的同事们知道原来的版本是什么,有什么变化。

如果只有一个人编辑 Word 文档,则以下宏有效。

Sub Macro1()

Dim chgAdd As Word.Revision

If ActiveDocument.Revisions.Count = 0 Then
    MsgBox "There are no revisions in this document", vbOKOnly
Else
    ActiveDocument.TrackRevisions = False
    For Each chgAdd In ActiveDocument.Revisions
        If chgAdd.Type = wdRevisionDelete Then
            chgAdd.Range.Font.StrikeThrough = True
            chgAdd.Range.Font.Color = wdColorDarkBlue
            chgAdd.Reject
        ElseIf chgAdd.Type = wdRevisionInsert Then
            chgAdd.Range.Font.Color = wdColorRed
            chgAdd.Accept
        Else
            MsgBox ("Unexpected Change Type Found"), vbOKOnly + vbCritical
            chgAdd.Range.Select ' move insertion point
        End If
    Next chgAdd
End If
End Sub

当另一个人编辑已编辑的文档时,问题就开始了。在这种情况下,第二作者可以删除第一作者(不是原文)的添加。上面的宏没有将其删除,而是将其转换为我的同事错误地认为原始文本中存在的划掉的文本。

我只想将已删除的原始文本转换为划掉的文本,而不是已删除的编辑(一位作者的编辑被另一位作者删除)。

这是一个示例,说明当文本由一位作者编辑时宏如何(正确)工作。

在“C”中可以看到,深蓝色划掉的文字是从原文中删除的,红色是添加的。

现在让我们看看当文本被两个(或理论上更多)不同的编辑器编辑时会发生什么,宏运行在最后(不是中间):

问题在“C”中变得很明显:“plantes”这个词变成了深蓝色划掉的文本,即使它不是原始文本的一部分。

如您所见,图 2-C 与图 1-C 不同。所以我希望更新后的宏能够正常工作,使图 2-C 与图 1-C 相同。

【问题讨论】:

  • 我有点遵循你想要的,但在概念上很难应用逻辑。您当前的宏关闭曲目更改 - 什么时候再次打开?宏应该如何知道这种状态(已经编辑过一次)何时存在?宏会在由多个编辑器更改的文档上运行,还是一次仅由一个编辑器更改?这里涉及哪个版本的 Word?
  • @CindyMeister 跟踪更改不会再次打开。它将在多个编辑器更改的文档上运行(这也是我想要的)但问题是它不区分第二个是否编辑删除了第一个编辑的添加或原始文本。我希望它忽略后者(本质上不接受)
  • 我仍然不确定我是否理解 100%,所以需要和你一起探索更多... 1. 有一个文档。 2. 有人用 TrackChanges 编辑它。 3. 您的代码运行并且跟踪更改已关闭。 4. 另一个人编辑但没有音轨变化。目标:您检测到 (4) 中所做的更改。问题 仅针对以前的更改,还是整个文档?如果不需要更改,为什么还要由另一个人进行编辑?保护整个文档或宏进行更改的位置是否有意义?或者更好地将 (3) 的副本与 (4) 的结果进行比较?
  • @CindyMeister 这些步骤实际上是按顺序排列的: 1. 有一个文档。 2. 有人用 TrackChanges 编辑它。 3. 另一个人编辑,但跟踪更改仍在进行中,并且在此更改期间之前的编辑的跟踪更改。 4. 代码运行并跟踪更改被关闭
  • 所以这是一种情况,文档中不止一个“编辑器”处于活动状态,而您只想“转换”一个编辑器的更改,而放弃其余的更改?还是只丢弃对相同文本范围所做的更改?如果最后一个是真的,你的代码会以同样的方式处理任何编辑器的任何其他更改吗?这些信息确实对用于编码的方法产生了重要影响...

标签: vba ms-word


【解决方案1】:

以下 VBA 代码循环遍历一组修订,检查修订是插入还是删除。如果是,并且在这部分循环之前没有立即拒绝,那么它会检查当前作者是否也是先前修订的作者,因为如果它们相同,则不会发生冲突。

如果它们不相同,则检查当前作者是否不是主要作者,以及当前修订版是否与之前的修订版在同一范围内,这意味着它已经“覆盖”了主要作者的修订版。在这种情况下,当前版本被拒绝。

或者,如果上一个修订的作者不是主要作者,并且之前的修订与当前的修订在同一范围内,那么之前的修订已经由主要作者替换了一个修订,那么之前的修订被拒绝.

在循环中,如果一个修订版刚刚被拒绝,代码会检查新的当前修订版是否由非主要作者的作者撰写,并且与之前的拒绝直接相邻。如果是这种情况,新的当前版本也会被拒绝。

然后,您已经拥有的代码将在此代码完成后运行。

Sub CompareRevisionsRanges()
  Dim revs As word.Revisions
  Dim rev As word.Revision, revOld As word.Revision
  Dim rngDoc As word.Range
  Dim rngRevNew As word.Range, rngRevOld As word.Range
  Dim authMain As String, authNew As String, authOld As String
  Dim bReject As Boolean

  bReject = False
  Set rngDoc = ActiveDocument.content
  Set revs = rngDoc.Revisions
  If revs.Count > 0 Then
    authMain = revs(1).Author
  Else 'No revisions so...
    Exit Sub
  End If

  For Each rev In revs
    'rev.Range.Select  'for debugging, only
    authNew = rev.Author
    If rev.Type = wdRevisionInsert Or wdRevisionDelete Then
        Set rngRevNew = rev.Range
        'There's only something to compare if an Insertion
        'or Deletion have been made prior to this
        If Not rngRevOld Is Nothing Then
            'The last revision was rejected, so we need to check
            'whether the next revision (insertion for a deletion, for example)
            'is adjacent and reject it, as well
            If bReject Then
                If rngRevNew.Start - rngRevOld.End <= 1 And authNew <> authMain Then
                    rev.Reject
                End If
                bReject = False 'reset in any case
            End If

            'If the authors are the same there's no conflict
            If authNew <> authOld Then
                'If the current revision is not the main author
                'and his revision is in the same range as the previous
                'this means his revision has replaced that
                'of the main author and must be rejected.
                If authNew <> authMain And rngRevNew.InRange(rngRevOld) Then
                    rev.Reject
                    bReject = True
                'If the previous revision is not the main author
                'and the new one is in the same range as the previous
                'this means that revision has replaced this one
                'of the main author and the previous must be rejected.
                ElseIf authOld <> authMain And rngRevOld.InRange(rngRevNew) Then
                    revOld.Reject
                    bReject = True
                End If
            End If
        End If
        Set rngRevOld = rngRevNew
        Set revOld = rev
        authOld = authNew
    End If

  Next        
End Sub

【讨论】:

  • 好的,差不多了。它适用于与所述删除配对的插入,但它所做的是拒绝插入/删除(因此保留旧版本的文本)。我想要相反的 - 接受插入/删除(保持最新的变化)。所以我猜它会在代码中从拒绝变为接受。
  • 另一件要检查的是哪个作者被接受/拒绝。示例代码假设主要作者是第一次更改的人。但是您可能需要找到一种不同的方式来识别该人。 Word 不会跟踪哪个作者最先使用 track changrs。
  • 跟踪更改已开启。在上面的代码中,RejectAccept 总共替换了三个。当前一个编辑器插入的单词被后一个编辑器更改为不同的单词时,第一个单词被“删除”(紫色划线),然后是新单词(带下划线的紫色)齐平,没有空格。在这种情况下,宏将正确删除删除线单词,并且它会从字面上接受新单词,使其变为黑色。也许有一种方法既不拒绝也不接受,而是跳过那个新词,以便它保持“被跟踪”。
  • 就您的第二条评论而言,这很可能是原因。总结一下我上面所说的,我认为我确实需要revOld.Accept,但我需要的不是rev.Accept,它会让它跳过,既不接受也不拒绝。
  • 实际上我只是通过在rev.Accept 行下方将bReject = True 替换为bReject = False 来解决颜色变化问题。同样,我同意你的第二条评论,它很可能是在多个不同时间进行的修订(即使只有两种颜色)。再次感谢。文档经过多次编辑后,跟踪更改变得非常混乱。
【解决方案2】:

您还可以转换所有更改,然后搜索并删除所有同时具有下划线和删除线属性的文本。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多