none
Change formatting of all text on a line before a string RRS feed

  • Question

  • I have a several thousand page word document that I need to edit so that every line that contains "X" has all text on the line before "X" changed to a different format. 
    Wednesday, March 5, 2014 9:05 PM

Answers

  • I'm not sure what you mean by delineated they have a hard return

    That's the delineation I was referring to. For the task of bolding lines with an 'X', you could use a macro coded as:

    Sub Demo()
    Application.ScreenUpdating = False
    Dim i As Long
    With ActiveDocument.Range
      .InsertBefore vbCr
      With .Duplicate
        With .Find
          .ClearFormatting
          .Replacement.ClearFormatting
          .Text = "[^13^l][!^13^l]@X"
          .Replacement.Text = ""
          .Forward = True
          .Wrap = wdFindStop
          .Format = False
          .MatchWildcards = True
          .Execute
        End With
        Do While .Find.Found
          i = i + 1
          .Start = .Start + 1
          .Font.Bold = True
          .Collapse wdCollapseEnd
          .Find.Execute
        Loop
      End With
      .Characters.First.Text = vbNullString
    End With
    Application.ScreenUpdating = True
    MsgBox i & " instances found."
    End Sub

    I gather you want to do more extensive formatting than just bolding the found strings. That call all be done where '.Font.Bold = True' appears.

    As for processing multiple strings, it's also possible to use Word documents, text files or Excel workbooks for the input. For example, the following code demonstrates how you might adapt the above code to use a separate Word document in which the strings to find (e.g. 'X' and 'Y') are in separate paragraphs.

    Sub BulkDemo()
    Application.ScreenUpdating = False
    Dim FRDoc As Document, FRList As String, i As Long
    'Load the strings from the reference doc into a text string to be used as an array.
    Set FRDoc = Documents.Open("Drive:\FilePath\FindReplaceList.doc", AddToRecentFiles:=False)
    FRList = FRDoc.Range.Text
    FRDoc.Close False
    Set FRDoc = Nothing
    With ActiveDocument.Range
      .InsertBefore vbCr
      'Process each word from the List.
      For i = 0 To UBound(Split(FRList, vbCr)) - 1
        With .Duplicate
          With .Find
            .ClearFormatting
            .Replacement.ClearFormatting
            .Text = "[^13^l][!^13^l]@" & Split(FRList, vbCr)(i)
            .Replacement.Text = ""
            .Forward = True
            .Wrap = wdFindStop
            .Format = False
            .MatchWildcards = True
            .Execute
          End With
          Do While .Find.Found
            .Start = .Start + 1
            .Font.Bold = True
            .Collapse wdCollapseEnd
            .Find.Execute
          Loop
        End With
      Next
      .Characters.First.Text = vbNullString
    End With
    Application.ScreenUpdating = True
    End Sub


    Cheers
    Paul Edstein
    [MS MVP - Word]

    • Marked as answer by tthomas1977 Friday, March 7, 2014 1:33 PM
    Friday, March 7, 2014 4:11 AM

