Мне нужно сгенерировать много похожего одностраничного контента в одном файле docx для личных целей, поэтому я создал скрипт Python для автоматизации этого. Часть этого контента представляет собой пронумерованный список, но, к сожалению, нумерация продолжается и от страницы к странице, например:
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut Labore et dolore magna aliqua. Ut enim реклама minim veniam, quis nostrum упражнения ullamco Laboris Nisi ut aliquip ex ea commodo consequat.
1. Элемент списка1
2. Элемент списка2
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum долоре eu fugiat nulla pariatur. За исключением sint occaecat cupidatat non гордый, сун в culpa qui officia deserunt mollit anim id est трудум.
<--- Разрыв страницы -->
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut Labore et dolore magna aliqua. Ut enim реклама minim veniam, quis nostrum упражнения ullamco Laboris Nisi ut aliquip ex ea commodo consequat.
3. Элемент списка1
4. Элемент списка2
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum долоре eu fugiat nulla pariatur. За исключением sint occaecat cupidatat non гордый, сун в culpa qui officia deserunt mollit anim id est трудум.
И я хочу, чтобы это выглядело так:
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut Labore et dolore magna aliqua. Ut enim реклама minim veniam, quis nostrum упражнения ullamco Laboris Nisi ut aliquip ex ea commodo consequat.
1. Элемент списка1
2. Элемент списка2
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum долоре eu fugiat nulla pariatur. За исключением sint occaecat cupidatat non гордый, сун в culpa qui officia deserunt mollit anim id est трудум.
<--- Разрыв страницы -->
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut Labore et dolore magna aliqua. Ut enim реклама minim veniam, quis nostrum упражнения ullamco Laboris Nisi ut aliquip ex ea commodo consequat.
1. Элемент списка1
2. Элемент списка2
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum долоре eu fugiat nulla pariatur. За исключением sint occaecat cupidatat non гордый, сун в culpa qui officia deserunt mollit anim id est трудум.
Чтобы предоставить более подробную информацию о том, как работает мой код, предположим, что у меня есть список страниц, из которого можно получить список элементов на основе страницы, и это реализовано в функции get_items(page). Учитывая вышесказанное, мой код в настоящее время выглядит примерно так (для простоты я исключаю абзацы форматирования):
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
@ДаСт, спасибо!
Когда я просмотрел комментарий SO, упомянутый DaSt, стало ясно, что нет прямого способа добавить более трех нумерованных списков в один документ с отдельной нумерацией. Решение абстрактной нумерации кажется слишком сложным, поэтому самый простой способ решения этой проблемы, который я вижу, заключается в следующем:
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
Мой ответ в нумерации списка перезапуска python-docx заключается в том, чтобы объяснить проблему и предложить два решения.
Второе решение слишком сложное? Ну, как всегда в программировании, самые уродливые и сложные вещи нужно где-то делать. Поэтому, чтобы избежать необходимости делать эти вещи в основной логике программы и засорять ее уродливым и сложным кодом, вам следует делать это в подпрограммах.
Пример:
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')
Все еще слишком сложно?
Нет необходимости быть пассивно-агрессивным с вопросом «Все еще слишком сложно?»; Я никогда не говорил, что ваше решение плохое или что-то в этом роде 🤷♀️. Просто нет необходимости делать весь этот код для личных целей, все равно есть счетчик нумерации элементов, поэтому мне проще сделать так, как я сделал. Если бы проект был производственным, то, возможно, ваше решение было бы лучше, это более правильный путь и, вероятно, имело свои преимущества. Суть вопроса заключалась в том, чтобы спросить, есть ли какой-нибудь прямой путь без ссылки на классы низкого уровня. Вот и все.
Взгляните на этот комментарий: stackoverflow.com/a/78685353