1

I need to generate lots of similar one-page content in a single docx file for personal purposes, so I have created a Python script to automate that. Some of this content is a numbered list, but unfortunately, the numbering continues from page to page too, such as:


Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

1. List item1

2. List item2

Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

<--- Page break -->

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

3. List item1

4. List item2

Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.


And I want it to look like this:


Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

1. List item1

2. List item2

Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

<--- Page break -->

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

1. List item1

2. List item2

Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.


To provide more details on how my code works, let's say I have a list of pages, where it's possible to get a list of items based on the page and that's implemented in the get_items(page) function. Having the above in mind, my code currently looks something like this (I'm excluding formatting paragraphs for simplicity):

document = Document()
pages = [...]                      # list of pages
for page in pages:
    document.add_paragraph("...")  # put some regular text to the page
    items = get_items(page)
    for item in items:
        p = document.add_paragraph(item, style='List Number 2')     # 'Line Numer 2' is for some extra indent
    document.add_paragraph("...")  # put some regular text to the page
    document.add_page_break()      # add page breaks to start from a new page
document.save("...")               # save the document
1

2 Answers 2

1

My answer in python-docx restart list numbering is to explain the problem and provides two solutions.

The second solution is too complex? Well, as always in programming, the ugly, complex things have to be done somewhere. So to avoid having to do these things in the main program logic and polluting it with ugly, complex code, you should do them in subroutines.

Example:

from docx import Document
from docx.text.paragraph import Paragraph

def prepare_numberings(document: Document, style_name: str) -> int:
    #prepare the numberings to have a new numbering, which points to the same abstract numbering, 
    #the style style_name also points to but has start override set
    styles = document.styles
    #get numId to which style style_name links
    num_id_list_number = -1
    for style in styles:
        if (style.name == style_name):
            num_id_list_number = style._element.pPr.numPr.numId.val
    #add new numbering linking to same abstractNumId but has startOverride 
    #and get new numId
    num_id_list_number_new = -1
    if (num_id_list_number > -1):        
        ct_numbering = document.part.numbering_part.numbering_definitions._numbering
        ct_num = ct_numbering.num_having_numId(num_id_list_number)
        abstractNumId = ct_num.abstractNumId.val
        ct_num = ct_numbering.add_num(abstractNumId)
        num_id_list_number_new = ct_num.numId
        startOverride = ct_num.add_lvlOverride(0)._add_startOverride()
        startOverride.val = 1
    return num_id_list_number_new;
    
def set_link_to_numId(paragraph: Paragraph, num_id: int):
    if num_id > -1:
        numPr = paragraph._element.pPr._add_numPr()
        numPr._add_numId().val = num_id
    

# Main program logic

document = Document()

text_1 = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.'
text_2 = 'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'
pages = [['List 1 Item 1','List 1 Item 2'], ['List 2 Item 1','List 2 Item 2','List 2 Item 3','List 2 Item 4'], ['List 3 Item 1','List 3 Item 2','List 3 Item 3']] # list of list items in pages

for page in pages:
    document.add_paragraph(text_1) # put some regular text to the page
    #items = get_items(page)
    items = page

    #prepare the numberings to have a new numbering, which points to the same abstract numbering, 
    #the style 'List Number 2' also points to but has start override set 
    num_id_list_number_new = prepare_numberings(document, 'List Number 2')
    item_count = 0
    for item in items:
        p = document.add_paragraph(item, style='List Number 2') # 'Line Numer 2' is for some extra indent
        if item_count == 0:
            #first paragraph in new list links to new numId having startOverride
            set_link_to_numId(p, num_id_list_number_new)
        item_count += 1
         
    document.add_paragraph(text_2) # put some regular text to the page
    document.add_page_break() # add page breaks to start from a new page

document.save('test.docx')

Still too complex?

Sign up to request clarification or add additional context in comments.

1 Comment

There is no need to be passively aggressive with "Still too complex?"; I never said your solution was bad or something 🤷‍♀️. There's simply no need to do all of that code for personal purposes, there's still the counter for numbering items so it's easier for me to do it the way I did. If the project was for production then maybe your solution would be better, that's more of a correct way and probably has its advantages. The question's point was to ask if there's any direct way without referring to low-level classes. That's all.
0

As I reviewed the SO comment mentioned by DaSt, it became clear that there's no direct way to add more than 3 numbered lists in a single document with separate numbering. The abstract numbering solution seems too complex, so the simplest way I see of solving this is the following:

LEFT_INDENT = Pt(36)               # sample left indent for numbered list
document = Document()
pages = [...]                      # list of pages
for page in pages:
    document.add_paragraph("...")  # put some regular text to the page
    items = get_items(page)
    for i in range(len(items)):
        p = document.add_paragraph(f"{i + 1}. {items[i]}")
        p.paragraph_format.left_indent = LEFT_INDENT
    document.add_paragraph("...")  # put some regular text to the page
    document.add_page_break()      # add page breaks to start from a new page
document.save("...")               # save the document

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.