首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >python-docx插入点

python-docx插入点
EN

Stack Overflow用户
提问于 2014-07-25 21:50:29
回答 5查看 13K关注 0票数 9

我不确定我是否遗漏了任何显而易见的东西,但我没有发现任何文档记录了如何在文档中的某个特定位置插入Word元素(例如,表格)。

我正在通过以下方法加载现有的MS Word .docx文档:

代码语言:javascript
复制
my_document = Document('some/path/to/my/document.docx')

我的用例是获取文档中书签或节的“位置”,然后继续插入该点以下的表格。

我正在考虑一个API,它允许我做一些类似的事情:

代码语言:javascript
复制
insertion_point = my_document.bookmarks['bookmark_name'].position
my_document.add_table(rows=10, cols=3, position=insertion_point+1)

我看到有人计划实现类似MS Word API的“range”对象,这将有效地解决这个问题。同时,是否有一种方法可以指示document对象方法在哪里插入新元素?

也许我可以粘合一些lxml代码来找到一个节点并将它传递给这些python方法?在这个问题上的任何帮助都将不胜感激!谢谢。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2014-07-29 15:40:49

我记得一句古老的格言:“用源头,卢克!”,我能弄清楚。python所有者在其git项目页面上发布的一篇文章也给了我一个提示:https://github.com/python-openxml/python-docx/issues/7

可以使用its _document_part._element属性访问完整的XML文档模型。它的行为完全类似于lxml etree元素。从此,一切皆有可能。

为了解决特定的插入点问题,我创建了一个临时docx.Document对象,用于存储生成的内容。

代码语言:javascript
复制
import docx
from docx.oxml.shared import qn
tmp_doc = docx.Document()

# Generate content in tmp_doc document
tmp_doc.add_heading('New heading', 1)
# more content generation using docx API.
# ...

# Reference the tmp_doc XML content
tmp_doc_body = tmp_doc._document_part._element.body
# You could pretty print it by using:
#print(docx.oxml.xmlchemy.serialize_for_reading(tmp_doc_body))

然后我将docx模板(包含名为‘insertion_point’的书签)加载到第二个docx.Document对象中。

代码语言:javascript
复制
doc = docx.Document('/some/path/example.docx')
doc_body = doc._document_part._element.body
#print(docx.oxml.xmlchemy.serialize_for_reading(doc_body))

下一步是解析文档XML以找到插入点的索引。我为手头的任务定义了一个小函数,它返回一个命名书签父段落元素:

代码语言:javascript
复制
def get_bookmark_par_element(document, bookmark_name):
"""
Return the named bookmark parent paragraph element. If no matching
bookmark is found, the result is '1'. If an error is encountered, '2'
is returned.
"""
doc_element = document._document_part._element
bookmarks_list = doc_element.findall('.//' + qn('w:bookmarkStart'))
for bookmark in bookmarks_list:
    name = bookmark.get(qn('w:name'))
    if name == bookmark_name:
        par = bookmark.getparent()
        if not isinstance(par, docx.oxml.CT_P): 
            return 2
        else:
            return par
return 1

新定义的函数用于获取书签'insertion_point‘父段落。错误控制留给读取器。

代码语言:javascript
复制
bookmark_par = get_bookmark_par_element(doc, 'insertion_point')

现在我们可以使用bookmark_par的etree索引在正确的位置插入我们的tmp_doc生成的内容:

代码语言:javascript
复制
bookmark_par_parent = bookmark_par.getparent()
index = bookmark_par_parent.index(bookmark_par) + 1
for child in tmp_doc_body:
    bookmark_par_parent.insert(index, child)
    index = index + 1
bookmark_par_parent.remove(bookmark_par)

该文档现已定稿,生成的内容已插入到现有Word文档的书签位置。

代码语言:javascript
复制
# Save result
# print(docx.oxml.xmlchemy.serialize_for_reading(doc_body))
doc.save('/some/path/generated_doc.docx')

我希望这能对某些人有所帮助,因为有关这方面的文件仍有待编写。

票数 14
EN

Stack Overflow用户

发布于 2015-02-06 01:17:39

将图像作为标记放在模板文档中:

代码语言:javascript
复制
for paragraph in document.paragraphs:
    if "[image]" in paragraph.text:
        paragraph.text = paragraph.text.strip().replace("[image]", "")

        run = paragraph.add_run()
        run.add_picture(image_path, width=Inches(3))

在表格单元格中也有一个段落。找到牢房然后按上面的方式做。

票数 3
EN

Stack Overflow用户

发布于 2016-01-15 15:17:33

Python所有者建议如何将表插入现有文档的中间:https://github.com/python-openxml/python-docx/issues/156

以下是一些改进:

代码语言:javascript
复制
import re
from docx import Document

def move_table_after(document, table, search_phrase):
    regexp = re.compile(search_phrase)
    for paragraph in document.paragraphs:
        if paragraph.text and regexp.search(paragraph.text):
            tbl, p = table._tbl, paragraph._p
            p.addnext(tbl)
            return paragraph

if __name__ == '__main__':
    document = Document('Existing_Document.docx')    
    table = document.add_table(rows=..., cols=...)
    ...
    move_table_after(document, table, "your search phrase")                    
    document.save('Modified_Document.docx')
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24965042

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档