将页眉与 Python - docx

Put Header with Python - docx

我正在使用 Python-docx 创建和编写 Word 文档。

如何使用 python-docx 将文本放入文档页眉?

http://image.prntscr.com/image/8757b4e6d6f545a5ab6a08a161e4c55e.png

谢谢

你可以header.text喜欢

header = section.header
header.text = 'foobar'

有关详细信息,请参阅 http://python-docx.readthedocs.io/en/latest/dev/analysis/features/header.html?highlight=header

更新:此功能自本回答时起已实施。

正如其他受访者在下面指出的那样,Section object 提供对其 header object 的访问权限。

header = document.sections[0].header

请注意,一个部分最多可以有三个 header(first_page、odd_pages、even_pages),每个部分可以有自己的一组 header秒。最常见的情况是文档只有一个 header 和一个部分。

A header 类似于文档 body 或 table 单元格,因为它可以包含 tables and/or 段落并且默认情况下有一个空段落(不能包含零个段落)。

header.paragraphs[0].text = "My header text"

文档中的此页面对此进行了更详细的解释::
https://python-docx.readthedocs.io/en/latest/user/hdrftr.html

很遗憾,此功能尚未实现。 @SamRogers 链接到的页面是增强建议的一部分(又名“分析页面”)。但是,@eupharis 正在实施,因此可能会在一个月左右的时间内可用。如果您想关注正在进行的拉取请求,请点击此处。 https://github.com/python-openxml/python-docx/pull/291

(关于这个问题是旧的...)

我在我的项目中使用了 work-around,我的 "client" 希望在不同的页面中使用不同的 header:

  1. 使用 python-docx 和分节符创建文档

  2. 执行带有两个参数的word宏文件(*.xlsm): (1) fileName = path, docTitle = 要插入页脚的文档的标题。

宏文件将打开新创建的文档并添加宏文件中已有的 header 和页脚。如果 header 和页脚文本需要变化,则需要修改。

Pyton 代码:

wd = win32com.client.Dispatch("Word.Application")
wd.Visible = False
doc = wd.Documents.Open(pathToDOCM) # path here
wd.Run("Main.RunMain",fileName, docTitle) # 2 args
doc.Close()
del wd

VBA代码:

VBA (inside *.xlsm) code:

Sub RunInside()
    Call RunMain("C:\Users\???\dokument.docx", "test")
End Sub

Sub RunMain(wordDocument As String, wordTitle As String)
    ' Create Headers
    Call CreateHeaders(wordDocument, wordTitle)
End Sub

Sub CreateHeaders(wordDocument As String, wordTitle As String)

    Dim i As Integer
    Dim outputName As String

    Dim aDoc As Document
    Dim oApp As Word.Application
    Dim oSec As Word.Section
    Dim oDoc As Word.Document

    Dim hdr1, hdr2 As HeaderFooter
    Dim ftr1, ftr2 As HeaderFooter

    'Create a new document in Word
    Set oApp = New Word.Application
    'Set oDoc = oApp.Documents.Add
    Set oDoc = oApp.Documents.Open(wordDocument)
    'Set aDoc as active document
    Set aDoc = ActiveDocument


    oDoc.BuiltInDocumentProperties("Title") = wordTitle


    For i = 1 To 9:
        Set hdr1 = aDoc.Sections(i).Headers(wdHeaderFooterPrimary)
        Set hdr2 = oDoc.Sections(i).Headers(wdHeaderFooterPrimary)

        Set ftr1 = aDoc.Sections(i).Footers(wdHeaderFooterPrimary)
        Set ftr2 = oDoc.Sections(i).Footers(wdHeaderFooterPrimary)


        If i > 1 Then
            With oDoc.Sections(i).Headers(wdHeaderFooterPrimary)
             .LinkToPrevious = False
            End With

            With oDoc.Sections(i).Footers(wdHeaderFooterPrimary)
             .LinkToPrevious = False
            End With
        End If

        hdr1.Range.Copy
        hdr2.Range.Paste

        ftr1.Range.Copy
        ftr2.Range.Paste

    Next i



    outputName = Left(wordDocument, Len(wordDocument) - 5)
    outputName = outputName + ".pdf"

    oDoc.SaveAs outputName, 17

    oDoc.Close SaveChanges:=wdSaveChanges

    Set oDoc = Nothing
    Set aDoc = Nothing

End Sub

最后的评论: 代码循环遍历不同的部分和 copy-paste header 和页脚。它还将文档保存为 *.PDF。

此功能已实现。参见:https://python-docx.readthedocs.io/en/latest/dev/analysis/features/header.html

您可以使用 python-docx 将文本添加到 word 文档的页眉,如下所示:

header = document.sections[0].header
head = header.paragraphs[0]
head.text = 'Add Your Text'

我一直在用它工作

header = document.sections[0].header
header.add_paragraph('Test Header')

