如何在包含表单元格的Word文档选择中迭代并替换VBA RegExp匹配(或其部分)?

时间:2018-08-27 21:14:01

标签: regex vba replace ms-word

我使用下面的VBA宏替换短语“ claim <#>”的数字部分,如“ 5.权利要求4的设备,还包括...”,其中具有更新的交叉引用引用的索赔段落,因此,如果我在某处(带有编号列表段落样式)插入索赔并更改了编号,则不必一一手动更新所有受影响的索赔引用。

它已经按预期工作,但是我发现如果选择中有一个表,则会收到错误消息“运行时错误'4198':命令失败”,调试器突出显示了要插入的粗体行交叉参考。如果我不得不猜测的话,单元格边界似乎会将m.FirstIndex的值(与匹配开始处的光标位置相关联)增加2,而Selection.MoveStart方法似乎没有将单元格边界视为具有字符宽度,因此将光标移动到m.FirstIndex实际上将其放在比赛开始位置的右边两个空格。我相信可能是这样,因为在我的一次测试运行中,出现了正确的交叉引用,但是不是替换了“ claim 1”的纯文本“ 1”,而是替换了下一个单元格开头附近的字符(但不是第一个字符-第二个字符!)。但是,我不确定这为什么会导致“命令失败”错误,因为插入交叉引用的命令似乎在执行中,尽管位置错误。

此外,在我的初始运行中,该命令插入了交叉引用,以便替换包含索赔清单的单元格的全部内容,因此它显示为“错误!找不到参考源。”,因为“索赔”通过插入删除了交叉引用所指的1“段落。但是在摆弄索赔表相对于表格的不同位置之后,我无法重现此行为。 (不用说,我是一个新手程序员,而且我的调试技术还有很长的路要走...)

如果有人可以阐明正在发生的事情,并解释如何跳过此例程,如何跳过单元格边界,或者忽略它们的存在,我将不胜感激。

子InsertMultipleClaimReferences()

If Word.Selection.Type = wdSelectionIP Then
    MsgBox ("Nothing selected")
    Exit Sub
End If

' Inserts patent claim references in selection by replacing number after "claim " in selection with numbered item paragraph number
' having an index corresponding to the replaced number.
' Assumes that the only other numbered paragraph numbering style in the patent
' application, if any, is "[0001]", etc., for the specification paragraphs.


Dim re As VBScript_RegExp_55.RegExp
Set re = New VBScript_RegExp_55.RegExp
Dim listPara As Paragraph

Dim n As Long
Dim matchCount As Long
Dim lastMatchLastIndex As Long
Dim submatch As String

Dim rng As Range
Dim txt As String
Dim allMatches As MatchCollection, m As Match

'Declares RegExp pattern of patent specification paragraph numbering style

re.pattern = "\[[0-9]{4,}\]" 'for numbering style: "[0001]", etc.
re.Global = True
n = 0

'Determines index n of last patent specification paragraph having the above numbering style

For Each listPara In ActiveDocument.ListParagraphs
    If re.Test(listPara.Range.ListFormat.ListString) Then
        n = n + 1
    End If
Next listPara

'Declares RegExp pattern of a reference to a parent patent claim in a dependent patent claim

Set re = New VBScript_RegExp_55.RegExp
re.pattern = "(?:claim\s)(\d+)"
re.IgnoreCase = True
re.Global = True


'Replaces numeric portion of patent claim references in selection with an updatable (using f9 on selection)
' numeric cross reference to the number of the nth list paragraph following the last specification paragraph,
' which is assumed to be the paragraph containing claim n, or the "preamble" (first paragraph following the number)
' of claim n.

txt = Selection.Text
    If re.Test(txt) Then
      Selection.Collapse (wdCollapseStart)
      Set allMatches = re.Execute(txt)
      matchCount = allMatches.count
      lastMatchLastIndex = 0
      For Each m In allMatches
          Selection.MoveStart wdCharacter, m.FirstIndex + 6 - lastMatchLastIndex 'Note: 6 is the character
                'length of "Claim "; so this moves the cursor forward from the end of the last match to the beginning of
                'the numeric portion of the current match
          Selection.MoveEnd wdCharacter, m.length - 6 'selects the claim number
          **Selection.InsertCrossReference ReferenceType:="Numbered item", _
          ReferenceKind:=wdNumberNoContext, ReferenceItem:=n + m.SubMatches(0), _
          InsertAsHyperlink:=True, IncludePosition:=False, SeparateNumbers:=True, _
          SeparatorString:=" " 'inserts the cross reference - this command fails if selection contains a table**
          Selection.Collapse (wdCollapseEnd)
          lastMatchLastIndex = m.FirstIndex + m.length
      Next m

    End If
End Sub

1 个答案:

答案 0 :(得分:0)

Regex确实不适合返回包含表,嵌入式图像,字段等的文档中的范围。尝试使用基于Word的通配符工具进行操作:

Sub Demo()
Application.ScreenUpdating = False
With ActiveDocument.Range
  With .Find
    .ClearFormatting
    .Replacement.ClearFormatting
    .Text = "<[Cc]laim \<[0-9]@\>"
    .Replacement.Text = ""
    .Forward = True
    .Format = False
    .Wrap = wdFindStop
    .MatchWildcards = True
    .Execute
  End With
  Do While .Find.Found
    With .Duplicate
      .Collapse wdCollapseEnd
      .MoveStartUntil "<", wdBackward
      .Collapse wdCollapseStart
      .MoveEndUntil ">", wdForward
      .InsertCrossReference ReferenceType:="Numbered item", _
          ReferenceKind:=wdNumberNoContext, ReferenceItem:=.Text, _
          InsertAsHyperlink:=True
    End With
    .Collapse wdCollapseEnd
    .Find.Execute
  Loop
End With
Application.ScreenUpdating = True
End Sub