Search code examples
pythonms-wordpywin32pywin

Use pywin32 to go to specified page in word doc


I have a long word document with over 100 tables. I am trying to allow users to select a page number via python to enter data into the table on the specified page within the word document. I am able to enter data into a table with the following code, but the problem is that the document is so long, it's not easy for a user to know which table number they are on when they are 80 pages into the word document (not every page has a table and some pages have multiple tables).

import win32com.client as win32    
word = win32.Dispatch("Word.Application")
word.Documents.Open(my_document_path)
doc = word.ActiveDocument
table = doc.Tables(51) #random selection for testing purposes
table.Cell(Row = 7, Column = 2).Range.Text = "test"

So what I need help with is extracting the table number on a page in a word document that is specified via user input (i.e., user specifies that they want to add data to page 13 so the code will determine that table 51 is on page 72).

If I record a macro in word for simply jumping to a page, this is the VB code...

Selection.GoTo What:=wdGoToPage, Which:=wdGoToNext, Name:="13"

I have tried translating this into Python using the following line of code, but it's not jumping to the correct page.

doc.GoTo(win32.constants.wdGoToPage, win32.constants.wdGoToNext, "13")

Solution

  • GoTo works with the Selection object, which is a property of the Word application, not a document. In the code in the question, word represents the Word application, so word.Selection.GoTo should work.

    Note the subsitution of wdGoToAbsolute in the GoTo method call for wdGoToNext - that's "safer" for going to a specific page number.

    In order to get the entire Range for a page it's possible to use a built-in bookmark name "\Page". This only works for the page where the selection is, which is why it's necessary to first go to the page. It's then possible to get the first table (or any other table index) on the page.

    If the index number of the table in the document is also required, that can be calculated by getting the document's range, then setting the end-point to the end of the page's range.

    import win32com.client as win32    
    word = win32.Dispatch("Word.Application")
    word.Documents.Open(my_document_path)
    doc = word.ActiveDocument
    word.Selection.GoTo(win32.constants.wdGoToPage, win32.constants.wdGoToAbsolute, "13")
    rngPage = doc.Bookmarks("\Page").Range
    table = rngPage.Tables(1) #first table on the page
    table.Cell(Row = 7, Column = 2).Range.Text = "test"
    
    #rngToPage = doc.Content
    #rngToPage.End = rngPage.End
    #tableIndex = rngToPage.Tables.Count
    

    Note that I don't work with Python, so I'm not able to test the Python code. So watch out for syntax errors. For this reason, I've appended the VBA code I used to test the approach.

    Sub GetTableCountOnPage()
        Dim tbl As Word.Table
        Dim sPage As String
        Dim rngPage As Word.Range
    
        sPage = InputBox("On which page is the table?")
        Selection.GoTo What:=wdGoToPage, Name:=sPage
        Set rngPage = Selection.Document.Bookmarks("\Page").Range
        If rngPage.Tables.Count > 0 Then
            Set tbl = rngPage.Tables(1)
            tbl.Select
    
            Dim rngToTable As Word.Range
            Set rngToTable = Selection.Document.content
            rngToTable.End = rngPage.End
            Debug.Print rngToTable.Tables.Count & " to this point."
        End If
    End Sub