none
.Information method turns Options.Pagination on RRS feed

  • General discussion

  • When processing Word tables in VBA, I set Options.Pagination=False to improve performance. I recently exercised a bit of code which looked at Range.Information, and found that it set Pagination back to True.
    The following code illustrates the problem. I have run it in Word 2000 and 2010 with identical results:
    Sub showProblem()
        ' Set pagination False
        Application.Options.Pagination = False
        ' Confirm it is False
        Debug.Print "Options.Pagination:  " & Application.Options.Pagination
        ' Get some Information
        Debug.Print "Getting Information: " & ThisDocument.Content.Information(wdWithInTable)
        ' See that the .Information method has set Pagination to True
        Debug.Print "Options.Pagination:  " & Application.Options.Pagination
    End Sub
    
    Is this by design or a bug? If the former it should be documented. I suspect it is the latter . . .
    Tuesday, September 20, 2011 9:25 AM

All replies

  • Hi Julian

    In my opinion, this is almost certainly "by design".

    Information is a direct "conversion" from the old WordBasic SelInfo() function. WordBasic always works with the current selection. It returns information such as the current page number, current section number, etc. In order for this information to be correct, the document must be repaginated.

    If you want to avoid using Information you need to work more closely with the object model. For example, you can do something like setting a Range from the beginning of the document to the current selection. Count the number of tables in this Range. Then use InRange to check whether Selection.Range is inside the last table (Tables(Index)) in the Range from the start of the document to the current selection point. A lot more steps, but it is doable.

    Please also note that turning off Pagination is only going to have an effect if the document is in the Draft (Normal) view.


    Cindy Meister, VSTO/Word MVP
    Tuesday, September 20, 2011 10:45 AM
    Moderator
  • Hi Cindy,

    Thanks for a quick and thought-provoking reply. My initial reaction was just to switch Pagination off after each call to Information, but I thought I would run a few tests first to see what the overhead might be. I will document the results here in case anyone finds them useful. All tests were run in a blank document.

    1. Setting .pagination=true 500 (five hundred) times in a loop took just over 6 seconds. Obviously there is quite an overhead here. If Information has to set pagination, it might be similarly affected, so I ran another test:

    2. Getting Information about an empty document using this code:

    Sub benchmarkInformation()
        Dim timeStamp As Single
        timeStamp = Timer
        For i = 1 To 5000
            z = ThisDocument.Content.Information(wdWithInTable)
        Next i
        Debug.Print "Using Information: " & (Timer - timeStamp)
    End Sub

    took about 1.4 seconds. (NB this loop was five thousand - Information is not as badly affected as the first test might suggest).

    3. I already had a couple of home-grown functions which do pretty much what you suggest. Using them, the 5000-loop took about a tenth of a second.

    So the take home message for me is that .Information, while convenient, is not very efficient.

    Here is the code that runs fastest for me, just in case anyone finds it useful:

     

    Sub benchmarkBIsInTable()
        Dim timeStamp As Single
        timeStamp = Timer
        For i = 1 To 5000
            z = BWordRangeIsInTable(ThisDocument.Content, ThisDocument)
        Next i
        Debug.Print "Using BWord: " & (Timer - timeStamp)
    End Sub
    
    Public Function BWordRangeIsInTable(xRange As Range, xDoc As Document) As Boolean
        BWordRangeIsInTable = BWordRangeTableIndex(xRange, xDoc) > 0
    End Function
    Public Function BWordRangeTableIndex(xRange As Range, xDoc As Document) As Integer
        ' Return index of table containing xRange, or zero if xRange is not in a table
        Dim i As Integer
        Dim t As Table
        For i = 1 To xDoc.Tables.Count
            If xRange.InRange(xDoc.Tables(i).Range) Then
                BWordRangeTableIndex = i
                Exit Function
            End If
        Next i
    End Function
    

     

     


    • Edited by Julian Ladbury Tuesday, September 20, 2011 11:50 AM correct typo
    Tuesday, September 20, 2011 11:49 AM