Header是BlockItemContainer的子类,继承了与Document相同的内容编辑能力,如.add_paragraph().

    import docx

    document = docx.Document()

    header_section = document.sections[0]
    header = header_section.header
    header_text = header.paragraphs[0]
    header_text.text = "Header of document"

您可以使用\t文本的任一侧将其居中对齐

对于那些希望设置自定义 headers w/docx:

的人

我不得不使用几个包来让它工作。我的用例是这样的:我正在生成多个模板,然后将它们合并在一起,但是当我将它们与 docx 合并时,主文件(下方)中的 header 被应用于所有部分,并且所有部分都被标记为 linkedToPrevious = True 尽管在原始文件中是 =False。然而,docx 在附加文件并在另一端输出 error-free 方面做得非常好,所以我决定找到一种方法让它工作。代码参考:

master = Document(files[0])
composer = Composer(master)
footnotes_doc = Document('chapters/footnotes.docx')
for file in files[1:]:
    mergeDoc = Document(file)
    composer.append(mergeDoc)
composer.append(footnotes_doc)
composer.save("chapters/combined.docx")

所以现在我有了一个包含所有正确部分的主文档 (combined.docx),但是 header 需要调整。您无法使用 docx 遍历文档,获取您所在的当前部分,并对其进行调整或将 headers 链接设置为 false。如果设置为 False,则会完全擦除 header。您可以显式调用该部分并对其进行调整,但由于它之后的所有内容都链接到之前的部分,因此您可以从该点更改文档的其余部分。所以我拉入了 win32com:

获取节数,然后使用 win32com 向后遍历它们。这样,当您删除 linkedToPrevious 时,您会保留 header。

def getSections(document):
    sectionArray = {}
    sections = document.sections
    x = 1
    for section in sections:
        sectionArray[x] = section
        x += 1
    return sectionArray

start_doc = Document('chapters/combined.docx')
listArray = getSections(start_doc) #gets an array of all sections
keylist = list(reversed(sorted(listArray.keys()))) ##now reverse it

word = win32com.client.gencache.EnsureDispatch("Word.Application")
word = client.DispatchEx("Word.Application")
word.Visible = False
#tell word to open the document
word.Documents.Open(' C:\path to\combined.docx')
#open it internally
doc = word.Documents(1)

try:
    for item in keylist:
        word.ActiveDocument.Sections(item).Headers(win32com.client.constants.wdHeaderFooterPrimary).LinkToPrevious=False
        word.ActiveDocument.Sections(item).Headers(win32com.client.constants.wdHeaderFooterEvenPages).LinkToPrevious=False
    word.ActiveDocument.SaveAs("c:\wherever\combined_1.docx")
    doc.Close()
    word.Quit()
except:
    doc.Close()
    word.Quit()

好的,现在文档已准备好编辑 headers,我们现在可以使用 docx 轻松无忧地完成这些工作。首先,我们需要解析 XML,我使用 docx 访问它,然后将其提供给 lxml,以获取所需部分的位置:

xml = str(start_doc._element.xml) #this gets the full XML using docx
tree = etree.fromstring(xml)

WORD_NAMESPACE='{http://schemas.openxmlformats.org/wordprocessingml/2006/main}'
TEXT = WORD_NAMESPACE + 't'
PARA = WORD_NAMESPACE + 'p'
SECT = WORD_NAMESPACE + 'sectPr'
sectionLoc = []
for item in tree.iter(PARA):
    for node in item.iter(TEXT):
        if 'Section' in node.text: #this is how I am identifying which headers I need to edit
            print(node.text)
            sectionLoc.append(node.text)    
            
    for sect in item.iter(SECT):
        print(sect)
        sectionLoc.append('section')
        # print(etree.tostring(sect))

counter =0
sectionLocs = []
for index, item in enumerate(sectionLoc): #just some logic to get the correct section number from the xml parse
    if 'Section' in item:
        sectionLocs.append(counter)
        continue
    counter += 1

#ok now use those locations with docx to adjust the headers
#remember that start_doc here needs to be the new result from win32 process- 
#so start_doc = Document('C:\path to\combined.docx') in this case
for item in sectionLocs: 
    section = start_doc.sections[item]
    header = section.header
    para_new = header.paragraphs[0]
    para_new.text = 'TEST!'

start_doc.save('willthiswork.docx')

工作量很大。我敢打赌有一种方法可以完全用 win32com 来完成,但我无法根据页面 body 中的内容弄清楚如何获取相关部分。 “sectPr”标签总是出现在页面的末尾,所以在梳理文档的文本时,我知道页面上需要一个新的 header、“Section”,我知道下一个打印出来的部分是我要编辑的那个,所以我只得到它在列表中的位置。

我认为整个工作流程都是 hack,但它确实有效,我希望示例代码对某人有所帮助。