Создание верхнего и нижнего колонтитулов с использованием python-docx

есть ли обходной путь для добавления колонтитулов в Microsoft Word (docx файл)?

на реализация заголовок предоставил в python-docx все еще находится в разработке.

более конкретно, я хотел бы добавить:

  1. номер страницы в нижний колонтитул
  2. некоторый случайный текст в заголовки

на идеал код будет выглядеть следующим образом:

from docx import Document

document = Document()

# Add header and footer on all pages

document.save("demo.docx")

4 ответов


Как насчет чего-то подобного (благодаря Элиоту K)

from docx import Document
import win32com.client as win32
import os.path
import tempfile

tempdir = tempfile.gettempdir()
msword = win32.gencache.EnsureDispatch('Word.Application')
tempfile = os.path.join(tempdir, "temp.doc")

document = Document()

document.save(tempfile)

doc = msword.Documents.Open(tempfile)

doc.Sections(1).Footers(1).Range.Text = r'Text to be included'
doc.Sections(1).Footers(1).PageNumbers.Add()
doc.SaveAs(tempfile, FileFormat = 0)

document = Document(tempfile)

Не самый элегантный подход, возможно, но должен делать то, что вам нужно. Возможно, секвестр уродливый код сохранения / загрузки в функции где-то в пыльном углу вашего кода; -)

опять же, требуется машина windows с установленным Microsoft office.

удачи!


решение шаблона работает, но только если стиль уже после в документе.

давайте рассмотрим (упрощенную) версию примера игрушки из python-docx страница документация.

первый этап включает в себя создание шаблона документа:

from docx import Document

document = Document()

document.add_heading('Document Title', 0)

p = document.add_paragraph('A plain paragraph having some ')
p.add_run('bold').bold = True
p.add_run(' and some ')
p.add_run('italic.').italic = True

document.add_heading('Heading, level 1', level=1)
document.add_paragraph('Intense quote', style='IntenseQuote')

document.add_paragraph(
    'first item in unordered list', style='ListBullet'
)
document.add_paragraph(
    'first item in ordered list', style='ListNumber'
)

document.save('demo.docx')

(обратите внимание, что вы также можете применить стили вручную на этом первом шаге без использования python-docx, то есть изнутри слова.)

Далее вы открываете этот demo.docx в Microsoft Word, где вы:

  1. добавить нужный заголовок
  2. вставить номера страниц из меню
  3. сохранить документ

после того как вы сделали выше, вы просто удалите основное содержание demo.docx документ (но не содержание верхнего и нижнего колонтитулов!) и сохраните файл снова.

на втором шаге, вы называете demo.docx используя python-docx чтобы внести необходимые изменения:

from docx import Document

document = Document('demo.docx')

document.add_heading('A New Title for my Document', 0)

p = document.add_paragraph('A new paragraph having some plain ')
p.add_run('bold').bold = True
p.add_run(' and some ')
p.add_run('italic.').italic = True

document.add_heading('New Heading, level 1', level=1)
document.add_paragraph('Intense quote', style='IntenseQuote')

document.add_paragraph(
    'first new item in unordered list', style='ListBullet'
)
document.add_paragraph(
    'first new item in ordered list', style='ListNumber'
)

document.save('demo.docx')

вы даже можете сделать дополнительные добавления контента, такие как таблица с существующим стилем таблицы:

from docx import Document

document = Document('demo.docx')

document.add_page_break()

recordset = [ [1, "101", "Spam"], [2, "42", "Eggs"], [3, "631", "Spam, spam, eggs, and spam"]]

table = document.add_table(rows=1, cols=3)
hdr_cells = table.rows[0].cells
hdr_cells[0].text = 'Qty'
hdr_cells[1].text = 'Id'
hdr_cells[2].text = 'Desc'

for item in recordset:
    row_cells = table.add_row().cells
    row_cells[0].text = str(item[0])
    row_cells[1].text = str(item[1])
    row_cells[2].text = item[2]

table.style = 'ColorfulShading'

document.save('demo.docx')

конечно, можно избежать повторения первого шага все время, по копирование настроенного файла а затем внести необходимые изменения (например,demo_copy.docx), не затрагивая шаблон:

import shutil
shutil.copyfile('demo.docx', 'demo_copy.docx')

наконец, стоит отметить, что вы также можете использовать подгонянные стили! Для примера того, как это сделать с помощью python-docx и стили таблиц посмотреть здесь.


Это не самый элегантный (он требует навигации между VBA и Python), но вы можете использовать библиотеку win32com, чтобы подключиться к функциональности MS Word. Это конечно требует Windows машину с МС офис установлен.

import win32com.client as win32
msword = win32.gencache.EnsureDispatch('Word.Application')
doc = msword.Documents.Add
doc.Sections(1).Footers(1).Range.Text = r'Text to be included'
doc.Sections(1).Footers(1).PageNumbers.Add()

один из обходных путей, который вы можете использовать, - это использование документа шаблона, созданного в Word. Создайте пустой документ, добавьте любой заголовок с текстом, который вы хотите, и нижний колонтитул с номерами страниц и сохраните документ. Затем используйте:

from docx import Document
document = Document("template.docx")
# Do your editing
document.save("demo.docx")

... и вы должны иметь возможность редактировать все остальное, сохраняя верхний и Нижний колонтитулы.

в конечном счете, я думаю, что это решение будет отлично работать для проблемы номеров страниц. Если вам нужен уникальный текст заголовка для каждого документа может быть немного сложнее. Если это так, вы можете попробовать отредактировать XML-файл docx напрямую. Вы можете использовать это в терминале:

unzip template.docx

... чтобы получить XML-файлы docx, выплюнутые в каталог. Вы также можете использовать zipfile для этого в python:

import zipfile

document = zipfile.ZipFile("template.docx")
for xml in document.filelist:
    if "header" in xml.filename:
        read = document.read(xml.filename)
        print(read.decode())

оператор Print будет печатать весь XML-файл, но вы должны быть в состоянии найти этот лакомый кусочек:

<w:r><w:t>ThisIsMyHeader</w:t></w:r>

который будет текстом в вашем заголовке. Все, что вам нужно сделать, это отредактируйте XML-файл, объедините файлы вместе, а затем измените тип файла на docx.

это, очевидно, супер хакерский обходной путь, и, к сожалению, я не смог заставить его полностью работать, но это, по крайней мере, было бы хорошим шагом в правильном направлении, если вам это абсолютно нужно.

удачи!