使用python-docx添加页码

时间:2019-06-19 01:19:06

标签: ms-word python-docx

我正在尝试使用python-docx在word doc的页脚中添加页码。到目前为止,我还没有找到方法。 This问题地址如何找到页码(或如何找到)。 This谈论创建模板并在其中添加页码。是否可以在我使用doc = Document()创建的文档上添加页码?

6 个答案:

答案 0 :(得分:3)

通过设置页脚段落的对齐方式,我可以使其显示在中间。因此,我将@max_max_mir的答案的最后几行修改为读取

doc = Document()
add_page_number(doc.sections[0].footer.paragraphs[0].add_run())
doc.sections[0].footer.paragraphs[0].alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
doc.save("your_doc.docx")

更一般而言,通过修改上面的答案,我能够在页脚中显示“ y的第x页”:

def create_element(name):
    return OxmlElement(name)


def create_attribute(element, name, value):
    element.set(nsqn(name), value)


def add_page_number(paragraph):
    paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER

    page_run = paragraph.add_run()
    t1 = create_element('w:t')
    create_attribute(t1, 'xml:space', 'preserve')
    t1.text = 'Page '
    page_run._r.append(t1)

    page_num_run = paragraph.add_run()

    fldChar1 = create_element('w:fldChar')
    create_attribute(fldChar1, 'w:fldCharType', 'begin')

    instrText = create_element('w:instrText')
    create_attribute(instrText, 'xml:space', 'preserve')
    instrText.text = "PAGE"

    fldChar2 = create_element('w:fldChar')
    create_attribute(fldChar2, 'w:fldCharType', 'end')

    page_num_run._r.append(fldChar1)
    page_num_run._r.append(instrText)
    page_num_run._r.append(fldChar2)

    of_run = paragraph.add_run()
    t2 = create_element('w:t')
    create_attribute(t2, 'xml:space', 'preserve')
    t2.text = ' of '
    of_run._r.append(t2)

    fldChar3 = create_element('w:fldChar')
    create_attribute(fldChar3, 'w:fldCharType', 'begin')

    instrText2 = create_element('w:instrText')
    create_attribute(instrText2, 'xml:space', 'preserve')
    instrText2.text = "NUMPAGES"

    fldChar4 = create_element('w:fldChar')
    create_attribute(fldChar4, 'w:fldCharType', 'end')

    num_pages_run = paragraph.add_run()
    num_pages_run._r.append(fldChar3)
    num_pages_run._r.append(instrText2)
    num_pages_run._r.append(fldChar4)

doc = Document()
add_page_number(doc.sections[0].footer.paragraphs[0])
doc.save("your_doc.docx")

答案 1 :(得分:1)

我认为添加PageNumber是一项尚未实现的功能。

但是...

  1. 如果它是现有文档,则要添加页眉和页脚 您可以调用VBA宏。我最近发布了一种方法 (https://stackoverflow.com/a/44767400/7386332
  2. 如果它是一个新文档,那么您确实可以继续创建一个 模板文档,然后将其打开并继续以 由scanny描述。
  3. 这在其文档中引用了此用例,但未演示 怎么样 https://python-docx.readthedocs.io/en/latest/dev/analysis/features/header.html?highlight=page%20number
  4. 或者您可以尝试一下 https://github.com/python-openxml/python-docx/issues/498

答案 2 :(得分:1)

页脚中的自动页码实现为字段。字段尚未在python-docx中提供API支持,因此您无法对通过默认模板(document = Document())创建的文档执行所需的操作,至少不能通过调用API来实现。

两种可能的方法是创建在页脚中已经具有页码的模板文档,然后从此处开始:

document = Document("my-template.docx")

或者创建一个变通方法,该函数使用从lxml对象(例如python-docx)获得的XML元素对象的低级paragraph._p调用来添加XML。

Syafiqur__在他的回答中提供的链接可以帮助您采用后一种方法。

答案 3 :(得分:1)

由于Syafiqur__和scanny,我想出了一种添加页码的解决方案。

def create_element(name):
    return OxmlElement(name)

def create_attribute(element, name, value):
    element.set(ns.qn(name), value)


def add_page_number(run):
    fldChar1 = create_element('w:fldChar')
    create_attribute(fldChar1, 'w:fldCharType', 'begin')

    instrText = create_element('w:instrText')
    create_attribute(instrText, 'xml:space', 'preserve')
    instrText.text = "PAGE"

    fldChar2 = create_element('w:fldChar')
    create_attribute(fldChar2, 'w:fldCharType', 'end')

    run._r.append(fldChar1)
    run._r.append(instrText)
    run._r.append(fldChar2)

doc = Document()
add_page_number(doc.sections[0].footer.paragraphs[0].add_run())
doc.save("your_doc.docx")

答案 4 :(得分:1)

谢谢 max_max_mir 和 Utkarsh Dalal。这太棒了。我做了一些更改,在这里分享给需要它的人:

  1. 设置不同的首页(封面)
  2. 从 0 开始计算页数(封面页不计算在内)
import docx
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
from docx.oxml import OxmlElement, ns

def create_element(name):
    return OxmlElement(name)
        
def create_attribute(element, name, value):
    element.set(ns.qn(name), value)
        
def add_page_number(run):
    fldStart = create_element('w:fldChar')
    create_attribute(fldStart, 'w:fldCharType', 'begin')

    instrText = create_element('w:instrText')
    create_attribute(instrText, 'xml:space', 'preserve')
    instrText.text = "PAGE"

    fldChar1 = create_element('w:fldChar')
    create_attribute(fldChar1, 'w:fldCharType', 'separate')

    fldChar2 = create_element('w:t')
    fldChar2.text = "2"

    fldEnd = create_element('w:fldChar')
    create_attribute(fldEnd, 'w:fldCharType', 'end')

    run._r.append(fldStart)

    run._r.append(instrText)
    run._r.append(fldChar1)
    run._r.append(fldChar2)

    run._r.append(fldEnd)


    add_page_number(doc.sections[0].footer.paragraphs[0].add_run())
    doc.sections[0].footer.paragraphs[0].alignment = WD_PARAGRAPH_ALIGNMENT.CENTER

    doc.sections[0].different_first_page_header_footer = True
    sectPr = doc.sections[0]._sectPr
        
    pgNumType = OxmlElement('w:pgNumType')
    pgNumType.set(ns.qn('w:start'), "0")
    sectPr.append(pgNumType)

答案 5 :(得分:0)

我没有“声誉点”来评论“Syafiqur__和scanny”max_max_mir的解决方案,所以我被迫写了一个全新的评论。鉴于复杂的 xml 解决方案,我设计了一个技巧,将我选择的文本添加到页脚,然后按照我想要的方式对齐页脚一侧的页码。

因此,我使用 run 创建页脚的文本,并使用制表符相应地对齐它。然后我调用max_max_mir的函数:

my_footer_run = footer.paragraphs[0].add_run()
my_footer_run.text = "Copyright MyCompany  All Rights Reserved.\t\t"
add_page_number(my_footer_run)

... 并且页码显示在适当的角落。在上例中,页码显示在右侧,而原始文本显示在左侧。

非常感谢原始解决方案!