简体   繁体   中英

How to iterate through and replace VBA RegExp matches (or portions thereof) in a Word doc selection containing table cells?

I use the following VBA macro to replace the numeric portion of the phrase "claim <#>", as in, "5. The device of claim 4, further comprising . . .", with an updating cross-reference to the paragraph of the claim referred to, so that if I insert a claim somewhere (with a numbered list paragraph style) and the numbering changes, I don't have to manually update all the affected claim references one by one.

It has been working as intended, but I discovered that if there is a table in the selection, I get the error message "Run-time error '4198': Command failed", and the debugger highlights the bolded line for inserting the cross reference. If I had to guess, the cell boundaries seem to increment the value of m.FirstIndex (associated with the cursor location of the beginning of a match) by TWO, whereas the Selection.MoveStart method seems not to count the cell boundaries as having a character width at all, so that moving the cursor to m.FirstIndex actually puts it two spaces to the right of the beginning of the match. I believe this may be the case because on one of my test runs, the correct cross reference appeared, but instead of replacing the plain text "1" of "claim 1", it replaced a character near the beginning of the next cell (but not the first character - the SECOND character!). I am not sure, however, why this causes a "command failed" error, as the command of inserting the cross reference appears to be executing, albeit in the wrong place.

Also, in my initial runs, the command inserted the cross reference so as to replace the entire contents of the cell containing the claim listing, so that it appeared as "Error! Reference source not found.", because the "claim 1" paragraph to which the cross reference referred had been deleted by the insertion. But after fiddling around with different placements of the claim listing relative to the table, I couldn't reproduce this behavior. (Needless to say, I am a novice programmer, and my debugging technique has a long way to go...)

I would appreciate if someone could shed some light on what is happening and explain how to skip over cell boundaries, or otherwise ignore their presence, in this routine.

Sub 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

Regex really isn't suited to returning ranges in documents with tables, in-line images, fields, etc. Try something based on Word's on wildcard tools:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM