• Word macro for Wildcard Find and Replace with Increment

    Home » Forums » AskWoody support » Productivity software by function » MS Word and word processing help » Word macro for Wildcard Find and Replace with Increment

    Author
    Topic
    #484904

    I thought that I was close but I’m seeing some weird behavior. A little background. I’m writing a requirements specification and each requirement should have a unique number (e.g. HRS0010, HRS0020). Once the number is established in the first revision of the document it mustn’t change; that’s why I haven’t used something like SEQ, other fields, or lists. What I’d like to be able to do is create Normal paragraphs for each requirement and preface the paragraph with a placeholder text.

    E.g.

    [REQ0000] This is a requirement.

    Once I’m ready, I’d like to run a macro that will wildcard search for the placeholder and replace them all with an incrementing value. I’d like something generic so I should be able to specify the text prefix of the placeholder (the “REQ” in the example) and enter a custom prefix for the replacement (e.g. “HRS” or “SRS”). All this so that something like

    REQ0000 First requirement.
    REQ0000 Second requirement.
    REQ0000 Third requirement.

    becomes

    HRS0010 First requirement.
    HRS0020 Second requirement.
    HRS0030 Third requirement.

    Here is the code that I’m working from.

    Code:
    '
    ' AutoIncReqNumber
    '
    ' Searches through a selection for #### and replaces the text
    ' with  where  is an auto-incremented value that
    ' starts at 0 and increments by 10 each time.  The primary use for
    ' this is to assign requirement numbers just before you commit the
    ' draft version of the document.  This will not hold onto old numbers
    ' and will overwrite numbers that already exist so it shouldn't be
    ' used for documents that have already been in the review process
    ' against which people are starting development.
    '
    Sub AutoIncReqNumber()
        Dim iCount As Integer
        Dim strSearchStr As String
        Dim strOutPrefix As String
        Dim strFormatStr As String
    
        ' Get the search prefix that you would like to
        ' replace in the text.  This allows you to search
        ' for already created requirement numbers and
        ' replace them with incremented numbers.  Use with
        ' caution
        strSearchStr = InputBox("Search string for Requirement (REQ, SSS, HRS, etc.)", "Search String", "REQ")
        strSearchStr = UCase(strSearchStr)
        strSearchStr = strSearchStr & "[0-9]{4}"
    
        ' Get the prefix that you would like to use with
        ' the default of SSS for a system specification
        strOutPrefix = InputBox("Type of Requirement (SSS, HRS, SRS, etc.)", "Requirement Type", "SSS")
        strOutPrefix = UCase(strOutPrefix)
    
        ' This is the main part of the find.  It sets up the find
        ' criteria for the regular expression ####
        Selection.Find.ClearFormatting
        Selection.Find.Replacement.ClearFormatting
        iCount = 0
        With Selection.Find
            .Text = strSearchStr
            .Forward = True
            .Wrap = wdFindStop
            .Format = False
            .MatchWildcards = True
            .Execute Replace:=wdReplaceOne
           
            ' Here is the replacement.  The iCount increments by
            ' 10 and the value is formatted into the replacement
            ' string before performing the replacement.
            Do Until Not .Found
                iCount = iCount + 10
                strFormatStr = strOutPrefix & Format(iCount, "0000")
                .Replacement.Text = strFormatStr
                .Execute Replace:=wdReplaceOne
                Selection.MoveRight Unit:=wdCharacter, Count:=1
            Loop
        End With
    End Sub
    

    Seems to make sense to me but I’m seeing some odd behavior. Things like it will delete the first instance of what it finds and only replace the second instance. Or, it will only replace the first instance but with the number associated with the last instance. Can anyone make heads or tails of this and offer some suggestions?

    Thanks,
    Ben

    Viewing 1 reply thread
    Author
    Replies
    • #1345919

      Try:

      Code:
      Sub AutoIncReqNumber()
           '
           ' AutoIncReqNumber
           '
           ' Searches through a selection for #### and replaces the text
           ' with  where  is an auto-incremented value that
           ' starts at 0 and increments by 10 each time.  The primary use for
           ' this is to assign requirement numbers just before you commit the
           ' draft version of the document.  This will not hold onto old numbers
           ' and will overwrite numbers that already exist so it shouldn't be
           ' used for documents that have already been in the review process
           ' against which people are starting development.
           '
          Dim iCount As Long, strSearchStr As String, strOutPrefix As String
           ' Get the search prefix that you would like to
           ' replace in the text.  This allows you to search
           ' for already created requirement numbers and
           ' replace them with incremented numbers.  Use with
           ' caution
          strSearchStr = UCase(InputBox("Search string for Requirement (REQ, SSS, HRS, etc.)", "Search String", "REQ"))
           ' Get the prefix that you would like to use with
           ' the default of SSS for a system specification
          strOutPrefix = UCase(InputBox("Type of Requirement (SSS, HRS, SRS, etc.)", "Requirement Type", "SSS"))
           ' This is the main part of the find.  It sets up the find
           ' criteria for the regular expression ####
          iCount = 0
          With ActiveDocument.Content
              With .Find
                  .ClearFormatting
                  .Replacement.ClearFormatting
                  .Text = strSearchStr & "[0-9]{4}"
                  .Forward = True
                  .Wrap = wdFindStop
                  .Format = False
                  .MatchWildcards = True
                  .Execute
              End With
               ' Here is the replacement.  The iCount increments by
               ' 10 and the value is formatted into the replacement
               ' string before performing the replacement.
              While .Find.Found = True
                  iCount = iCount + 10
                  .Text = strOutPrefix & Format(iCount, "0000")
                  .Collapse wdCollapseEnd
                  .Find.Execute
              Wend
          End With
      End Sub

      Cheers,
      Paul Edstein
      [Fmr MS MVP - Word]

      • #1346282

        Paul,

        This seems to be working. It appears that the biggest difference was in the Selection versus the ActiveDocument.Content and the .Collapse parameter (still not sure what that one does). Thanks for your help.

        Sincerely,
        Ben

        • #1346330

          It appears that the biggest difference was in the Selection versus the ActiveDocument.Content and the .Collapse parameter (still not sure what that one does).

          Hi Ben,

          Using ActiveDocument ensures the whole document gets processed, rather than just what you might have selected (or from the insertion point to the end of the document). The .Collapse method tells Word to start searching again from the end of the range we’ve just processed, rather than including it (which would cause an endless loop).

          Cheers,
          Paul Edstein
          [Fmr MS MVP - Word]

    • #1346252

      Another approach entirely would be to use a SEQ field with live numbering right up until the time you were done with the doc or at least done with putting in new requirements. At that point you could use the Word command that changes the numbering from live to fixed text (which exists but I don’t remember what it is called right at the moment).

      • #1346259

        @jweissmn1: The SEQ fields can be converted to text by selecting them and pressing Ctrl-Shift-F9. It is probably a good idea to update the fields first by pressing F9.

        Other field shortcuts include Alt-F9 to toggle the view between field codes and their calculated results — or Shift-F9 for a single selected field code; F11 and Shift-F11 to jump to the next or previous field code; Ctrl-F11 and Shift-Ctrl-F11 to lock & unlock a field code. If you use field codes, consider using the Word Option to turn on visibility: it causes any calculated redult to display in grey on the screen (but is not printed) so you can see at a glance that it is not ordinary text.

        • #1346310

          Thanks. that will certainly work.

          What I had in mind and have finally found again is the VBA method ConvertNumbersToText. You can use it for a list object, a listformat object, or an entire document.

          ActiveDocument.Lists(1).ConvertNumberstoText

          for example. It will work from the Immediate window or from a macro.

      • #1346283

        I thought about this one but there are a large number of requirements and the documents contain a large number of other fields, too. It would be very tedious to go through and convert each of the SEQ fields to text; selecting the document and performing the replacement would change all of the other fields to text, too. Thanks for the suggestion.

    Viewing 1 reply thread
    Reply To: Word macro for Wildcard Find and Replace with Increment

    You can use BBCodes to format your content.
    Your account can't use all available BBCodes, they will be stripped before saving.

    Your information: