locked
Skip Tables from a Macro RRS feed

  • Question

  • Hi guys,

    I have a macro that runs through an entire document to find similar formatting and mark them in different color. Macro is running fine but small issue I'm having is the time. So i decided to skip tables from the macro but when im running the macro it throws an error. Any suggestions ???


    Macro:

    Sub Test()

    Application.ScreenUpdating = False

    Dim i As Long
    With ActiveDocument
    For i = 2 To .Paragraphs.Count
    With .Paragraphs(i)

    If .Information(wdWithInTable) Then Exit For   

    If (.Range.ParagraphFormat.LeftIndent = .Previous.Range.ParagraphFormat.LeftIndent) And _
             (.Range.ParagraphFormat.Alignment = .Previous.Range.ParagraphFormat.Alignment) And _
             (.Range.Font.Size = .Previous.Range.Font.Size) And _
             (.Range.ParagraphFormat.FirstLineIndent = .Previous.Range.ParagraphFormat.FirstLineIndent) Then
            .Range.Font.Color = .Previous.Range.Font.Color
          End If
        End With
      Next
    End With
    End Sub

    Thanks...

    Tuesday, June 14, 2016 2:47 AM

Answers

  • Employing successive If tests will be far faster if there is a strong likelihood of any of the test conditions failing. And, clearly, if you're testing every paragraph to determine whether it's in a table and there are many such paragraphs, the code will quite obviously take time to perform those tests. Long document will likewise take longer to execute than short ones. Execution speed could also be enhanced by excluding the tables instead of testing whether a paragraph is within one:

    Sub Test()
    Application.ScreenUpdating = False
    Dim i As Long, j As Long, t As Long, Rng As Range
    Dim RngPrev As Range, FmtPrev As ParagraphFormat
    With ActiveDocument
      t = .Tables.Count
      For i = 1 To t
        If i = 1 Then
          Set Rng = .Range(0, Tables(i).Range.Start)
        ElseIf i = t Then
          Set Rng = .Range(Tables(i).Range.End, .Range.End)
        Else
          Set Rng = .Range(Tables(i - 1).Range.End, Tables(i).Range.Start)
        End If
        With Rng
          For j = 2 To .Paragraphs.Count
            Set RngPrev = .Paragraphs(j - 1).Range
            Set FmtPrev = RngPrev.ParagraphFormat
            With .Paragraphs(j).Range
              If .ParagraphFormat.LeftIndent = FmtPrev.LeftIndent Then
                If .ParagraphFormat.Alignment = FmtPrev.Alignment Then
                  If .ParagraphFormat.FirstLineIndent = FmtPrev.FirstLineIndent Then
                    If .Font.Size = RngPrev.Font.Size Then .Font.Color = RngPrev.Font.Color
                  End If
                End If
              End If
            End With
          Next
        End With
      Next
    End With
    Set FmtPrev = Nothing: Set RngPrev = Nothing
    Application.ScreenUpdating = True
    End Sub

    You could, of course, replace:

            With .Paragraphs(j).Range
              If .ParagraphFormat.LeftIndent = FmtPrev.LeftIndent Then
                If .ParagraphFormat.Alignment = FmtPrev.Alignment Then
                  If .ParagraphFormat.FirstLineIndent = FmtPrev.FirstLineIndent Then
                    If .Font.Size = RngPrev.Font.Size Then .Font.Color = RngPrev.Font.Color
                  End If
                End If
              End If
            End With

    with:

            With .Paragraphs(j).Range
              If (.ParagraphFormat.LeftIndent = FmtPrev.LeftIndent) And _
                (.ParagraphFormat.Alignment = FmtPrev.Alignment) And _
                (.ParagraphFormat.FirstLineIndent = FmtPrev.FirstLineIndent) And _
                (.Font.Size = RngPrev.Font.Size) Then .Font.Color = RngPrev.Font.Color
            End With


    Cheers
    Paul Edstein
    [MS MVP - Word]


    • Edited by macropodMVP Tuesday, June 14, 2016 4:52 AM Code revision
    • Marked as answer by Supunsam Tuesday, June 14, 2016 5:21 AM
    Tuesday, June 14, 2016 4:23 AM

All replies

  • The basic error in your code is that Information is a Range property:
    If .Range.Information(wdWithInTable) Then Exit For   

    As for the execution speed, it would be much faster if you:
    a) used consecutive If tests instead of combining the conditions via And; and
    b) set some references to things that will be tested repeatedly instead of repeatedly calling those objects.
    For example:

    Sub Test()
    Application.ScreenUpdating = False
    Dim i As Long, RngPrev As Range, FmtPrev As ParagraphFormat
    With ActiveDocument
      For i = 2 To .Paragraphs.Count
        Set RngPrev = .Paragraphs(i - 1).Range
        Set FmtPrev = RngPrev.ParagraphFormat
        With .Paragraphs(i).Range
          If .Information(wdWithInTable) = False Then
            If .ParagraphFormat.LeftIndent = FmtPrev.LeftIndent Then
              If .ParagraphFormat.Alignment = FmtPrev.Alignment Then
                If .ParagraphFormat.FirstLineIndent = FmtPrev.FirstLineIndent Then
                  If .Font.Size = RngPrev.Font.Size Then .Font.Color = RngPrev.Font.Color
                End If
              End If
            End If
          End If
        End With
      Next
    End With
    Set FmtPrev = Nothing: Set RngPrev = Nothing
    Application.ScreenUpdating = True
    End Sub

    Note that I've replaced your Exit For with Then; otherwise your code would exit at the first table it encountered.

    Execution speed would also be enhanced if you ordered the If tests in order of likelihood to fail.

    Finally, you might also want to test the font colour since it's impossible to use:
    If .Font.Size = RngPrev.Font.Size Then .Font.Color = RngPrev.Font.Color
    if the fonts have mixed colours - if that occurs, the colours won't be changed. You might also want to consider what to do with paragraphs using different fonts and/or font sizes. A test like:
    If .Font.Size = RngPrev.Font.Size Then
    could result in a True outcome where both paragraphs use mixed fonts & sizes but none of them is the same!


    Cheers
    Paul Edstein
    [MS MVP - Word]

    Tuesday, June 14, 2016 3:31 AM
  • Hi paul,

    Thank you very much for your suggestions. But this code takes much longer to run than the last one. Not sure whats causing this. Any way the document i'm testing this code has more than 100 pages and have 30% of tables in it.

    Tuesday, June 14, 2016 3:47 AM
  • Employing successive If tests will be far faster if there is a strong likelihood of any of the test conditions failing. And, clearly, if you're testing every paragraph to determine whether it's in a table and there are many such paragraphs, the code will quite obviously take time to perform those tests. Long document will likewise take longer to execute than short ones. Execution speed could also be enhanced by excluding the tables instead of testing whether a paragraph is within one:

    Sub Test()
    Application.ScreenUpdating = False
    Dim i As Long, j As Long, t As Long, Rng As Range
    Dim RngPrev As Range, FmtPrev As ParagraphFormat
    With ActiveDocument
      t = .Tables.Count
      For i = 1 To t
        If i = 1 Then
          Set Rng = .Range(0, Tables(i).Range.Start)
        ElseIf i = t Then
          Set Rng = .Range(Tables(i).Range.End, .Range.End)
        Else
          Set Rng = .Range(Tables(i - 1).Range.End, Tables(i).Range.Start)
        End If
        With Rng
          For j = 2 To .Paragraphs.Count
            Set RngPrev = .Paragraphs(j - 1).Range
            Set FmtPrev = RngPrev.ParagraphFormat
            With .Paragraphs(j).Range
              If .ParagraphFormat.LeftIndent = FmtPrev.LeftIndent Then
                If .ParagraphFormat.Alignment = FmtPrev.Alignment Then
                  If .ParagraphFormat.FirstLineIndent = FmtPrev.FirstLineIndent Then
                    If .Font.Size = RngPrev.Font.Size Then .Font.Color = RngPrev.Font.Color
                  End If
                End If
              End If
            End With
          Next
        End With
      Next
    End With
    Set FmtPrev = Nothing: Set RngPrev = Nothing
    Application.ScreenUpdating = True
    End Sub

    You could, of course, replace:

            With .Paragraphs(j).Range
              If .ParagraphFormat.LeftIndent = FmtPrev.LeftIndent Then
                If .ParagraphFormat.Alignment = FmtPrev.Alignment Then
                  If .ParagraphFormat.FirstLineIndent = FmtPrev.FirstLineIndent Then
                    If .Font.Size = RngPrev.Font.Size Then .Font.Color = RngPrev.Font.Color
                  End If
                End If
              End If
            End With

    with:

            With .Paragraphs(j).Range
              If (.ParagraphFormat.LeftIndent = FmtPrev.LeftIndent) And _
                (.ParagraphFormat.Alignment = FmtPrev.Alignment) And _
                (.ParagraphFormat.FirstLineIndent = FmtPrev.FirstLineIndent) And _
                (.Font.Size = RngPrev.Font.Size) Then .Font.Color = RngPrev.Font.Color
            End With


    Cheers
    Paul Edstein
    [MS MVP - Word]


    • Edited by macropodMVP Tuesday, June 14, 2016 4:52 AM Code revision
    • Marked as answer by Supunsam Tuesday, June 14, 2016 5:21 AM
    Tuesday, June 14, 2016 4:23 AM
  • Hi paul,

    Thank you very much for your time friend. Code looks great. Although when i try to run it shows an error, "Sub or Function not defined" with this part of the macro:

        If i = 1 Then
          Set Rng = .Range(0, Tables(i).Range.Start)
        ElseIf i = t Then
          Set Rng = .Range(Tables(i).Range.End, .End)
        Else
          Set Rng = .Range(Tables(i - 1).Range.End, Tables(i).Range.Start)
        End If

    What could be the problem..


    • Edited by Supunsam Tuesday, June 14, 2016 4:41 AM
    Tuesday, June 14, 2016 4:40 AM
  • I am unable to produce such an error with the code I posted. There was a different coding error (438: "object doesn't support this property or method"), though, which I've fixed. Try the revised code.

    Cheers
    Paul Edstein
    [MS MVP - Word]

    Tuesday, June 14, 2016 4:55 AM
  • Hi paul,

    Wow, It works like magic. I dont know how you do this friend. Thank you very much for this....

    Tuesday, June 14, 2016 5:22 AM