All replies

  • Generally speaking, Word doesn't work in lines; it works in paragraphs. The possible exception is if you're using manual line breaks. What constitutes a line in a paragraph in a Word document can vary according to whatever printer driver is active, even to the point of being on a different page. So, how are your lines defined?

    Cheers
    Paul Edstein
    [MS MVP - Word]

    Thursday, March 6, 2014 3:41 AM
  • Hi,

    According to your description, you want to find all the lines containing specific Strings "X" in a document and change the format of all characters before the "X" in every line.

    In fact, we could automatically find all specific Strings "X" in a several thousand pages Word document with the VBA code 1 below, and set the format of a Range which starts from 0 character to 10 character as the code 2 below. But as macropod said, there is no Line Object in Word Object Model. We could access to Paragraph and Range object. But it's difficult to define the beginning and the ending position of a line as a Range. So I'm afraid you may not achieve the goal.

    'code 1:
    Sub FindAndChangeFormat()
            Dim doc As Word.Document
    
            Dim rng As Word.Range
            Dim search As String
            search = "X"
    
            Set doc = ActiveDocument
            Set rng = doc.Range
            
            With rng.Find
                .MatchWildcards = True
                Do While .Execute(FindText:=search, Forward:=True) = True
                    rng.Bold = True
                Loop
            End With
    End Sub

    'code 2:
    Sub SetRangeFormat()
    Dim myRange As Word.Range
    Set myRange = ActiveDocument.Range(Start:=0, End:=10)
    myRange.Bold = True
    myRange.Font.ColorIndex = wdRed
    End Sub



    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Thursday, March 6, 2014 8:32 AM
    Moderator
  • My lines would be any number of random text before "X" then any number of lines until the next line that would contain a heading with a line that contains "X". Sometimes it may be a line other times it could be a page away. There is no specific format that would be easily identified other than the lines I need to change all contain "X" in them. I tried your code and it worked to find and change all "X". Is there a way to read it in 1 line at a time and then check for "X" and count to "X" then use your Code 2 to modify that range?  

    Edit:

    I was able to use a perl script and pull out all the random text that I need to modify is there a way to feed the output of that script into a search array so that any where it finds any of those strings to then change the format?

    'Code 3'

    Sub FindAndChangeFormat()
            Const ForReading = 1
            Dim doc As Word.Document
            Dim rng As Word.Range
            Dim search As String
            Set doc = ActiveDocument
            Set rng = doc.Range
            strTextFile = "C:\Scripts\words.txt"
            Set objFSO = CreateObject("Scripting.FileSystemObject")
            Set listFile = objFSO.OpenTextFile(strTextFile, ForReading)
                Do Until listFile.AtEndOfStream
                    FName = listFile.ReadLine
                        With rng.Find
                        .MatchWildcards = True
                        Do While .Execute(FindText:=FName, Forward:=True) = True
                            rng.Bold = True
                        Loop
                        End With
                Loop
    End Sub

    • Edited by tthomas1977 Thursday, March 6, 2014 7:26 PM
    Thursday, March 6, 2014 3:04 PM
  • You still haven't said how your lines are delineated. Without that information, it's hard to provide code that addresses the situation.

    Cheers
    Paul Edstein
    [MS MVP - Word]

    Thursday, March 6, 2014 10:14 PM
  • I'm not sure what you mean by delineated they have a hard return and the lines I am looking for are similar to this

    cefcFRUPSUEntry O-TYPE

    I have ran a PERL script to pull out this portion 

    cefcFRUPSUEntry

    So I now have a text file containing the thousand or so lines like the above that I need to modify. I have tried running the code posted above to change them all to bold so I can then do a search and replace on the Bolded Items to get them to the proper format I desire. As far as I know the lines are delineated with a hard return. As previously stated there may be as few as 2 lines in between the sections containing O-TYPE to several pages of other text. If I run the code above I let it sit for 3 hours and it just seems to hang Word. Is there another way to run the Code 1 Pactera above that would feed X in the search string from a text file containing all the entries that I need to modify?

    Thanks for your help so far. 

    Friday, March 7, 2014 3:20 AM
  • I'm not sure what you mean by delineated they have a hard return

    That's the delineation I was referring to. For the task of bolding lines with an 'X', you could use a macro coded as:

    Sub Demo()
    Application.ScreenUpdating = False
    Dim i As Long
    With ActiveDocument.Range
      .InsertBefore vbCr
      With .Duplicate
        With .Find
          .ClearFormatting
          .Replacement.ClearFormatting
          .Text = "[^13^l][!^13^l]@X"
          .Replacement.Text = ""
          .Forward = True
          .Wrap = wdFindStop
          .Format = False
          .MatchWildcards = True
          .Execute
        End With
        Do While .Find.Found
          i = i + 1
          .Start = .Start + 1
          .Font.Bold = True
          .Collapse wdCollapseEnd
          .Find.Execute
        Loop
      End With
      .Characters.First.Text = vbNullString
    End With
    Application.ScreenUpdating = True
    MsgBox i & " instances found."
    End Sub

    I gather you want to do more extensive formatting than just bolding the found strings. That call all be done where '.Font.Bold = True' appears.

    As for processing multiple strings, it's also possible to use Word documents, text files or Excel workbooks for the input. For example, the following code demonstrates how you might adapt the above code to use a separate Word document in which the strings to find (e.g. 'X' and 'Y') are in separate paragraphs.

    Sub BulkDemo()
    Application.ScreenUpdating = False
    Dim FRDoc As Document, FRList As String, i As Long
    'Load the strings from the reference doc into a text string to be used as an array.
    Set FRDoc = Documents.Open("Drive:\FilePath\FindReplaceList.doc", AddToRecentFiles:=False)
    FRList = FRDoc.Range.Text
    FRDoc.Close False
    Set FRDoc = Nothing
    With ActiveDocument.Range
      .InsertBefore vbCr
      'Process each word from the List.
      For i = 0 To UBound(Split(FRList, vbCr)) - 1
        With .Duplicate
          With .Find
            .ClearFormatting
            .Replacement.ClearFormatting
            .Text = "[^13^l][!^13^l]@" & Split(FRList, vbCr)(i)
            .Replacement.Text = ""
            .Forward = True
            .Wrap = wdFindStop
            .Format = False
            .MatchWildcards = True
            .Execute
          End With
          Do While .Find.Found
            .Start = .Start + 1
            .Font.Bold = True
            .Collapse wdCollapseEnd
            .Find.Execute
          Loop
        End With
      Next
      .Characters.First.Text = vbNullString
    End With
    Application.ScreenUpdating = True
    End Sub


    Cheers
    Paul Edstein
    [MS MVP - Word]

    • Marked as answer by tthomas1977 Friday, March 7, 2014 1:33 PM
    Friday, March 7, 2014 4:11 AM