Consulting

Page 1 of 2 1 2 LastLast
Results 1 to 20 of 24

Thread: Check for end of sentence and add a full stop if missing

  1. #1

    Check for end of sentence and add a full stop if missing

    Hi,

    I check a lot of large documents and it is amazing how many people still don't put full stops at the end of a sentence.

    I want to make a macro which will search a document for the end of a paragraph, see if there is a valid end of sentence character e.g. full stop, question mark etc and if not, automatically insert a full stop.

    Any ideas where to start?

    Thanks in advance for any help....
    There are 10 types of people in the world. Those who understand binary and those that don't.

  2. #2
    VBAX Wizard
    Joined
    May 2004
    Posts
    6,713
    Location
    I check a lot of large documents and it is amazing how many people still don't put full stops at the end of a sentence.
    Are you saying these large documents are ONE paragraph, in that by full stop you mean a paragraph mark? They are using a Shift-Enter to make a new line (but the same paragraph)?

    If so, then by definition you can not have a maco searching for "the end of a paragraph", because without a "full stop" (paragraph mark), there is no end of the paragraph.

    Please clarify.

    Have you tried recording such a macro? To replace line breaks, with paragraph marks, it wouldf be something like:[vba] Selection.Find.ClearFormatting
    Selection.Find.Replacement.ClearFormatting
    With Selection.Find
    .Text = "^l"
    .Replacement.Text = "^p"
    .Forward = True
    .Wrap = wdFindContinue

    End With
    Selection.Find.Execute Replace:=wdReplaceAll[/vba]

  3. #3
    Microsoft Word MVP 2003-2009 VBAX Guru gmaxey's Avatar
    Joined
    Sep 2005
    Posts
    3,334
    Location
    It is also amazing that Word routinely mistakes abbreviations for sentence stops. See: http://gregmaxey.mvps.org/word_tip_p...sentences.html
    Greg

    Visit my website: http://gregmaxey.com

  4. #4
    Knowledge Base Approver VBAX Guru macropod's Avatar
    Joined
    Jul 2008
    Posts
    4,435
    Location
    Try:
    Sub Demo()
    Dim Para As Paragraph
    For Each Para In ActiveDocument.Paragraphs
      If Len(Para.Range.Text) > 1 Then
        If Not Para.Range.Characters.Last.Previous Like "[.!?:;]" Then
          Para.Range.Characters.Last.InsertBefore "."
        End If
      End If
    Next
    End Sub
    Last edited by macropod; 05-22-2022 at 07:23 AM.
    Cheers
    Paul Edstein
    [Fmr MS MVP - Word]

  5. #5
    Macropod - you are brilliant. So simple, but so far seems to do the job perfectly. Thank you very much

    gmaxey - cheers for the link. I had a quick look, but I will need to spend some time looking at it properly later on

    fumei - Thanks for your reponse. They are large documents with multiple paragraphs.
    There are 10 types of people in the world. Those who understand binary and those that don't.

  6. #6
    OK, I am going to be really cheeky now

    Whilst the code does work on simple text in a document, it also adds a full stop to headings, graphics etc. It also appears to be erroring when it hits the end of the first line of a table with a

    "Run-time error '5251':
    This is not a valid action for the end of a row."

    Is there anyway we can adjust the code above so that it will only apply to text in the "Normal" style? I thought this might be the easiest way to eliminate headings, graphics etc.... Or can anyone think of a better idea?
    There are 10 types of people in the world. Those who understand binary and those that don't.

  7. #7
    Knowledge Base Approver VBAX Guru macropod's Avatar
    Joined
    Jul 2008
    Posts
    4,435
    Location
    On the assumption that your in-line graphics are the only things in their paragraphs, you could try something along the lines of:
    Sub Demo()
        Dim Para As Paragraph
        For Each Para In ActiveDocument.Paragraphs
      If Len(Para.Range.Text) > 2 And Left(Para.Range.Style.NameLocal, 7) <> "Heading" Then
        If Not Para.Range.Characters.Last.Previous Like "[.!?:;]" Then
          Para.Range.Characters.Last.InsertBefore "."
        End If
      End If
        Next
    End Sub
    The above takes care of the table issue too.
    Last edited by macropod; 05-22-2022 at 07:25 AM.
    Cheers
    Paul Edstein
    [Fmr MS MVP - Word]

  8. #8
    Thanks again

    I have tweaked it a bit to include a few other styles that we would want excluded, so that is great and really helpful.

    Is there anyway that we can exclude tables altogether from the code? At the moment it is putting a full stop in all of the table headings, every column (when usually we don't want them) etc.
    There are 10 types of people in the world. Those who understand binary and those that don't.

  9. #9
    Knowledge Base Approver VBAX Guru macropod's Avatar
    Joined
    Jul 2008
    Posts
    4,435
    Location
    You could use a test like:
    If Len(.Text) > 2 And .Information(wdWithInTable) = False And Left(.Style.NameLocal, 7) <> "Heading" Then
    Cheers
    Paul Edstein
    [Fmr MS MVP - Word]

  10. #10
    This is all brilliant. I seem to have 1 final problem. I keep getting a

    "Run-time error '91':
    Object variable or With block variable not set"

    when I run it. I think it is failing on the Table of Contents. I have tried to exclude the TOC style, but it doesn't seem to make a difference.

    At the moment, the code is running on the ActiveDocument. Is there any way I can change it so that it either starts on a certain page e.g. 6 onwards or starts in the second section onwards?

    As a side note, some of my users have been creating headings in normal text and then making them look like the headings style (people just don't get styles). This code puts a full stop after these, so it is easy to see which headings contain errors.....great little spin off effect
    There are 10 types of people in the world. Those who understand binary and those that don't.

  11. #11
    Knowledge Base Approver VBAX Guru macropod's Avatar
    Joined
    Jul 2008
    Posts
    4,435
    Location
    There seems to be a measure of scope creep going on here. Try the following. I've added some efficiency enhancements:
    Sub Demo()
    Application.ScreenUpdating = False
    Dim Para As Paragraph
    On Error Resume Next
    For Each Para In ActiveDocument.Paragraphs
      With Para.Range
        If .Characters.Last.Previous.InRange(ActiveDocument.TablesOfContents(1).Range) = False Then
          If Left(.Style.NameLocal, 7) <> "Heading" Then
            If Len(.Text) > 2 Then
              If Not .Characters.Last.Previous Like "[.!?:;]" Then
                .Characters.Last.InsertBefore "."
              End If
            End If
          End If
        End If
      End With
    Next
    Application.ScreenUpdating = True
    End Sub
    Last edited by macropod; 05-22-2022 at 07:26 AM.
    Cheers
    Paul Edstein
    [Fmr MS MVP - Word]

  12. #12
    It all works great! I just added the table check and it does the job. I very much appreciate your help and time on this. Thank you.
    There are 10 types of people in the world. Those who understand binary and those that don't.

  13. #13
    VBAX Newbie
    Joined
    Mar 2014
    Posts
    1
    Location
    Hi Dr Howells, I'm trying to achieve what you have here but am unfamiliar with VBA, would you be able to post your solution here? Fundamentally I too need to scan a document and add a fullstop at the end of a paragraph of text without affecting another part of the document nor any other stsyele - in fact the paragraphs are all in a special style, "StandardCo" I'd created. If anyone else can advise, please do, there's a lot of knowledgable experts here.
    Thanks
    James

  14. #14
    Knowledge Base Approver VBAX Guru macropod's Avatar
    Joined
    Jul 2008
    Posts
    4,435
    Location
    The 'Dr Howells' solution is in post 11. Try:
    Sub Demo1()
    Application.ScreenUpdating = False
    Dim i As Long
    With ActiveDocument.Range
      With .Find
        .ClearFormatting
        .Replacement.ClearFormatting
        .Text = "^p"
        .Style = "StandardCo"
        .Replacement.Text = ""
        .Forward = True
        .Wrap = wdFindStop
        .Format = True
        .MatchWildcards = False
        .Execute
      End With
      Do While .Find.Found
        If Len(Trim(.Duplicate.Paragraphs(1).Range.Text)) > 1 Then
          If Not .Characters.Last.Previous Like "[.!?:;]" Then
            .Characters.Last.InsertBefore "."
            i = i + 1
          End If
        End If
         If .Duplicate.End = ActiveDocument.Range.End Then Exit Do
        .Collapse wdCollapseEnd
        .Find.Execute
      Loop
    End With
    Application.ScreenUpdating = True
    MsgBox i & " instances found & updated."
    End Sub
    or:
    Sub Demo2()
        Application.ScreenUpdating = False
        Dim Para As Paragraph, i As Long
        On Error Resume Next
        For Each Para In ActiveDocument.Paragraphs
            With Para.Range
                If .Style.NameLocal = "StandardCo" Then
                    If Len(Trim(.Text)) > 2 Then
                        If Not .Characters.Last.Previous Like "[.!?:;]" Then
                            i = i + 1
                            .Characters.Last.InsertBefore "."
                        End If
                    End If
                End If
            End With
        Next
        Application.ScreenUpdating = True
        MsgBox i & " instances found & updated."
    End Sub
    The first one will be faster, but won't get content terminated by table end-of-cell markers.
    Cheers
    Paul Edstein
    [Fmr MS MVP - Word]

  15. #15

    user approval ?

    Hi !
    I'm glad to have found this code (Demo2) !!!
    I adapted it to do the job for several styles in the document.
    But now, I'd like the user be asked (VbYesNOCancel) if he wants the full stop or not for each location where there is none and I tried many many things without any result
    I'm just a coder monkey...
    If someone can help me, it would be great !!!

  16. #16
    Microsoft Word MVP 2003-2009 VBAX Guru gmaxey's Avatar
    Joined
    Sep 2005
    Posts
    3,334
    Location
    Sub Demo2()
    Dim oPar As Paragraph, lngInst As Long, lngUpdate As Long
    On Error Resume Next
      For Each oPar In ActiveDocument.Paragraphs
        With oPar.Range
          If .Style.NameLocal = "Normal" Then
            If Len(Trim(.Text)) > 2 Then
              If Not .Characters.Last.Previous Like "[.!?:;]" Then
                .Characters.Last.Previous.Select
                lngInst = lngInst + 1
                Select Case MsgBox("Do you want a period here?", vbYesNoCancel, "Add Stop")
                  Case vbYes
                    .Characters.Last.InsertBefore "."
                    lngUpdate = lngUpdate + 1
                  Case vbNo
                  Case Else: Exit For
                End Select
              End If
            End If
          End If
        End With
      Next
      MsgBox lngInst & " instances found " & lngUpdate & " instances updated."
    End Sub
    Greg

    Visit my website: http://gregmaxey.com

  17. #17
    Thanks Greg !
    I'm silly, I didn't try" Select case MsgBox"... only tried "If MsgBox"...
    I'll closely compare the 2 versions of Demo2 and for sure I'll learn new things !
    Thanks again for sharing your knowledge !!!!

    Bernard

  18. #18
    I know this is a very old thread, but I have found it extremely helpful and so didn't want to start a new thread.

    I just wondered, for the code in Demo2 - is there a way to start it from a specific page onwards. I would like to achieve exactly what it achieves, but only from page 8 onwards and ignore pages 1-7 completely.

  19. #19
    Microsoft Word MVP 2003-2009 VBAX Guru gmaxey's Avatar
    Joined
    Sep 2005
    Posts
    3,334
    Location
    If you can physically put the cursor at the top of page 8 then Demo3 should work. Otherwise, use Demo4

    Sub Demo3()
    Dim oRng As Range
    Dim oPar As Paragraph, lngInst As Long, lngUpdate As Long
    On Error Resume Next
      Set oRng = ActiveDocument.Range
      oRng.Start = Selection.Range.Start
      For Each oPar In oRng.Paragraphs
        With oPar.Range
          If .Style.NameLocal = "Normal" Then
            If Len(Trim(.Text)) > 2 Then
              If Not .Characters.Last.Previous Like "[.!?:;]" Then
                .Characters.Last.Previous.Select
                lngInst = lngInst + 1
                Select Case MsgBox("Do you want a period here?", vbYesNoCancel, "Add Stop")
                  Case vbYes
                    .Characters.Last.InsertBefore "."
                    lngUpdate = lngUpdate + 1
                  Case vbNo
                  Case Else: Exit For
                End Select
              End If
            End If
          End If
        End With
      Next
      MsgBox lngInst & " instances found " & lngUpdate & " instances updated."
    End Sub
    Sub Demo4()
    Dim oRng As Range
    Dim oPar As Paragraph, lngInst As Long, lngUpdate As Long
    On Error Resume Next
      Set oRng = ActiveDocument.Range
      oRng.Collapse wdCollapseStart
      Do Until oRng.Paragraphs(1).Range.Characters.Last.Information(wdActiveEndPageNumber) = 8
        oRng.Move wdParagraph, 1
      Loop
      oRng.Select
      oRng.End = ActiveDocument.Range.End
      For Each oPar In oRng.Paragraphs
        With oPar.Range
          If .Style.NameLocal = "Normal" Then
            If Len(Trim(.Text)) > 2 Then
              If Not .Characters.Last.Previous Like "[.!?:;]" Then
                .Characters.Last.Previous.Select
                lngInst = lngInst + 1
                Select Case MsgBox("Do you want a period here?", vbYesNoCancel, "Add Stop")
                  Case vbYes
                    .Characters.Last.InsertBefore "."
                    lngUpdate = lngUpdate + 1
                  Case vbNo
                  Case Else: Exit For
                End Select
              End If
            End If
          End If
        End With
      Next
      MsgBox lngInst & " instances found " & lngUpdate & " instances updated."
    End Sub
    Greg

    Visit my website: http://gregmaxey.com

  20. #20
    VBAX Regular
    Joined
    Feb 2020
    Location
    Auckland, NZ
    Posts
    29
    Location
    How would you represent a long dash in that list of excluded characters?

    I've tried everything I can think of: copying a long dash into the sequence, adding a forward slash in front of it, putting in character codes Chr(151), ChrW(&H2014). But the macro still finds every paragraph that legitimately ends in a long dash. Even concatenating it as follows:

    If Not .Characters.Last.Previous Like "[0123456789'….,!?:*;"")" & "ChrW(&H2014)]"

    Stumped!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •